From 89cd3d8a8a8ac72e0ca190ff63cf17b714e6c093 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Sun, 26 Sep 2010 02:29:42 +0000 Subject: [PATCH 001/333] Added patch from Daniel Trebbien [SVN r65593] --- doc/table_of_contents.html | 4 +++- example/stoer_wagner.cpp | 3 ++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/doc/table_of_contents.html b/doc/table_of_contents.html index 8c0783f98..da03f48e8 100644 --- a/doc/table_of_contents.html +++ b/doc/table_of_contents.html @@ -208,9 +208,11 @@

Table of Contents: the Boost Graph Library
  • boykov_kolmogorov_max_flow
  • edmonds_maximum_cardinality_matching + +
  • Minimum Cut Algorithms +
    1. stoer_wagner_min_cut
    -
  • Sparse Matrix Ordering Algorithms
    1. #include +#include #include #include #include @@ -19,7 +20,7 @@ struct edge_t unsigned long second; }; -// A graphic of the min-cut is available at +// A graphic of the min-cut is available at int main() { using namespace std; From 7b97cbf3935d2003fcc43f81592d3c47f6ba9830 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Fri, 8 Oct 2010 17:32:57 +0000 Subject: [PATCH 002/333] Fixed const issue on VC++ 8; fixes #4715 [SVN r65836] --- include/boost/graph/named_function_params.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/boost/graph/named_function_params.hpp b/include/boost/graph/named_function_params.hpp index 47535fbda..e08c5c4c5 100644 --- a/include/boost/graph/named_function_params.hpp +++ b/include/boost/graph/named_function_params.hpp @@ -392,8 +392,8 @@ BOOST_BGL_DECLARE_NAMED_PARAMS template struct override_const_property_t { - typedef ArgType result_type; - result_type operator()(const Graph&, const typename boost::add_reference::type a) const {return a;} + typedef typename boost::remove_const::type result_type; + result_type operator()(const Graph&, const ArgType& a) const {return a;} }; template From adc6eb0f0d93c54df73f825c3fd3cc0b8abf5681 Mon Sep 17 00:00:00 2001 From: Andrew Sutton Date: Wed, 13 Oct 2010 13:47:23 +0000 Subject: [PATCH 003/333] Clarifying references to MST in Dijkstra's SP algorithm. [SVN r65939] --- doc/dijkstra_shortest_paths.html | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/doc/dijkstra_shortest_paths.html b/doc/dijkstra_shortest_paths.html index ac991c794..a62790a69 100644 --- a/doc/dijkstra_shortest_paths.html +++ b/doc/dijkstra_shortest_paths.html @@ -248,9 +248,10 @@

      Named Parameters

      OUT: predecessor_map(PredecessorMap p_map)
      - The predecessor map records the edges in the minimum spanning - tree. Upon completion of the algorithm, the edges (p[u],u) - for all u in V are in the minimum spanning tree. If p[u] = + The predecessor map records the edges in the search tree, the tree computed + by the traversal of the graph. Upon completion of the algorithm, the edges + (p[u],u) for all u in V are in the search tree. The search + tree is not guaranteed to be a minimum spanning tree. If p[u] = u then u is either the source vertex or a vertex that is not reachable from the source. The PredecessorMap type must be a Date: Thu, 14 Oct 2010 18:58:00 +0000 Subject: [PATCH 004/333] Fixed documentation of distance map; fixes #4737 [SVN r65963] --- doc/prim_minimum_spanning_tree.html | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/doc/prim_minimum_spanning_tree.html b/doc/prim_minimum_spanning_tree.html index 371a7a70e..c42d1e7ff 100644 --- a/doc/prim_minimum_spanning_tree.html +++ b/doc/prim_minimum_spanning_tree.html @@ -197,11 +197,10 @@

      Named Parameters

      UTIL/OUT: distance_map(DistanceMap d_map)
      - The shortest path weight from the source vertex s to each - vertex in the graph g is recorded in this property map. The - shortest path weight is the sum of the edge weights along the - shortest path. The type DistanceMap must be a model of - g is recorded in this property map, with edges + directed away from the spanning tree root. + The type DistanceMap must be a model of Read/Write Property Map. The vertex descriptor type of the graph needs to be usable as the key type of the distance map. The From 7ba05ec48762257cd028ec68a4405b9d0d355dec Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Thu, 14 Oct 2010 19:02:03 +0000 Subject: [PATCH 005/333] Clarified docs further; fixes #4731 [SVN r65964] --- doc/dijkstra_shortest_paths.html | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/doc/dijkstra_shortest_paths.html b/doc/dijkstra_shortest_paths.html index a62790a69..40f55c0d6 100644 --- a/doc/dijkstra_shortest_paths.html +++ b/doc/dijkstra_shortest_paths.html @@ -248,9 +248,12 @@

      Named Parameters

      OUT: predecessor_map(PredecessorMap p_map)
      - The predecessor map records the edges in the search tree, the tree computed + The predecessor map records the edges in the shortest path tree, the tree computed by the traversal of the graph. Upon completion of the algorithm, the edges - (p[u],u) for all u in V are in the search tree. The search + (p[u],u) for all u in V are in the tree. The shortest path + from vertex s to each vertex v in the graph consists of the + vertices v, p[v], p[p[v]], and so on until s is + reached, in reverse order. The tree is not guaranteed to be a minimum spanning tree. If p[u] = u then u is either the source vertex or a vertex that is not reachable from the source. The PredecessorMap type From 61d37fe7430ff182191ce64fcfe2909a7551674f Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Tue, 19 Oct 2010 15:46:00 +0000 Subject: [PATCH 006/333] Repeating edge insertions (up to a limit) when they fail in generate_random_graph; fixes #4758 [SVN r66097] --- include/boost/graph/random.hpp | 29 +++++++++++++++++++++++++---- 1 file changed, 25 insertions(+), 4 deletions(-) diff --git a/include/boost/graph/random.hpp b/include/boost/graph/random.hpp index c79c9c68f..7e1d65969 100644 --- a/include/boost/graph/random.hpp +++ b/include/boost/graph/random.hpp @@ -125,6 +125,7 @@ namespace boost { bool self_edges = false) { typedef graph_traits Traits; + typedef typename Traits::edge_descriptor edge_t; typedef typename Traits::vertices_size_type v_size_t; typedef typename Traits::edges_size_type e_size_t; typedef typename Traits::vertex_descriptor vertex_descriptor; @@ -149,12 +150,23 @@ namespace boost { for (v_size_t i = 0; i < V; ++i) add_vertex(g); - for (e_size_t j = 0; j < E; ++j) { + e_size_t not_inserted_counter = 0; /* Number of edge insertion failures */ + e_size_t num_vertices_squared = num_vertices(g) * num_vertices(g); + for (e_size_t j = 0; j < E; /* Increment in body */) { vertex_descriptor a = random_vertex(g, gen), b; do { b = random_vertex(g, gen); } while (self_edges == false && a == b); - add_edge(a, b, g); + edge_t e; bool inserted; + boost::tie(e, inserted) = add_edge(a, b, g); + if (inserted) { + ++j; + } else { + ++not_inserted_counter; + } + if (not_inserted_counter >= num_vertices_squared) { + return; /* Rather than looping forever on complete graph */ + } } } } @@ -191,15 +203,24 @@ namespace boost { for (v_size_t i = 0; i < V; ++i) *vertex_out++ = add_vertex(g); - for (e_size_t j = 0; j < E; ++j) { + e_size_t not_inserted_counter = 0; /* Number of edge insertion failures */ + e_size_t num_vertices_squared = num_vertices(g) * num_vertices(g); + for (e_size_t j = 0; j < E; /* Increment in body */) { vertex_t a = random_vertex(g, gen), b; do { b = random_vertex(g, gen); } while (self_edges == false && a == b); edge_t e; bool inserted; boost::tie(e, inserted) = add_edge(a, b, g); - if (inserted) + if (inserted) { *edge_out++ = std::make_pair(source(e, g), target(e, g)); + ++j; + } else { + ++not_inserted_counter; + } + if (not_inserted_counter >= num_vertices_squared) { + return; /* Rather than looping forever on complete graph */ + } } } From 24a2de892f61abd700da218c499ac8b269bf669a Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Tue, 19 Oct 2010 15:55:27 +0000 Subject: [PATCH 007/333] Fixed remove_edge_if and clear_vertex for subgraphs; commented out remove_vertex; refs #4752; fixes #4753 [SVN r66098] --- include/boost/graph/subgraph.hpp | 32 ++++++++++++++++++++++++++------ 1 file changed, 26 insertions(+), 6 deletions(-) diff --git a/include/boost/graph/subgraph.hpp b/include/boost/graph/subgraph.hpp index 093da7b03..33f67a406 100644 --- a/include/boost/graph/subgraph.hpp +++ b/include/boost/graph/subgraph.hpp @@ -677,17 +677,35 @@ remove_edge(typename subgraph::edge_descriptor e, subgraph& g) } } -// TODO: This is wrong... +// This is slow, but there may not be a good way to do it safely otherwise template void -remove_edge_if(Predicate p, subgraph& g) -{ remove_edge_if(p, g.m_graph); } +remove_edge_if(Predicate p, subgraph& g) { + while (true) { + bool any_removed = false; + typedef typename subgraph::edge_iterator ei_type; + for (std::pair ep = edges(g); + ep.first != ep.second; ++ep.first) { + if (p(*ep.first)) { + any_removed = true; + remove_edge(*ep.first, g); + continue; /* Since iterators may be invalidated */ + } + } + if (!any_removed) break; + } +} -// TODO: Ths is wrong template void -clear_vertex(typename subgraph::vertex_descriptor v, subgraph& g) -{ clear_vertex(v, g.m_graph); } +clear_vertex(typename subgraph::vertex_descriptor v, subgraph& g) { + while (true) { + typedef typename subgraph::out_edge_iterator oei_type; + std::pair p = out_edges(v, g); + if (p.first == p.second) break; + remove_edge(*p.first, g); + } +} namespace detail { template @@ -727,10 +745,12 @@ add_vertex(subgraph& g) } +#if 0 // TODO: Under Construction template void remove_vertex(typename subgraph::vertex_descriptor u, subgraph& g) { assert(false); } +#endif //=========================================================================== // Functions required by the PropertyGraph concept From 822fc80494c1db9e2857f415df72cec1e7890fc3 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Tue, 19 Oct 2010 16:00:15 +0000 Subject: [PATCH 008/333] Merged patch from #4631 and made appropriate doc changes; fixes #4631 [SVN r66099] --- doc/r_c_shortest_paths.html | 4 ++-- include/boost/graph/r_c_shortest_paths.hpp | 12 ++++++++---- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/doc/r_c_shortest_paths.html b/doc/r_c_shortest_paths.html index cc5fd260f..9964e3fec 100755 --- a/doc/r_c_shortest_paths.html +++ b/doc/r_c_shortest_paths.html @@ -446,11 +446,11 @@

      Parameters

      OUT: std::vector<typename graph_traits<Graph>::edge_descriptor>& pareto_optimal_solution
      -A container for storing the first Pareto-optimal (undominated) solution (s-t-path) in the overloads where only one Pareto-optimal solution is returned. The path is returned as a sequence of edge descriptors in reverse order (from t to s). +A container for storing the first Pareto-optimal (undominated) solution (s-t-path) in the overloads where only one Pareto-optimal solution is returned. The path is returned as a sequence of edge descriptors in reverse order (from t to s). This argument is not modified if there are no solutions.
      OUT: Resource_Container& pareto_optimal_resource_container
      -A Resource_Container object for storing the Pareto-optimal resource container corresponding to the first Pareto-optimal path in the overloads where only one Pareto-optimal solution is returned. +A Resource_Container object for storing the Pareto-optimal resource container corresponding to the first Pareto-optimal path in the overloads where only one Pareto-optimal solution is returned. This argument is not modified if there are no solutions.
      IN: const Resource_Container& rc
      diff --git a/include/boost/graph/r_c_shortest_paths.hpp b/include/boost/graph/r_c_shortest_paths.hpp index 37bf3f347..9d395799e 100644 --- a/include/boost/graph/r_c_shortest_paths.hpp +++ b/include/boost/graph/r_c_shortest_paths.hpp @@ -559,8 +559,10 @@ void r_c_shortest_paths dominance, la, vis ); - pareto_optimal_solution = pareto_optimal_solutions[0]; - pareto_optimal_resource_container = pareto_optimal_resource_containers[0]; + if (!pareto_optimal_solutions.empty()) { + pareto_optimal_solution = pareto_optimal_solutions[0]; + pareto_optimal_resource_container = pareto_optimal_resource_containers[0]; + } } // third overload: @@ -644,8 +646,10 @@ void r_c_shortest_paths dominance, default_r_c_shortest_paths_allocator(), default_r_c_shortest_paths_visitor() ); - pareto_optimal_solution = pareto_optimal_solutions[0]; - pareto_optimal_resource_container = pareto_optimal_resource_containers[0]; + if (!pareto_optimal_solutions.empty()) { + pareto_optimal_solution = pareto_optimal_solutions[0]; + pareto_optimal_resource_container = pareto_optimal_resource_containers[0]; + } } // r_c_shortest_paths From a3786d7f7e77af5301ac91abb39765334bf4487b Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Tue, 26 Oct 2010 18:24:01 +0000 Subject: [PATCH 009/333] Repaired copy_component() using suggestion from Christopher Alfeld; fixes #4793 [SVN r66203] --- include/boost/graph/copy.hpp | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/include/boost/graph/copy.hpp b/include/boost/graph/copy.hpp index 402e75f24..970166d5c 100644 --- a/include/boost/graph/copy.hpp +++ b/include/boost/graph/copy.hpp @@ -350,15 +350,28 @@ namespace boost { : g_out(graph), orig2copy(c), copy_vertex(cv), copy_edge(ce) { } template - void examine_vertex(Vertex u, const Graph& g_in) const { + typename graph_traits::vertex_descriptor copy_one_vertex(Vertex u, const Graph& g_in) const { typename graph_traits::vertex_descriptor new_u = add_vertex(g_out); put(orig2copy, u, new_u); copy_vertex(u, new_u); + return new_u; } template - void examine_edge(Edge e, const Graph& g_in) const { + void tree_edge(Edge e, const Graph& g_in) const { + // For a tree edge, the target vertex has not been copied yet. + typename graph_traits::edge_descriptor new_e; + bool inserted; + boost::tie(new_e, inserted) = add_edge(get(orig2copy, source(e, g_in)), + this->copy_one_vertex(target(e, g_in), g_in), + g_out); + copy_edge(e, new_e); + } + + template + void non_tree_edge(Edge e, const Graph& g_in) const { + // For a non-tree edge, the target vertex has already been copied. typename graph_traits::edge_descriptor new_e; bool inserted; boost::tie(new_e, inserted) = add_edge(get(orig2copy, source(e, g_in)), @@ -387,8 +400,10 @@ namespace boost { { graph_copy_visitor vis(g_out, orig2copy, copy_vertex, copy_edge); + typename graph_traits::vertex_descriptor src_copy + = vis.copy_one_vertex(src); breadth_first_search(g_in, src, params.visitor(vis)); - return get(orig2copy, src); + return src_copy; } } // namespace detail From 55dec7c0795d87fcebad1b547a66211507303442 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Tue, 26 Oct 2010 18:37:29 +0000 Subject: [PATCH 010/333] Fixed signature of copy_one_vertex(); refs #4793 [SVN r66204] --- include/boost/graph/copy.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/boost/graph/copy.hpp b/include/boost/graph/copy.hpp index 970166d5c..8ef01238c 100644 --- a/include/boost/graph/copy.hpp +++ b/include/boost/graph/copy.hpp @@ -350,7 +350,7 @@ namespace boost { : g_out(graph), orig2copy(c), copy_vertex(cv), copy_edge(ce) { } template - typename graph_traits::vertex_descriptor copy_one_vertex(Vertex u, const Graph& g_in) const { + typename graph_traits::vertex_descriptor copy_one_vertex(Vertex u) const { typename graph_traits::vertex_descriptor new_u = add_vertex(g_out); put(orig2copy, u, new_u); @@ -364,7 +364,7 @@ namespace boost { typename graph_traits::edge_descriptor new_e; bool inserted; boost::tie(new_e, inserted) = add_edge(get(orig2copy, source(e, g_in)), - this->copy_one_vertex(target(e, g_in), g_in), + this->copy_one_vertex(target(e, g_in)), g_out); copy_edge(e, new_e); } From 11187e5a25a96a8374e4c7e2cd9fad45f649f6b8 Mon Sep 17 00:00:00 2001 From: Daniel James Date: Sat, 30 Oct 2010 14:32:50 +0000 Subject: [PATCH 011/333] Link fixes. [SVN r66273] --- doc/random_spanning_tree.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/random_spanning_tree.html b/doc/random_spanning_tree.html index 15d4ac3e7..e6d82f48a 100644 --- a/doc/random_spanning_tree.html +++ b/doc/random_spanning_tree.html @@ -76,7 +76,7 @@

      Parameters

      A random number generator. The generator type must be a model of Uniform + href="../../../doc/html/boost_random/reference.html#boost_random.reference.concepts.uniform_random_number_generator">Uniform Random Number Generator or a pointer or reference to such a type.
      From 7d02f7dd6b0650f41606d761112cb1a32992df74 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Sat, 30 Oct 2010 20:16:17 +0000 Subject: [PATCH 012/333] Applied patch from Daniel Trebbien [SVN r66286] --- include/boost/graph/read_dimacs.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/boost/graph/read_dimacs.hpp b/include/boost/graph/read_dimacs.hpp index b19c81392..4e82f84ed 100644 --- a/include/boost/graph/read_dimacs.hpp +++ b/include/boost/graph/read_dimacs.hpp @@ -90,7 +90,7 @@ int read_dimacs_max_flow_internal(Graph& g, const int EN20 = 19; const int EN22 = 20; - static char *err_message[] = + static const char *err_message[] = { /* 0*/ "more than one problem line.", /* 1*/ "wrong number of parameters in the problem line.", From f5b408ef7fa5107d636e9bdc635918a2c316f4a3 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Fri, 12 Nov 2010 15:34:20 +0000 Subject: [PATCH 013/333] Removed access to (unused) edge id attribute, also making that attribute optional; fixes #4843 [SVN r66528] --- src/graphml.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/graphml.cpp b/src/graphml.cpp index 87cab74ca..3571b06fe 100644 --- a/src/graphml.cpp +++ b/src/graphml.cpp @@ -92,7 +92,6 @@ class graphml_reader // Search for edges BOOST_FOREACH(const ptree::value_type& edge, *gr) { if (edge.first != "edge") continue; - std::string id = edge.second.get(path("/id")); std::string source = edge.second.get(path("/source")); std::string target = edge.second.get(path("/target")); std::string local_directed = edge.second.get(path("/directed"), ""); From a934539462176f4375a012d1689bc45498432957 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Sat, 13 Nov 2010 15:04:24 +0000 Subject: [PATCH 014/333] Fixed typo; fixes #4851 [SVN r66559] --- doc/file_dependency_example.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/file_dependency_example.html b/doc/file_dependency_example.html index c600b74c9..fed8ef6a1 100644 --- a/doc/file_dependency_example.html +++ b/doc/file_dependency_example.html @@ -211,7 +211,7 @@

      the time slot must be one more than the maximum time-slot of the files it depends on. -

      We start be creating a vector time that will store the +

      We start by creating a vector time that will store the time step at which each file can be built. We initialize every value with time step zero.

      From 8e365de48806365415eda1b0194f8738d934bcc4 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Wed, 24 Nov 2010 01:23:42 +0000 Subject: [PATCH 015/333] Applied patch from #4887 -- thank you for the bug report and patch; fixes #4887 [SVN r66707] --- include/boost/graph/clustering_coefficient.hpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/include/boost/graph/clustering_coefficient.hpp b/include/boost/graph/clustering_coefficient.hpp index 15574f041..d897d94b5 100644 --- a/include/boost/graph/clustering_coefficient.hpp +++ b/include/boost/graph/clustering_coefficient.hpp @@ -37,8 +37,8 @@ namespace detail template inline typename graph_traits::degree_size_type count_edges(const Graph& g, - typename Graph::vertex_descriptor u, - typename Graph::vertex_descriptor v, + typename graph_traits::vertex_descriptor u, + typename graph_traits::vertex_descriptor v, directed_tag) { @@ -51,8 +51,8 @@ namespace detail template inline typename graph_traits::degree_size_type count_edges(const Graph& g, - typename Graph::vertex_descriptor u, - typename Graph::vertex_descriptor v, + typename graph_traits::vertex_descriptor u, + typename graph_traits::vertex_descriptor v, undirected_tag) { function_requires< AdjacencyMatrixConcept >(); From fb567057dfc3a0019b63a71fab66181ebb146f37 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Tue, 30 Nov 2010 17:48:33 +0000 Subject: [PATCH 016/333] Fixed bundled graph properties in filtered_graph; fixes #4914 [SVN r66900] --- include/boost/graph/filtered_graph.hpp | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/include/boost/graph/filtered_graph.hpp b/include/boost/graph/filtered_graph.hpp index 764b2d7d1..66cead609 100644 --- a/include/boost/graph/filtered_graph.hpp +++ b/include/boost/graph/filtered_graph.hpp @@ -233,6 +233,13 @@ namespace boost { typedef typename edge_property_type::type type; }; + template + struct graph_property_type > { + typedef typename graph_property_type::type type; + }; + #ifndef BOOST_GRAPH_NO_BUNDLED_PROPERTIES template @@ -244,6 +251,11 @@ namespace boost { struct edge_bundle_type > : edge_bundle_type { }; + + template + struct graph_bundle_type > + : graph_bundle_type { }; #endif // BOOST_GRAPH_NO_BUNDLED_PROPERTIES //=========================================================================== From 6c48845da834cf90123450f85d4d7bc23689ed65 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Tue, 30 Nov 2010 18:16:29 +0000 Subject: [PATCH 017/333] Fixed up computation of property types; fixes #1021 [SVN r66907] --- include/boost/graph/properties.hpp | 2 +- include/boost/graph/reverse_graph.hpp | 23 +++++++++++------------ 2 files changed, 12 insertions(+), 13 deletions(-) diff --git a/include/boost/graph/properties.hpp b/include/boost/graph/properties.hpp index fa8440e93..7225ebbd9 100644 --- a/include/boost/graph/properties.hpp +++ b/include/boost/graph/properties.hpp @@ -266,7 +266,7 @@ namespace boost { class graph_property { public: typedef typename property_value< - typename Graph::graph_property_type, Property + typename boost::graph_property_type::type, Property >::type type; }; diff --git a/include/boost/graph/reverse_graph.hpp b/include/boost/graph/reverse_graph.hpp index 60de2b0ee..30d303b19 100644 --- a/include/boost/graph/reverse_graph.hpp +++ b/include/boost/graph/reverse_graph.hpp @@ -79,16 +79,6 @@ class reverse_graph { typedef reverse_graph_tag graph_tag; - // Graph, vertex, and edge properties - typedef typename graph_property_type::type graph_property_type; - typedef typename graph_bundle_type::type graph_bundled; - - typedef typename vertex_property_type::type vertex_property_type; - typedef typename vertex_bundle_type::type vertex_bundled; - - typedef typename edge_property_type::type edge_property_type; - typedef typename edge_bundle_type::type edge_bundled; - #ifndef BOOST_GRAPH_NO_BUNDLED_PROPERTIES // Bundled properties support template @@ -101,10 +91,10 @@ class reverse_graph { operator[](Descriptor x) const { return m_g[x]; } - graph_bundled& operator[](graph_bundle_t) + typename boost::graph_property_type::type& operator[](graph_bundle_t) { return get_property(*this); } - graph_bundled const& operator[](graph_bundle_t) const + typename boost::graph_property_type::type const& operator[](graph_bundle_t) const { return get_property(*this); } #endif // BOOST_GRAPH_NO_BUNDLED_PROPERTIES @@ -128,6 +118,11 @@ struct edge_property_type > { typedef typename boost::edge_property_type::type type; }; +template +struct graph_property_type > { + typedef typename boost::graph_property_type::type type; +}; + #ifndef BOOST_GRAPH_NO_BUNDLED_PROPERTIES template struct vertex_bundle_type > @@ -136,6 +131,10 @@ struct edge_property_type > { template struct edge_bundle_type > : edge_bundle_type { }; + + template + struct graph_bundle_type > + : graph_bundle_type { }; #endif // BOOST_GRAPH_NO_BUNDLED_PROPERTIES template From db812aa773dc18fc6efafc98ab344dd25203e1d4 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Wed, 1 Dec 2010 20:15:41 +0000 Subject: [PATCH 018/333] Fixed complexity of Dijkstra's algorithm; fixes #4852 [SVN r66960] --- doc/dijkstra_shortest_paths.html | 2 +- doc/dijkstra_shortest_paths_no_color_map.html | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/dijkstra_shortest_paths.html b/doc/dijkstra_shortest_paths.html index 40f55c0d6..4ed19711f 100644 --- a/doc/dijkstra_shortest_paths.html +++ b/doc/dijkstra_shortest_paths.html @@ -390,7 +390,7 @@

      Named Parameters

      Complexity

      -The time complexity is O(V log V). +The time complexity is O(V log V + E).

      Visitor Event Points

      diff --git a/doc/dijkstra_shortest_paths_no_color_map.html b/doc/dijkstra_shortest_paths_no_color_map.html index c08cc57e0..e1cc1c8ec 100644 --- a/doc/dijkstra_shortest_paths_no_color_map.html +++ b/doc/dijkstra_shortest_paths_no_color_map.html @@ -322,7 +322,7 @@

      Named Parameters

      Complexity

      -The time complexity is O(V log V). +The time complexity is O(V log V + E).

      Visitor Event Points

      From 9bcc1b9a690251e3a2e08133b8f45aa43cd99aa2 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Sat, 4 Dec 2010 20:31:33 +0000 Subject: [PATCH 019/333] Changed to Boost.Filesystem v3 [SVN r67008] --- test/all_planar_input_files_test.cpp | 11 ++++++----- test/parallel_edges_loops_test.cpp | 9 ++++----- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/test/all_planar_input_files_test.cpp b/test/all_planar_input_files_test.cpp index b0d5289da..ff9aabdec 100644 --- a/test/all_planar_input_files_test.cpp +++ b/test/all_planar_input_files_test.cpp @@ -18,6 +18,8 @@ This test needs to be linked against Boost.Filesystem. */ +#define BOOST_FILESYSTEM_VERSION 3 + #include #include #include @@ -264,20 +266,19 @@ int test_main(int argc, char* argv[]) << std::endl; filesystem::path input_directory = - filesystem::system_complete - (filesystem::path(input_directory_str, filesystem::native)); - const std::string dimacs_suffix = ".dimacs"; + filesystem::system_complete(filesystem::path(input_directory_str)); + const std::string dimacs_extension = ".dimacs"; filesystem::directory_iterator dir_end; for( filesystem::directory_iterator dir_itr(input_directory); dir_itr != dir_end; ++dir_itr) { - if (!ends_with(dir_itr->string(), dimacs_suffix)) + if (dir_itr->path().extension() != dimacs_extension) continue; std::cout << "Testing " << dir_itr->path().leaf() << "... "; - BOOST_REQUIRE (test_graph(dir_itr->string()) == 0); + BOOST_REQUIRE (test_graph(dir_itr->path().string()) == 0); std::cout << std::endl; } diff --git a/test/parallel_edges_loops_test.cpp b/test/parallel_edges_loops_test.cpp index 27ccf3ec8..a6ab1cbcc 100644 --- a/test/parallel_edges_loops_test.cpp +++ b/test/parallel_edges_loops_test.cpp @@ -340,20 +340,19 @@ int test_main(int argc, char* argv[]) << std::endl; filesystem::path input_directory = - filesystem::system_complete - (filesystem::path(input_directory_str, filesystem::native)); - const std::string dimacs_suffix = ".dimacs"; + filesystem::system_complete(filesystem::path(input_directory_str)); + const std::string dimacs_extension = ".dimacs"; filesystem::directory_iterator dir_end; for( filesystem::directory_iterator dir_itr(input_directory); dir_itr != dir_end; ++dir_itr) { - if (!ends_with(dir_itr->string(), dimacs_suffix)) + if (dir_itr->path().extension() != dimacs_extension) continue; std::cerr << "Testing " << dir_itr->path().leaf() << "... "; - BOOST_REQUIRE (test_graph(dir_itr->string()) == 0); + BOOST_REQUIRE (test_graph(dir_itr->path().string()) == 0); std::cerr << std::endl; } From e8640715469af51368af69a0380ff35c8bb03714 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Sat, 4 Dec 2010 20:39:00 +0000 Subject: [PATCH 020/333] Put in more checks to avoid seg faults [SVN r67010] --- test/graphviz_test.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/graphviz_test.cpp b/test/graphviz_test.cpp index 5ff2f80b6..765175df1 100644 --- a/test/graphviz_test.cpp +++ b/test/graphviz_test.cpp @@ -97,6 +97,7 @@ bool test_graph(std::istream& dotfile, std::size_t correct_num_vertices, std::string node_name = get(name,*i); // - get its mass float node_mass = get(mass,*i); + BOOST_CHECK(masses.find(node_name) != masses.end()); float ref_mass = masses.find(node_name)->second; // - compare the mass to the result in the table BOOST_CHECK_CLOSE(node_mass, ref_mass, 0.01f); @@ -114,6 +115,7 @@ bool test_graph(std::istream& dotfile, std::size_t correct_num_vertices, get(name, target(*i,graph))); // - get its weight double edge_weight = get(weight,*i); + BOOST_CHECK(weights.find(edge_name) != weights.end()); double ref_weight = weights.find(edge_name)->second; // - compare the weight to teh result in the table BOOST_CHECK_CLOSE(edge_weight, ref_weight, 0.01); From 904b4cc92439e7c2b2d3804bc2499b91196edfd7 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Sat, 4 Dec 2010 20:45:09 +0000 Subject: [PATCH 021/333] Forcing filesystem version 3 [SVN r67011] --- test/parallel_edges_loops_test.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/parallel_edges_loops_test.cpp b/test/parallel_edges_loops_test.cpp index a6ab1cbcc..42cd77fc5 100644 --- a/test/parallel_edges_loops_test.cpp +++ b/test/parallel_edges_loops_test.cpp @@ -16,6 +16,8 @@ This test needs to be linked against Boost.Filesystem. */ +#define BOOST_FILESYSTEM_VERSION 3 + #include #include #include From cc07f4c20198fa7722224233a06b6ecef6c0676e Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Sat, 4 Dec 2010 20:45:42 +0000 Subject: [PATCH 022/333] Moved #define up [SVN r67012] --- test/stoer_wagner_test.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/stoer_wagner_test.cpp b/test/stoer_wagner_test.cpp index 1fc4332b7..b2820e5c2 100644 --- a/test/stoer_wagner_test.cpp +++ b/test/stoer_wagner_test.cpp @@ -3,6 +3,7 @@ // (See accompanying file LICENSE_1_0.txt or the copy at // http://www.boost.org/LICENSE_1_0.txt) +#define BOOST_TEST_DYN_LINK 1 #include #include #include @@ -16,7 +17,6 @@ #include #include #include -#define BOOST_TEST_DYN_LINK 1 #include #include From 10b41afc0f98e03f36861bae913922fda5d3d660 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Sat, 4 Dec 2010 20:49:49 +0000 Subject: [PATCH 023/333] Fixed uninitialized variables [SVN r67014] --- include/boost/graph/stoer_wagner_min_cut.hpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/include/boost/graph/stoer_wagner_min_cut.hpp b/include/boost/graph/stoer_wagner_min_cut.hpp index 9cd2d0da0..39375467e 100644 --- a/include/boost/graph/stoer_wagner_min_cut.hpp +++ b/include/boost/graph/stoer_wagner_min_cut.hpp @@ -74,7 +74,8 @@ namespace boost { assert(pq.size() >= 2); - vertex_descriptor s, t; + vertex_descriptor s = boost::graph_traits::null_vertex(); + vertex_descriptor t = boost::graph_traits::null_vertex(); weight_type w; while (!pq.empty()) { // while PQ \neq {} do const vertex_descriptor u = pq.top(); // u = extractmax(PQ) From 086a94c8a5c1fd5d755fb8968135445832ec99b6 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Sun, 5 Dec 2010 20:17:48 +0000 Subject: [PATCH 024/333] Applied patch from Matthias Walter [SVN r67031] --- include/boost/graph/bipartite.hpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/include/boost/graph/bipartite.hpp b/include/boost/graph/bipartite.hpp index f902fd3e7..b917c607e 100644 --- a/include/boost/graph/bipartite.hpp +++ b/include/boost/graph/bipartite.hpp @@ -212,8 +212,6 @@ namespace boost { depth_first_search (graph, vertex_index_map (index_map).visitor (make_dfs_visitor (std::make_pair ( detail::colorize_bipartition (partition_map), std::make_pair (detail::check_bipartition (partition_map), put_property (partition_map, color_traits ::white (), on_start_vertex ())))))); - - // depth_first_search (graph, vertex_index_map (index_map).visitor (dfs_visitor)); } catch (detail::bipartite_visitor_error error) { @@ -284,11 +282,9 @@ namespace boost { typedef std::vector predecessors_t; typedef iterator_property_map predecessor_map_t; - typedef predecessor_recorder predecessor_recorder_t; predecessors_t predecessors (num_vertices (graph), graph_traits ::null_vertex ()); predecessor_map_t predecessor_map (predecessors.begin (), index_map); - predecessor_recorder_t predecessor_recorder (predecessor_map); /// Initialize predecessor map for (boost::tie (vertex_iter, vertex_end) = vertices (graph); vertex_iter != vertex_end; ++vertex_iter) From b76015210d84da3cb12f91a44d2544f5990b752e Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Sun, 5 Dec 2010 20:24:28 +0000 Subject: [PATCH 025/333] Turned off VC++ auto-linking [SVN r67033] --- test/stoer_wagner_test.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/test/stoer_wagner_test.cpp b/test/stoer_wagner_test.cpp index b2820e5c2..b53e87c7d 100644 --- a/test/stoer_wagner_test.cpp +++ b/test/stoer_wagner_test.cpp @@ -4,6 +4,7 @@ // http://www.boost.org/LICENSE_1_0.txt) #define BOOST_TEST_DYN_LINK 1 +#define BOOST_TEST_NO_LIB 1 #include #include #include From ff1775df186066e76f56e8613ce765f34724c541 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Sun, 5 Dec 2010 20:38:44 +0000 Subject: [PATCH 026/333] Removed and a few more uses of it; fixes #4642 [SVN r67035] --- example/bfs-example.cpp | 2 +- example/bfs-example2.cpp | 2 +- example/dfs-example.cpp | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/example/bfs-example.cpp b/example/bfs-example.cpp index 20e3b8da9..0f340ccf2 100644 --- a/example/bfs-example.cpp +++ b/example/bfs-example.cpp @@ -8,7 +8,7 @@ #include #include #include -#include +#include #include diff --git a/example/bfs-example2.cpp b/example/bfs-example2.cpp index 8225327ec..d7cb2dd23 100644 --- a/example/bfs-example2.cpp +++ b/example/bfs-example2.cpp @@ -8,7 +8,7 @@ #include #include #include -#include +#include #include diff --git a/example/dfs-example.cpp b/example/dfs-example.cpp index 017053de7..efb2b57e5 100644 --- a/example/dfs-example.cpp +++ b/example/dfs-example.cpp @@ -7,7 +7,7 @@ //======================================================================= #include #include -#include +#include #include #include From 2e5db3d02609514e66e7420d0d07096b711586ff Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Sun, 5 Dec 2010 20:39:59 +0000 Subject: [PATCH 027/333] Testing more example codes [SVN r67038] --- example/Jamfile.v2 | 3 +++ 1 file changed, 3 insertions(+) diff --git a/example/Jamfile.v2 b/example/Jamfile.v2 index c85df0ca4..fa7ebf9d6 100644 --- a/example/Jamfile.v2 +++ b/example/Jamfile.v2 @@ -30,3 +30,6 @@ exe ospf-example : ospf-example.cpp ../build//boost_graph ; exe implicit_graph : implicit_graph.cpp ; exe astar_maze : astar_maze.cpp ; exe stoer_wagner : stoer_wagner.cpp ; +exe bfs-example : bfs-example.cpp ; +exe bfs-example2 : bfs-example2.cpp ; +exe dfs-example : dfs-example.cpp ; From 4000bccb3dc8ed91d346f06b0dbb1dc101476616 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Sun, 5 Dec 2010 20:43:45 +0000 Subject: [PATCH 028/333] Fixed typo [SVN r67040] --- doc/fruchterman_reingold.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/fruchterman_reingold.html b/doc/fruchterman_reingold.html index f8a61d6d6..f0ea6bd95 100644 --- a/doc/fruchterman_reingold.html +++ b/doc/fruchterman_reingold.html @@ -216,7 +216,7 @@

      Named Parameters

      Complexity

      The time complexity is O(|V|2 + |E|) for each -iteration of the algorithm in the worse case. The average case for the +iteration of the algorithm in the worst case. The average case for the grid variant is O(|V| + |E|). The number of iterations is determined by the cooling schedule. From 0415ceffe02b82573606529e06f53a15f93100dd Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Mon, 6 Dec 2010 18:20:16 +0000 Subject: [PATCH 029/333] Removed dynamic linking to Boost.Test [SVN r67069] --- test/stoer_wagner_test.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/stoer_wagner_test.cpp b/test/stoer_wagner_test.cpp index b53e87c7d..7a1f64f7f 100644 --- a/test/stoer_wagner_test.cpp +++ b/test/stoer_wagner_test.cpp @@ -3,7 +3,7 @@ // (See accompanying file LICENSE_1_0.txt or the copy at // http://www.boost.org/LICENSE_1_0.txt) -#define BOOST_TEST_DYN_LINK 1 +// #define BOOST_TEST_DYN_LINK 1 #define BOOST_TEST_NO_LIB 1 #include #include From 595b9abbdc3df48738fa809498f2c896920d9916 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Tue, 7 Dec 2010 17:20:55 +0000 Subject: [PATCH 030/333] Simplified code for VC++ 7.1 [SVN r67084] --- include/boost/graph/named_function_params.hpp | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/include/boost/graph/named_function_params.hpp b/include/boost/graph/named_function_params.hpp index e08c5c4c5..092eead8c 100644 --- a/include/boost/graph/named_function_params.hpp +++ b/include/boost/graph/named_function_params.hpp @@ -584,14 +584,16 @@ BOOST_BGL_DECLARE_NAMED_PARAMS g_hasQ = (parameter_exists ::value)); + typedef boost::reference_wrapper int_refw; + typedef typename boost::parameter::value_type< + ArgPack, + PriorityQueueTag, + int_refw + >::type::type + param_value_type; + typedef typename boost::remove_const::type param_value_type_no_const; typedef priority_queue_maker_helper - >::type::type - >::type> helper; + param_value_type_no_const> helper; typedef typename helper::priority_queue_type priority_queue_type; static priority_queue_type make_queue(const Graph& g, const ArgPack& ap, KeyT defaultKey) { From f132fd060f52a66f30f7b6c8742274b72cd2d2a5 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Tue, 7 Dec 2010 17:35:24 +0000 Subject: [PATCH 031/333] Using incantation from Boost.Math (test_laplace.cpp) to try to get Boost.Test linking to work [SVN r67086] --- test/Jamfile.v2 | 2 +- test/stoer_wagner_test.cpp | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 5e01a4e39..e0cb54ac6 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -120,7 +120,7 @@ test-suite graph_test : [ run incremental_components_test.cpp ] [ run random_spanning_tree_test.cpp ../build//boost_graph ] [ run graphml_test.cpp ../build//boost_graph : : "graphml_test.xml" ] - [ run stoer_wagner_test.cpp ../../test/build : $(TEST_DIR) ] + [ run stoer_wagner_test.cpp ../../test/build//boost_unit_test_framework/static : $(TEST_DIR) ] ; # Run SDB tests only when -sSDB= is set. diff --git a/test/stoer_wagner_test.cpp b/test/stoer_wagner_test.cpp index 7a1f64f7f..112bf495c 100644 --- a/test/stoer_wagner_test.cpp +++ b/test/stoer_wagner_test.cpp @@ -3,8 +3,6 @@ // (See accompanying file LICENSE_1_0.txt or the copy at // http://www.boost.org/LICENSE_1_0.txt) -// #define BOOST_TEST_DYN_LINK 1 -#define BOOST_TEST_NO_LIB 1 #include #include #include From 4a5c105654dad0911920193c740e1c0b6ee82daf Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Wed, 8 Dec 2010 18:11:52 +0000 Subject: [PATCH 032/333] Applied patch from #4966 to fix self-loop insertion; fixes #4966 [SVN r67110] --- include/boost/graph/subgraph.hpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/include/boost/graph/subgraph.hpp b/include/boost/graph/subgraph.hpp index 33f67a406..fa5ec45ef 100644 --- a/include/boost/graph/subgraph.hpp +++ b/include/boost/graph/subgraph.hpp @@ -346,7 +346,7 @@ add_vertex(typename subgraph::vertex_descriptor u_global, subgraph& g) { assert(!g.is_root()); - typename subgraph::vertex_descriptor u_local, v_global, uu_global; + typename subgraph::vertex_descriptor u_local, v_global; typename subgraph::edge_descriptor e_global; u_local = add_vertex(g.m_graph); @@ -371,11 +371,13 @@ add_vertex(typename subgraph::vertex_descriptor u_global, typename subgraph::out_edge_iterator ei, ei_end; for(boost::tie(vi, vi_end) = vertices(r); vi != vi_end; ++vi) { v_global = *vi; - if(g.find_vertex(v_global).second) + if (v_global == u_global) + continue; // don't insert self loops twice! + if (!g.find_vertex(v_global).second) + continue; // not a subgraph vertex => try next one for(boost::tie(ei, ei_end) = out_edges(*vi, r); ei != ei_end; ++ei) { e_global = *ei; - uu_global = target(e_global, r); - if(uu_global == u_global && g.find_vertex(v_global).second) { + if(target(e_global, r) == u_global) { g.local_add_edge(g.global_to_local(v_global), u_local, e_global); } } From 6fb2f7edec8cd563a71278e238daf5be73f691d2 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Thu, 6 Jan 2011 01:51:16 +0000 Subject: [PATCH 033/333] Removed deprecated file [SVN r67703] --- include/boost/graph/kolmogorov_max_flow.hpp | 814 -------------------- 1 file changed, 814 deletions(-) delete mode 100644 include/boost/graph/kolmogorov_max_flow.hpp diff --git a/include/boost/graph/kolmogorov_max_flow.hpp b/include/boost/graph/kolmogorov_max_flow.hpp deleted file mode 100644 index c2b94c094..000000000 --- a/include/boost/graph/kolmogorov_max_flow.hpp +++ /dev/null @@ -1,814 +0,0 @@ -// Copyright (c) 2006, Stephan Diederich -// -// This code may be used under either of the following two licences: -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or -// sell copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. OF SUCH DAMAGE. -// -// Or: -// -// 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_KOLMOGOROV_MAX_FLOW_HPP -#define BOOST_KOLMOGOROV_MAX_FLOW_HPP - -#if defined(_MSC_VER) || defined(__BORLANDC__) || defined(__DMC__) -# pragma message ("The kolmogorov_max_flow.hpp header is deprecated and will be removed in Boost 1.46. Use boykov_kolmogorov_max_flow.hpp instead.") -#elif defined(__GNUC__) || defined(__HP_aCC) || defined(__SUNPRO_CC) || defined(__IBMCPP__) -# warning "The kolmogorov_max_flow.hpp header is deprecated and will be removed in Boost 1.46. Use boykov_kolmogorov_max_flow.hpp instead." -#endif - -#include -#include -#include -#include -#include -#include -#include // for std::min and std::max - -#include -#include -#include -#include -#include -#include -#include - -namespace boost { - namespace detail { - - template - class kolmogorov{ - typedef typename property_traits::value_type tEdgeVal; - typedef graph_traits tGraphTraits; - typedef typename tGraphTraits::vertex_iterator vertex_iterator; - typedef typename tGraphTraits::vertex_descriptor vertex_descriptor; - typedef typename tGraphTraits::edge_descriptor edge_descriptor; - typedef typename tGraphTraits::edge_iterator edge_iterator; - typedef typename tGraphTraits::out_edge_iterator out_edge_iterator; - typedef boost::queue tQueue; //queue of vertices, used in adoption-stage - typedef typename property_traits::value_type tColorValue; - typedef color_traits tColorTraits; - typedef typename property_traits::value_type tDistanceVal; - - public: - kolmogorov(Graph& g, - EdgeCapacityMap cap, - ResidualCapacityEdgeMap res, - ReverseEdgeMap rev, - PredecessorMap pre, - ColorMap color, - DistanceMap dist, - IndexMap idx, - vertex_descriptor src, - vertex_descriptor sink): - m_g(g), - m_index_map(idx), - m_cap_map(cap), - m_res_cap_map(res), - m_rev_edge_map(rev), - m_pre_map(pre), - m_tree_map(color), - m_dist_map(dist), - m_source(src), - m_sink(sink), - m_active_nodes(), - m_in_active_list_vec(num_vertices(g), false), - m_in_active_list_map(make_iterator_property_map(m_in_active_list_vec.begin(), m_index_map)), - m_has_parent_vec(num_vertices(g), false), - m_has_parent_map(make_iterator_property_map(m_has_parent_vec.begin(), m_index_map)), - m_time_vec(num_vertices(g), 0), - m_time_map(make_iterator_property_map(m_time_vec.begin(), m_index_map)), - m_flow(0), - m_time(1), - m_last_grow_vertex(graph_traits::null_vertex()){ - // initialize the color-map with gray-values - vertex_iterator vi, v_end; - for(boost::tie(vi, v_end) = vertices(m_g); vi != v_end; ++vi){ - set_tree(*vi, tColorTraits::gray()); - } - // Initialize flow to zero which means initializing - // the residual capacity equal to the capacity - edge_iterator ei, e_end; - for(boost::tie(ei, e_end) = edges(m_g); ei != e_end; ++ei) { - m_res_cap_map[*ei] = m_cap_map[*ei]; - assert(m_rev_edge_map[m_rev_edge_map[*ei]] == *ei); //check if the reverse edge map is build up properly - } - //init the search trees with the two terminals - set_tree(m_source, tColorTraits::black()); - set_tree(m_sink, tColorTraits::white()); - m_time_map[m_source] = 1; - m_time_map[m_sink] = 1; - } - - ~kolmogorov(){} - - tEdgeVal max_flow(){ - //augment direct paths from SOURCE->SINK and SOURCE->VERTEX->SINK - augment_direct_paths(); - //start the main-loop - while(true){ - bool path_found; - edge_descriptor connecting_edge; - boost::tie(connecting_edge, path_found) = grow(); //find a path from source to sink - if(!path_found){ - //we're finished, no more paths were found - break; - } - ++m_time; - augment(connecting_edge); //augment that path - adopt(); //rebuild search tree structure - } - return m_flow; - } - - //the complete class is protected, as we want access to members in derived test-class (see $(BOOST_ROOT)/libs/graph/test/kolmogorov_max_flow_test.cpp) - protected: - void augment_direct_paths(){ - //in a first step, we augment all direct paths from source->NODE->sink - //and additionally paths from source->sink - //this improves especially graphcuts for segmentation, as most of the nodes have source/sink connects - //but shouldn't have an impact on other maxflow problems (this is done in grow() anyway) - out_edge_iterator ei, e_end; - for(boost::tie(ei, e_end) = out_edges(m_source, m_g); ei != e_end; ++ei){ - edge_descriptor from_source = *ei; - vertex_descriptor current_node = target(from_source, m_g); - if(current_node == m_sink){ - tEdgeVal cap = m_res_cap_map[from_source]; - m_res_cap_map[from_source] = 0; - m_flow += cap; - continue; - } - edge_descriptor to_sink; - bool is_there; - boost::tie(to_sink, is_there) = lookup_edge(current_node, m_sink, m_g); - if(is_there){ - tEdgeVal cap_from_source = m_res_cap_map[from_source]; - tEdgeVal cap_to_sink = m_res_cap_map[to_sink]; - if(cap_from_source > cap_to_sink){ - set_tree(current_node, tColorTraits::black()); - add_active_node(current_node); - set_edge_to_parent(current_node, from_source); - m_dist_map[current_node] = 1; - m_time_map[current_node] = 1; - //add stuff to flow and update residuals - //we dont need to update reverse_edges, as incoming/outgoing edges to/from source/sink don't count for max-flow - m_res_cap_map[from_source] -= cap_to_sink; - m_res_cap_map[to_sink] = 0; - m_flow += cap_to_sink; - } else if(cap_to_sink > 0){ - set_tree(current_node, tColorTraits::white()); - add_active_node(current_node); - set_edge_to_parent(current_node, to_sink); - m_dist_map[current_node] = 1; - m_time_map[current_node] = 1; - //add stuff to flow and update residuals - //we dont need to update reverse_edges, as incoming/outgoing edges to/from source/sink don't count for max-flow - m_res_cap_map[to_sink] -= cap_from_source; - m_res_cap_map[from_source] = 0; - m_flow += cap_from_source; - } - } else if(m_res_cap_map[from_source]){ - //there is no sink connect, so we can't augment this path - //but to avoid adding m_source to the active nodes, we just activate this node and set the approciate things - set_tree(current_node, tColorTraits::black()); - set_edge_to_parent(current_node, from_source); - m_dist_map[current_node] = 1; - m_time_map[current_node] = 1; - add_active_node(current_node); - } - } - for(boost::tie(ei, e_end) = out_edges(m_sink, m_g); ei != e_end; ++ei){ - edge_descriptor to_sink = m_rev_edge_map[*ei]; - vertex_descriptor current_node = source(to_sink, m_g); - if(m_res_cap_map[to_sink]){ - set_tree(current_node, tColorTraits::white()); - set_edge_to_parent(current_node, to_sink); - m_dist_map[current_node] = 1; - m_time_map[current_node] = 1; - add_active_node(current_node); - } - } - } - - /** - * returns a pair of an edge and a boolean. if the bool is true, the edge is a connection of a found path from s->t , read "the link" and - * source(returnVal, m_g) is the end of the path found in the source-tree - * target(returnVal, m_g) is the beginning of the path found in the sink-tree - */ - std::pair grow(){ - assert(m_orphans.empty()); - vertex_descriptor current_node; - while((current_node = get_next_active_node()) != graph_traits::null_vertex()){ //if there is one - assert(get_tree(current_node) != tColorTraits::gray() && (has_parent(current_node) || current_node==m_source || current_node==m_sink)); - if(get_tree(current_node) == tColorTraits::black()){ - //source tree growing - out_edge_iterator ei, e_end; - if(current_node != m_last_grow_vertex){ - m_last_grow_vertex = current_node; - boost::tie(m_last_grow_edge_it, m_last_grow_edge_end) = out_edges(current_node, m_g); - } - for(; m_last_grow_edge_it != m_last_grow_edge_end; ++m_last_grow_edge_it){ - edge_descriptor out_edge = *m_last_grow_edge_it; - if(m_res_cap_map[out_edge] > 0){ //check if we have capacity left on this edge - vertex_descriptor other_node = target(out_edge, m_g); - if(get_tree(other_node) == tColorTraits::gray()){ //it's a free node - set_tree(other_node, tColorTraits::black()); //aquire other node to our search tree - set_edge_to_parent(other_node, out_edge); //set us as parent - m_dist_map[other_node] = m_dist_map[current_node] + 1; //and update the distance-heuristic - m_time_map[other_node] = m_time_map[current_node]; - add_active_node(other_node); - } else if(get_tree(other_node) == tColorTraits::black()){ - if(is_closer_to_terminal(current_node, other_node)){ //we do this to get shorter paths. check if we are nearer to the source as its parent is - set_edge_to_parent(other_node, out_edge); - m_dist_map[other_node] = m_dist_map[current_node] + 1; - m_time_map[other_node] = m_time_map[current_node]; - } - } else{ - assert(get_tree(other_node)==tColorTraits::white()); - //kewl, found a path from one to the other search tree, return the connecting edge in src->sink dir - return std::make_pair(out_edge, true); - } - } - } //for all out-edges - } //source-tree-growing - else{ - assert(get_tree(current_node) == tColorTraits::white()); - out_edge_iterator ei, e_end; - if(current_node != m_last_grow_vertex){ - m_last_grow_vertex = current_node; - boost::tie(m_last_grow_edge_it, m_last_grow_edge_end) = out_edges(current_node, m_g); - } - for(; m_last_grow_edge_it != m_last_grow_edge_end; ++m_last_grow_edge_it){ - edge_descriptor in_edge = m_rev_edge_map[*m_last_grow_edge_it]; - if(m_res_cap_map[in_edge] > 0){ //check if there is capacity left - vertex_descriptor other_node = source(in_edge, m_g); - if(get_tree(other_node) == tColorTraits::gray()){ //it's a free node - set_tree(other_node, tColorTraits::white()); //aquire that node to our search tree - set_edge_to_parent(other_node, in_edge); //set us as parent - add_active_node(other_node); //activate that node - m_dist_map[other_node] = m_dist_map[current_node] + 1; //set its distance - m_time_map[other_node] = m_time_map[current_node]; //and time - } else if(get_tree(other_node) == tColorTraits::white()){ - if(is_closer_to_terminal(current_node, other_node)){ - //we are closer to the sink than its parent is, so we "adopt" him - set_edge_to_parent(other_node, in_edge); - m_dist_map[other_node] = m_dist_map[current_node] + 1; - m_time_map[other_node] = m_time_map[current_node]; - } - } else{ - assert(get_tree(other_node)==tColorTraits::black()); - //kewl, found a path from one to the other search tree, return the connecting edge in src->sink dir - return std::make_pair(in_edge, true); - } - } - } //for all out-edges - } //sink-tree growing - //all edges of that node are processed, and no more paths were found. so remove if from the front of the active queue - finish_node(current_node); - } //while active_nodes not empty - return std::make_pair(edge_descriptor(), false); //no active nodes anymore and no path found, we're done - } - - /** - * augments path from s->t and updates residual graph - * source(e, m_g) is the end of the path found in the source-tree - * target(e, m_g) is the beginning of the path found in the sink-tree - * this phase generates orphans on satured edges, if the attached verts are from different search-trees - * orphans are ordered in distance to sink/source. first the farest from the source are front_inserted into the orphans list, - * and after that the sink-tree-orphans are front_inserted. when going to adoption stage the orphans are popped_front, and so we process the nearest - * verts to the terminals first - */ - void augment(edge_descriptor e){ - assert(get_tree(target(e, m_g)) == tColorTraits::white()); - assert(get_tree(source(e, m_g)) == tColorTraits::black()); - assert(m_orphans.empty()); - - const tEdgeVal bottleneck = find_bottleneck(e); - //now we push the found flow through the path - //for each edge we saturate we have to look for the verts that belong to that edge, one of them becomes an orphans - //now process the connecting edge - m_res_cap_map[e] -= bottleneck; - assert(m_res_cap_map[e] >= 0); - m_res_cap_map[m_rev_edge_map[e]] += bottleneck; - - //now we follow the path back to the source - vertex_descriptor current_node = source(e, m_g); - while(current_node != m_source){ - edge_descriptor pred = get_edge_to_parent(current_node); - m_res_cap_map[pred] -= bottleneck; - assert(m_res_cap_map[pred] >= 0); - m_res_cap_map[m_rev_edge_map[pred]] += bottleneck; - if(m_res_cap_map[pred] == 0){ - set_no_parent(current_node); - m_orphans.push_front(current_node); - } - current_node = source(pred, m_g); - } - //then go forward in the sink-tree - current_node = target(e, m_g); - while(current_node != m_sink){ - edge_descriptor pred = get_edge_to_parent(current_node); - m_res_cap_map[pred] -= bottleneck; - assert(m_res_cap_map[pred] >= 0); - m_res_cap_map[m_rev_edge_map[pred]] += bottleneck; - if(m_res_cap_map[pred] == 0){ - set_no_parent(current_node); - m_orphans.push_front(current_node); - } - current_node = target(pred, m_g); - } - //and add it to the max-flow - m_flow += bottleneck; - } - - /** - * returns the bottleneck of a s->t path (end_of_path is last vertex in source-tree, begin_of_path is first vertex in sink-tree) - */ - inline tEdgeVal find_bottleneck(edge_descriptor e){ - BOOST_USING_STD_MIN(); - tEdgeVal minimum_cap = m_res_cap_map[e]; - vertex_descriptor current_node = source(e, m_g); - //first go back in the source tree - while(current_node != m_source){ - edge_descriptor pred = get_edge_to_parent(current_node); - minimum_cap = min BOOST_PREVENT_MACRO_SUBSTITUTION(minimum_cap, m_res_cap_map[pred]); - current_node = source(pred, m_g); - } - //then go forward in the sink-tree - current_node = target(e, m_g); - while(current_node != m_sink){ - edge_descriptor pred = get_edge_to_parent(current_node); - minimum_cap = min BOOST_PREVENT_MACRO_SUBSTITUTION(minimum_cap, m_res_cap_map[pred]); - current_node = target(pred, m_g); - } - return minimum_cap; - } - - /** - * rebuild search trees - * empty the queue of orphans, and find new parents for them or just drop them from the search trees - */ - void adopt(){ - while(!m_orphans.empty() || !m_child_orphans.empty()){ - vertex_descriptor current_node; - if(m_child_orphans.empty()){ - //get the next orphan from the main-queue and remove it - current_node = m_orphans.front(); - m_orphans.pop_front(); - } else{ - current_node = m_child_orphans.front(); - m_child_orphans.pop(); - } - if(get_tree(current_node) == tColorTraits::black()){ - //we're in the source-tree - tDistanceVal min_distance = (std::numeric_limits::max)(); - edge_descriptor new_parent_edge; - out_edge_iterator ei, e_end; - for(boost::tie(ei, e_end) = out_edges(current_node, m_g); ei != e_end; ++ei){ - const edge_descriptor in_edge = m_rev_edge_map[*ei]; - assert(target(in_edge, m_g) == current_node); //we should be the target of this edge - if(m_res_cap_map[in_edge] > 0){ - vertex_descriptor other_node = source(in_edge, m_g); - if(get_tree(other_node) == tColorTraits::black() && has_source_connect(other_node)){ - if(m_dist_map[other_node] < min_distance){ - min_distance = m_dist_map[other_node]; - new_parent_edge = in_edge; - } - } - } - } - if(min_distance != (std::numeric_limits::max)()){ - set_edge_to_parent(current_node, new_parent_edge); - m_dist_map[current_node] = min_distance + 1; - m_time_map[current_node] = m_time; - } else{ - m_time_map[current_node] = 0; - for(boost::tie(ei, e_end) = out_edges(current_node, m_g); ei != e_end; ++ei){ - edge_descriptor in_edge = m_rev_edge_map[*ei]; - vertex_descriptor other_node = source(in_edge, m_g); - if(get_tree(other_node) == tColorTraits::black() && has_parent(other_node)){ - if(m_res_cap_map[in_edge] > 0){ - add_active_node(other_node); - } - if(source(get_edge_to_parent(other_node), m_g) == current_node){ - //we are the parent of that node - //it has to find a new parent, too - set_no_parent(other_node); - m_child_orphans.push(other_node); - } - } - } - set_tree(current_node, tColorTraits::gray()); - } //no parent found - } //source-tree-adoption - else{ - //now we should be in the sink-tree, check that... - assert(get_tree(current_node) == tColorTraits::white()); - out_edge_iterator ei, e_end; - edge_descriptor new_parent_edge; - tDistanceVal min_distance = (std::numeric_limits::max)(); - for(boost::tie(ei, e_end) = out_edges(current_node, m_g); ei != e_end; ++ei){ - const edge_descriptor out_edge = *ei; - if(m_res_cap_map[out_edge] > 0){ - const vertex_descriptor other_node = target(out_edge, m_g); - if(get_tree(other_node) == tColorTraits::white() && has_sink_connect(other_node)) - if(m_dist_map[other_node] < min_distance){ - min_distance = m_dist_map[other_node]; - new_parent_edge = out_edge; - } - } - } - if(min_distance != (std::numeric_limits::max)()){ - set_edge_to_parent(current_node, new_parent_edge); - m_dist_map[current_node] = min_distance + 1; - m_time_map[current_node] = m_time; - } else{ - m_time_map[current_node] = 0; - for(boost::tie(ei, e_end) = out_edges(current_node, m_g); ei != e_end; ++ei){ - const edge_descriptor out_edge = *ei; - const vertex_descriptor other_node = target(out_edge, m_g); - if(get_tree(other_node) == tColorTraits::white() && has_parent(other_node)){ - if(m_res_cap_map[out_edge] > 0){ - add_active_node(other_node); - } - if(target(get_edge_to_parent(other_node), m_g) == current_node){ - //we were it's parent, so it has to find a new one, too - set_no_parent(other_node); - m_child_orphans.push(other_node); - } - } - } - set_tree(current_node, tColorTraits::gray()); - } //no parent found - } //sink-tree adoption - } //while !orphans.empty() - } //adopt - - /** - * return next active vertex if there is one, otherwise a null_vertex - */ - inline vertex_descriptor get_next_active_node(){ - while(true){ - if(m_active_nodes.empty()) - return graph_traits::null_vertex(); - vertex_descriptor v = m_active_nodes.front(); - - if(!has_parent(v) && v != m_source && v != m_sink){ //if it has no parent, this node can't be active(if its not source or sink) - m_active_nodes.pop(); - m_in_active_list_map[v] = false; - } else{ - assert(get_tree(v) == tColorTraits::black() || get_tree(v) == tColorTraits::white()); - return v; - } - } - } - - /** - * adds v as an active vertex, but only if its not in the list already - */ - inline void add_active_node(vertex_descriptor v){ - assert(get_tree(v) != tColorTraits::gray()); - if(m_in_active_list_map[v]){ - return; - } else{ - m_in_active_list_map[v] = true; - m_active_nodes.push(v); - } - } - - /** - * finish_node removes a node from the front of the active queue (its called in grow phase, if no more paths can be found using this node) - */ - inline void finish_node(vertex_descriptor v){ - assert(m_active_nodes.front() == v); - m_active_nodes.pop(); - m_in_active_list_map[v] = false; - m_last_grow_vertex = graph_traits::null_vertex(); - } - - /** - * removes a vertex from the queue of active nodes (actually this does nothing, - * but checks if this node has no parent edge, as this is the criteria for beeing no more active) - */ - inline void remove_active_node(vertex_descriptor v){ - assert(!has_parent(v)); - } - - /** - * returns the search tree of v; tColorValue::black() for source tree, white() for sink tree, gray() for no tree - */ - inline tColorValue get_tree(vertex_descriptor v) const { - return m_tree_map[v]; - } - - /** - * sets search tree of v; tColorValue::black() for source tree, white() for sink tree, gray() for no tree - */ - inline void set_tree(vertex_descriptor v, tColorValue t){ - m_tree_map[v] = t; - } - - /** - * returns edge to parent vertex of v; - */ - inline edge_descriptor get_edge_to_parent(vertex_descriptor v) const{ - return m_pre_map[v]; - } - - /** - * returns true if the edge stored in m_pre_map[v] is a valid entry - */ - inline bool has_parent(vertex_descriptor v) const{ - return m_has_parent_map[v]; - } - - /** - * sets edge to parent vertex of v; - */ - inline void set_edge_to_parent(vertex_descriptor v, edge_descriptor f_edge_to_parent){ - assert(m_res_cap_map[f_edge_to_parent] > 0); - m_pre_map[v] = f_edge_to_parent; - m_has_parent_map[v] = true; - } - - /** - * removes the edge to parent of v (this is done by invalidating the entry an additional map) - */ - inline void set_no_parent(vertex_descriptor v){ - m_has_parent_map[v] = false; - } - - /** - * checks if vertex v has a connect to the sink-vertex (@var m_sink) - * @param v the vertex which is checked - * @return true if a path to the sink was found, false if not - */ - inline bool has_sink_connect(vertex_descriptor v){ - tDistanceVal current_distance = 0; - vertex_descriptor current_vertex = v; - while(true){ - if(m_time_map[current_vertex] == m_time){ - //we found a node which was already checked this round. use it for distance calculations - current_distance += m_dist_map[current_vertex]; - break; - } - if(current_vertex == m_sink){ - m_time_map[m_sink] = m_time; - break; - } - if(has_parent(current_vertex)){ - //it has a parent, so get it - current_vertex = target(get_edge_to_parent(current_vertex), m_g); - ++current_distance; - } else{ - //no path found - return false; - } - } - current_vertex=v; - while(m_time_map[current_vertex] != m_time){ - m_dist_map[current_vertex] = current_distance--; - m_time_map[current_vertex] = m_time; - current_vertex = target(get_edge_to_parent(current_vertex), m_g); - } - return true; - } - - /** - * checks if vertex v has a connect to the source-vertex (@var m_source) - * @param v the vertex which is checked - * @return true if a path to the source was found, false if not - */ - inline bool has_source_connect(vertex_descriptor v){ - tDistanceVal current_distance = 0; - vertex_descriptor current_vertex = v; - while(true){ - if(m_time_map[current_vertex] == m_time){ - //we found a node which was already checked this round. use it for distance calculations - current_distance += m_dist_map[current_vertex]; - break; - } - if(current_vertex == m_source){ - m_time_map[m_source] = m_time; - break; - } - if(has_parent(current_vertex)){ - //it has a parent, so get it - current_vertex = source(get_edge_to_parent(current_vertex), m_g); - ++current_distance; - } else{ - //no path found - return false; - } - } - current_vertex=v; - while(m_time_map[current_vertex] != m_time){ - m_dist_map[current_vertex] = current_distance-- ; - m_time_map[current_vertex] = m_time; - current_vertex = source(get_edge_to_parent(current_vertex), m_g); - } - return true; - } - - /** - * returns true, if p is closer to a terminal than q - */ - inline bool is_closer_to_terminal(vertex_descriptor p, vertex_descriptor q){ - //checks the timestamps first, to build no cycles, and after that the real distance - return (m_time_map[q] <= m_time_map[p] && m_dist_map[q] > m_dist_map[p]+1); - } - - //////// - // member vars - //////// - Graph& m_g; - IndexMap m_index_map; - EdgeCapacityMap m_cap_map; - ResidualCapacityEdgeMap m_res_cap_map; - ReverseEdgeMap m_rev_edge_map; - PredecessorMap m_pre_map; //stores paths found in the growth stage - ColorMap m_tree_map; //maps each vertex into one of the two search tree or none (gray()) - DistanceMap m_dist_map; //stores distance to source/sink nodes - vertex_descriptor m_source; - vertex_descriptor m_sink; - - tQueue m_active_nodes; - std::vector m_in_active_list_vec; - iterator_property_map::iterator, IndexMap> m_in_active_list_map; - - std::list m_orphans; - tQueue m_child_orphans; // we use a second queuqe for child orphans, as they are FIFO processed - - std::vector m_has_parent_vec; - iterator_property_map::iterator, IndexMap> m_has_parent_map; - - std::vector m_time_vec; //timestamp of each node, used for sink/source-path calculations - iterator_property_map::iterator, IndexMap> m_time_map; - tEdgeVal m_flow; - long m_time; - vertex_descriptor m_last_grow_vertex; - out_edge_iterator m_last_grow_edge_it; - out_edge_iterator m_last_grow_edge_end; - }; - } //namespace detail - - /** - * non-named-parameter version, given everything - * this is the catch all version - */ - template - typename property_traits::value_type - kolmogorov_max_flow - (Graph& g, - CapacityEdgeMap cap, - ResidualCapacityEdgeMap res_cap, - ReverseEdgeMap rev_map, - PredecessorMap pre_map, - ColorMap color, - DistanceMap dist, - IndexMap idx, - typename graph_traits::vertex_descriptor src, - typename graph_traits::vertex_descriptor sink - ) - { - typedef typename graph_traits::vertex_descriptor vertex_descriptor; - typedef typename graph_traits::edge_descriptor edge_descriptor; - //as this method is the last one before we instantiate the solver, we do the concept checks here - function_requires >(); //to have vertices(), num_vertices(), - function_requires >(); //to have edges() - function_requires >(); //to have source(), target() and out_edges() - function_requires >(); //read flow-values from edges - function_requires >(); //write flow-values to residuals - function_requires >(); //read out reverse edges - function_requires >(); //store predecessor there - function_requires >(); //write corresponding tree - function_requires >(); //write distance to source/sink - function_requires >(); //get index 0...|V|-1 - assert(num_vertices(g) >= 2 && src != sink); - detail::kolmogorov - algo(g, cap, res_cap, rev_map, pre_map, color, dist, idx, src, sink); - return algo.max_flow(); - } - - /** - * non-named-parameter version, given: capacity, residucal_capacity, reverse_edges, and an index map. - */ - template - typename property_traits::value_type - kolmogorov_max_flow - (Graph& g, - CapacityEdgeMap cap, - ResidualCapacityEdgeMap res_cap, - ReverseEdgeMap rev, - IndexMap idx, - typename graph_traits::vertex_descriptor src, - typename graph_traits::vertex_descriptor sink) - { - typename graph_traits::vertices_size_type n_verts = num_vertices(g); - std::vector::edge_descriptor> predecessor_vec(n_verts); - std::vector color_vec(n_verts); - std::vector::vertices_size_type> distance_vec(n_verts); - return kolmogorov_max_flow - (g, cap, res_cap, rev, - make_iterator_property_map(predecessor_vec.begin(), idx), - make_iterator_property_map(color_vec.begin(), idx), - make_iterator_property_map(distance_vec.begin(), idx), - idx, src, sink); - } - - /** - * non-named-parameter version, some given: capacity, residual_capacity, reverse_edges, color_map and an index map. - * Use this if you are interested in the minimum cut, as the color map provides that info - */ - template - typename property_traits::value_type - kolmogorov_max_flow - (Graph& g, - CapacityEdgeMap cap, - ResidualCapacityEdgeMap res_cap, - ReverseEdgeMap rev, - ColorMap color, - IndexMap idx, - typename graph_traits::vertex_descriptor src, - typename graph_traits::vertex_descriptor sink) - { - typename graph_traits::vertices_size_type n_verts = num_vertices(g); - std::vector::edge_descriptor> predecessor_vec(n_verts); - std::vector::vertices_size_type> distance_vec(n_verts); - - return kolmogorov_max_flow - (g, cap, res_cap, rev, - make_iterator_property_map(predecessor_vec.begin(), idx), - color, - make_iterator_property_map(distance_vec.begin(), idx), - idx, src, sink); - } - - /** - * named-parameter version, some given - */ - template - typename property_traits::const_type>::value_type - kolmogorov_max_flow - (Graph& g, - typename graph_traits::vertex_descriptor src, - typename graph_traits::vertex_descriptor sink, - const bgl_named_params& params) - { - return kolmogorov_max_flow(g, - choose_const_pmap(get_param(params, edge_capacity), g, edge_capacity), - choose_pmap(get_param(params, edge_residual_capacity), g, edge_residual_capacity), - choose_const_pmap(get_param(params, edge_reverse), g, edge_reverse), - choose_pmap(get_param(params, vertex_predecessor), g, vertex_predecessor), - choose_pmap(get_param(params, vertex_color), g, vertex_color), - choose_pmap(get_param(params, vertex_distance), g, vertex_distance), - choose_const_pmap(get_param(params, vertex_index), g, vertex_index), - src, sink); - } - - /** - * named-parameter version, none given - */ - template - typename property_traits::const_type>::value_type - kolmogorov_max_flow - (Graph& g, - typename graph_traits::vertex_descriptor src, - typename graph_traits::vertex_descriptor sink) - { - bgl_named_params params(0); // bogus empty param - return kolmogorov_max_flow(g, src, sink, params); - } -} // namespace boost - -#endif // BOOST_KOLMOGOROV_MAX_FLOW_HPP - From 287529480f3dff6a14c84870e1eb15c128205835 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Thu, 6 Jan 2011 02:00:35 +0000 Subject: [PATCH 034/333] Removed deprecated code and docs [SVN r67704] --- doc/kolmogorov_max_flow.html | 407 ----------------------------------- doc/table_of_contents.html | 5 - 2 files changed, 412 deletions(-) delete mode 100644 doc/kolmogorov_max_flow.html diff --git a/doc/kolmogorov_max_flow.html b/doc/kolmogorov_max_flow.html deleted file mode 100644 index fad874527..000000000 --- a/doc/kolmogorov_max_flow.html +++ /dev/null @@ -1,407 +0,0 @@ - - - - - Boost Graph Library: Boykov-Kolmogorov Maximum Flow - - - - - - - - - -

      -C++ Boost -

      - - - - - - -
      - Warning! This header and its contents are deprecated and - will be removed in a future release. Please update your program to use - boykov_kolmogorov_max_flow - instead. Note that only the name of the algorithm has changed. The template - and function parameters will remain the same. -
      - - -

      kolmogorov_max_flow -

      -
      // named parameter version
      -template <class Graph, class P, class T, class R>
      -typename property_traits<typename property_map<Graph, edge_capacity_t>::const_type>::value_type
      -kolmogorov_max_flow(Graph& g,
      -   typename graph_traits<Graph>::vertex_descriptor src,
      -   typename graph_traits<Graph>::vertex_descriptor sink,
      -   const bgl_named_params<P, T, R>& params = all defaults)
      -
      -// non-named parameter version
      -template <class Graph, class CapacityEdgeMap, class ResidualCapacityEdgeMap, class ReverseEdgeMap,
      -          class PredecessorMap, class ColorMap, class DistanceMap, class IndexMap>
      -typename property_traits<CapacityEdgeMap>::value_type
      -kolmogorov_max_flow(Graph& g,
      -       CapacityEdgeMap cap,
      -       ResidualCapacityEdgeMap res_cap,
      -       ReverseEdgeMap rev_map,
      -       PredecessorMap pre_map,
      -       ColorMap color,
      -       DistanceMap dist,
      -       IndexMap idx,
      -       typename graph_traits <Graph>::vertex_descriptor src,
      -       typename graph_traits <Graph >::vertex_descriptor sink)

      -Additional overloaded versions for non-named parameters -are provided (without DistanceMap/ColorMap/DistanceMap; for those -iterator_property_maps with the provided index map are used)

      -

      The kolmogorov_max_flow() function calculates the maximum -flow of a network. See Section Network -Flow Algorithms for a description of maximum flow. The calculated -maximum flow will be the return value of the function. The function -also calculates the flow values f(u,v) for all (u,v) in -E, which are returned in the form of the residual capacity -r(u,v) = c(u,v) - f(u,v). -

      -

      Requirements:
      The directed graph G=(V,E) that -represents the network must include a reverse edge for every edge in -E. That is, the input graph should be Gin = -(V,{E U ET}). The ReverseEdgeMap argument rev -must map each edge in the original graph to its reverse edge, that is -(u,v) -> (v,u) for all (u,v) in E. -

      -

      Remarks: While the push-relabel method states that each edge in ET -has to have capacity of 0, the reverse edges for this algorithm ARE -allowed to carry capacities. If there are already reverse edges in -the input Graph G, -those can be used. This can halve the amount of edges and will -noticeably increase the performance.

      Algorithm -description:
      Kolmogorov's algorithm is a variety of the -augmenting-path algorithm. Standard augmenting path algorithms find -shortest paths from source to sink vertex and augment them by -substracting the bottleneck capacity found on that path from the -residual capacities of each edge and adding it to the total flow. -Additionally the minimum capacity is added to the residual capacity -of the reverse edges. If no more paths in the residual-edge tree are -found, the algorithm terminates. Instead of finding a new shortest -path from source to sink in the graph in each iteration, Kolmogorov's -version keeps the already found paths as follows:

      -

      The algorithm builds up two search trees, a source-tree and a -sink-tree. Each vertex has a label (stored in ColorMap) to -which tree it belongs and a status-flag if this vertex is active or -passive. In the beginning of the algorithm only the source and the -sink are colored (source==black, sink==white) and have active status. -All other vertices are colored gray. The algorithm consists of three -phases:

      -

      grow-phase: In this phase active vertices are allowed to -acquire neighbor vertices that are connected through an edge that has -a capacity-value greater than zero. Acquiring means that those vertices -become active and belong now to the search tree of the current -active vertex. If there are no more valid connections to neighbor -vertices, the current vertex becomes passive and the grow phase -continues with the next active vertex. The grow phase terminates if -there are no more active vertices left or a vertex discovers a vertex -from the other search tree through an unsaturated edge. In this case -a path from source to sink is found.

      -

      augment-phase: This phase augments the path that was found -in the grow phase. First it finds the bottleneck capacity of the -found path, and then it updates the residual-capacity of the edges -from this path by substracting the bottleneck capacity from the -residual capacity. Furthermore the residual capacity of the reverse -edges are updated by adding the bottleneck capacity. This phase can -destroy the built up search trees, as it creates at least one -saturated edge. That means, that the search trees collapse to -forests, because a condition for the search trees is, that each -vertex in them has a valid (=non-saturated) connection to a terminal.

      -

      adoption-phase: Here the search trees are reconstructed. A -simple solution would be to mark all vertices coming after the first -orphan in the found path free vertices (gray). A more sophisticated -solution is to give those orphans new parents: The neighbor vertices -are checked if they have a valid connection to the same terminal like -this vertex had (a path with unsaturated edges). If there is one, -this vertex becomes the new parent of the current orphan and this -forest is re-included into the search tree. If no new valid parent is -found, this vertex becomes a free vertex (marked gray), and it's -children become orphans. The adoption phase terminates if there are -no more orphans.

      -


      Details:

      -
        -
      • Marking heuristics: A timestamp is stored for each vertex - which shows in which iteration of the algorithm the distance to the - corresponding terminal was calculated. -

        -
          -
        • This distance is used and gets calculated in the - adoption-phase. In order to find a valid new parent for an orphan, - the possible parent is checked for a connection to the terminal to - which tree it belongs. If there is such a connection, the path is - tagged with the current time-stamp, and the distance value. If - another orphan has to find a parent and it comes across a vertex - with a current timestamp, this information is used.

          -
        • The distance is also used in the grow-phase. If a vertex - comes across another vertex of the same tree while searching for - new vertices, the other's distance is compared to its distance. If - it is smaller, that other vertex becomes the new parent of the - current. This can decrease the length of the search paths, and so - amount of adoptions.

          -
        -
      • Ordering of orphans: As described above, the augment-phase - and the adoption phase can create orphans. The orphans the - augment-phase generates, are ordered according to their distance to - the terminals (smallest first). This combined with the - distance/timestamp heuristics results in the possibility for not - having to recheck terminal-connections too often. New orphans which - are generated in adoption phase are processed before orphans from - the main queue for the same reason.

        -
      -


      Implementation notes:

      -

      The algorithm is mainly implemented as described in the PhD thesis -of Kolmogorov. Few changes were made for increasing performance:

      -
        -
      • initialization: the algorithm first augments all paths from - source->sink and all paths from source->VERTEX->sink. This - improves especially graph-cuts used in image vision where nearly - each vertex has a source and sink connect. During this step, all - vertices that have an unsaturated connection from source are added - to the active vertex list and so the source is not. -

        -
      • active vertices: Kolmogorov uses two lists for active nodes - and states that new active vertices are added to the rear of the - second. Fetching an active vertex is done from the beginning of the - first list. If the first list is empty, it is exchanged by the - second. This implementation uses just one list.

        -
      • grow-phase: In the grow phase the first vertex in the - active-list is taken and all outgoing edges are checked if they are - unsaturated. This decreases performance for graphs with high-edge - density. This implementation stores the last accessed edge and - continues with it, if the first vertex in the active-list is the - same one as during the last grow-phase.

        -
      -

      This algorithm [68, 69] was developed by Boykov and Kolmogorov. -

      -

      Where Defined

      -

      boost/graph/kolmogorov_max_flow.hpp -

      -

      Parameters

      -

      IN: Graph& g -

      -
      A directed graph. The graph's type must be a model of -Vertex List Graph, Edge -List Graph and Incidence Graph. -For each edge (u,v) in the graph, the reverse edge (v,u) -must also be in the graph. Performance of the algorithm will be slightly -improved if the graph type also models Adjacency -Matrix. -
      -

      IN: vertex_descriptor src -

      -
      The source vertex for the flow network graph. -
      -

      IN: vertex_descriptor sink -

      -
      The sink vertex for the flow network graph. -
      -

      Named Parameters

      -

      IN: edge_capacity(EdgeCapacityMap cap) -

      -
      The edge capacity property map. The type must be a model -of a constant Lvalue -Property Map. The key type of the map must be the graph's edge -descriptor type.
      Default: get(edge_capacity, g) -
      -

      OUT: edge_residual_capacity(ResidualCapacityEdgeMap res) -

      -
      The edge residual capacity property map. The type must be -a model of a mutable Lvalue -Property Map. The key type of the map must be the graph's edge -descriptor type.
      Default: get(edge_residual_capacity, -g) -
      -

      IN: edge_reverse(ReverseEdgeMap rev) -

      -
      An edge property map that maps every edge (u,v) in -the graph to the reverse edge (v,u). The map must be a model -of constant Lvalue -Property Map. The key type of the map must be the graph's edge -descriptor type.
      Default: get(edge_reverse, g) -
      -

      UTIL: vertex_predecessor(PredecessorMap pre_map) -

      -
      A vertex property map that stores the edge to the vertex' -predecessor. The map must be a model of mutable Lvalue -Property Map. The key type of the map must be the graph's vertex -descriptor type.
      Default: get(vertex_predecessor, g) -
      -

      OUT/UTIL: vertex_color(ColorMap color) -

      -
      A vertex property map that stores a color for edge -vertex. If the color of a vertex after running the algorithm is black -the vertex belongs to the source tree else it belongs to the -sink-tree (used for minimum cuts). The map must be a model of mutable -Lvalue Property -Map. The key type of the map must be the graph's vertex -descriptor type.
      Default: get(vertex_color, g) -
      -

      UTIL: vertex_distance(DistanceMap dist) -

      -
      A vertex property map that stores the distance to the -corresponding terminal. It's a utility-map for speeding up the -algorithm. The map must be a model of mutable Lvalue -Property Map. The key type of the map must be the graph's vertex -descriptor type.
      Default: get(vertex_distance, g) -
      -

      IN: vertex_index(VertexIndexMap index_map) -

      -
      Maps each vertex of the graph to a unique integer in the -range [0, num_vertices(g)). The map must be a model of -constant LvaluePropertyMap. -The key type of the map must be the graph's vertex descriptor -type.
      Default: get(vertex_index, g) -
      -

      Example

      -

      This reads an example maximum flow problem (a graph with edge -capacities) from a file in the DIMACS format (example/max_flow.dat). -The source for this example can be found in -example/boykov_kolmogorov-eg.cpp. -

      -
      #include <boost/config.hpp>
      -#include <iostream>
      -#include <string>
      -#include <boost/graph/kolmogorov_max_flow.hpp>
      -#include <boost/graph/adjacency_list.hpp>
      -#include <boost/graph/read_dimacs.hpp>
      -#include <boost/graph/graph_utility.hpp>
      -
      -int
      -main()
      -{
      -  using namespace boost;
      -
      -  typedef adjacency_list_traits < vecS, vecS, directedS > Traits;
      -  typedef adjacency_list < vecS, vecS, directedS,
      -    property < vertex_name_t, std::string,
      -    property < vertex_index_t, long,
      -    property < vertex_color_t, boost::default_color_type,
      -    property < vertex_distance_t, long,
      -    property < vertex_predecessor_t, Traits::edge_descriptor > > > > >,
      -
      -    property < edge_capacity_t, long,
      -    property < edge_residual_capacity_t, long,
      -    property < edge_reverse_t, Traits::edge_descriptor > > > > Graph;
      -
      -  Graph g;
      -  property_map < Graph, edge_capacity_t >::type
      -      capacity = get(edge_capacity, g);
      -  property_map < Graph, edge_residual_capacity_t >::type
      -      residual_capacity = get(edge_residual_capacity, g);
      -  property_map < Graph, edge_reverse_t >::type rev = get(edge_reverse, g);
      -  Traits::vertex_descriptor s, t;
      -  read_dimacs_max_flow(g, capacity, rev, s, t);
      -
      -  std::vector<default_color_type> color(num_vertices(g));
      -  std::vector<long> distance(num_vertices(g));
      -  long flow = kolmogorov_max_flow(g ,s, t);
      -
      -  std::cout << "c  The total flow:" << std::endl;
      -  std::cout << "s " << flow << std::endl << std::endl;
      -
      -  std::cout << "c flow values:" << std::endl;
      -  graph_traits < Graph >::vertex_iterator u_iter, u_end;
      -  graph_traits < Graph >::out_edge_iterator ei, e_end;
      -  for (tie(u_iter, u_end) = vertices(g); u_iter != u_end; ++u_iter)
      -    for (tie(ei, e_end) = out_edges(*u_iter, g); ei != e_end; ++ei)
      -      if (capacity[*ei] > 0)
      -        std::cout << "f " << *u_iter << " " << target(*ei, g) << " "
      -          << (capacity[*ei] - residual_capacity[*ei]) << std::endl;
      -
      -  return EXIT_SUCCESS;
      -}

      -The output is: -

      -
      c  The total flow:
      -s 13
      -
      -c flow values:
      -f 0 6 3
      -f 0 1 0
      -f 0 2 10
      -f 1 5 1
      -f 1 0 0
      -f 1 3 0
      -f 2 4 4
      -f 2 3 6
      -f 2 0 0
      -f 3 7 5
      -f 3 2 0
      -f 3 1 1
      -f 4 5 4
      -f 4 6 0
      -f 5 4 0
      -f 5 7 5
      -f 6 7 3
      -f 6 4 0
      -f 7 6 0
      -f 7 5 0

      -See Also

      -

      edmonds_karp_max_flow(),
      push_relabel_max_flow(). -

      -
      - - - - - -
      -

      Copyright © 2006

      -
      -

      Stephan Diederich, University - Mannheim(diederich@ti.uni-manheim.de)

      -
      -



      -

      - - diff --git a/doc/table_of_contents.html b/doc/table_of_contents.html index da03f48e8..db02575c8 100644 --- a/doc/table_of_contents.html +++ b/doc/table_of_contents.html @@ -201,11 +201,6 @@

      Table of Contents: the Boost Graph Library
      1. edmonds_karp_max_flow
      2. push_relabel_max_flow -
      3. - kolmogorov_max_flow (Deprecated. - Use boykov_kolmogorov_max_flow - instead.) -
      4. boykov_kolmogorov_max_flow
      5. edmonds_maximum_cardinality_matching
      From 43386bca5c4871047542d110d5f75c1e32c0122d Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Thu, 6 Jan 2011 02:08:41 +0000 Subject: [PATCH 035/333] Fixed assert inspection issues in sequential BGL [SVN r67705] --- include/boost/graph/adjacency_matrix.hpp | 8 ++-- .../graph/boykov_kolmogorov_max_flow.hpp | 48 +++++++++---------- .../graph/compressed_sparse_row_graph.hpp | 4 +- include/boost/graph/detail/adjacency_list.hpp | 3 +- .../detail/compressed_sparse_row_struct.hpp | 8 ++-- include/boost/graph/detail/d_ary_heap.hpp | 4 +- include/boost/graph/detail/histogram_sort.hpp | 6 ++- include/boost/graph/dimacs.hpp | 15 +++--- include/boost/graph/erdos_renyi_generator.hpp | 6 +-- include/boost/graph/graph_stats.hpp | 3 +- include/boost/graph/graph_test.hpp | 2 +- include/boost/graph/gursoy_atun_layout.hpp | 3 +- .../graph/kamada_kawai_spring_layout.hpp | 31 +++++++++--- .../boost/graph/loop_erased_random_walk.hpp | 6 +-- include/boost/graph/mesh_graph_generator.hpp | 4 +- .../boost/graph/minimum_degree_ordering.hpp | 4 +- include/boost/graph/one_bit_color_map.hpp | 7 +-- include/boost/graph/properties.hpp | 4 +- include/boost/graph/push_relabel_max_flow.hpp | 8 ++-- include/boost/graph/random.hpp | 4 +- include/boost/graph/random_spanning_tree.hpp | 5 +- include/boost/graph/rmat_graph_generator.hpp | 9 ++-- include/boost/graph/stoer_wagner_min_cut.hpp | 12 ++--- include/boost/graph/subgraph.hpp | 8 ++-- include/boost/graph/two_bit_color_map.hpp | 7 +-- src/read_graphviz_new.cpp | 17 +++---- 26 files changed, 132 insertions(+), 104 deletions(-) diff --git a/include/boost/graph/adjacency_matrix.hpp b/include/boost/graph/adjacency_matrix.hpp index 6fb1f4865..47d8d5f28 100644 --- a/include/boost/graph/adjacency_matrix.hpp +++ b/include/boost/graph/adjacency_matrix.hpp @@ -14,7 +14,7 @@ #include #include #include -#include +#include #include #include #include @@ -982,7 +982,7 @@ namespace boost { inline typename adjacency_matrix::vertex_descriptor add_vertex(adjacency_matrix& g) { // UNDER CONSTRUCTION - assert(false); + BOOST_ASSERT(false); return *vertices(g).first; } @@ -991,7 +991,7 @@ namespace boost { inline typename adjacency_matrix::vertex_descriptor add_vertex(const VP2& /*vp*/, adjacency_matrix& g) { // UNDER CONSTRUCTION - assert(false); + BOOST_ASSERT(false); return *vertices(g).first; } @@ -1001,7 +1001,7 @@ namespace boost { adjacency_matrix& /*g*/) { // UNDER CONSTRUCTION - assert(false); + BOOST_ASSERT(false); } // O(V) diff --git a/include/boost/graph/boykov_kolmogorov_max_flow.hpp b/include/boost/graph/boykov_kolmogorov_max_flow.hpp index 8559bd771..6a4c4482f 100644 --- a/include/boost/graph/boykov_kolmogorov_max_flow.hpp +++ b/include/boost/graph/boykov_kolmogorov_max_flow.hpp @@ -33,7 +33,7 @@ #define BOOST_BOYKOV_KOLMOGOROV_MAX_FLOW_HPP #include -#include +#include #include #include #include @@ -126,7 +126,7 @@ class bk_max_flow { edge_iterator ei, e_end; for(boost::tie(ei, e_end) = edges(m_g); ei != e_end; ++ei) { m_res_cap_map[*ei] = m_cap_map[*ei]; - assert(m_rev_edge_map[m_rev_edge_map[*ei]] == *ei); //check if the reverse edge map is build up properly + BOOST_ASSERT(m_rev_edge_map[m_rev_edge_map[*ei]] == *ei); //check if the reverse edge map is build up properly } //init the search trees with the two terminals set_tree(m_source, tColorTraits::black()); @@ -235,13 +235,13 @@ class bk_max_flow { * target(returnVal, m_g) is the beginning of the path found in the sink-tree */ std::pair grow(){ - assert(m_orphans.empty()); + BOOST_ASSERT(m_orphans.empty()); vertex_descriptor current_node; while((current_node = get_next_active_node()) != graph_traits::null_vertex()){ //if there is one - assert(get_tree(current_node) != tColorTraits::gray() && - (has_parent(current_node) || - current_node == m_source || - current_node == m_sink)); + BOOST_ASSERT(get_tree(current_node) != tColorTraits::gray() && + (has_parent(current_node) || + current_node == m_source || + current_node == m_sink)); if(get_tree(current_node) == tColorTraits::black()){ //source tree growing @@ -269,7 +269,7 @@ class bk_max_flow { m_time_map[other_node] = m_time_map[current_node]; } } else{ - assert(get_tree(other_node)==tColorTraits::white()); + BOOST_ASSERT(get_tree(other_node)==tColorTraits::white()); //kewl, found a path from one to the other search tree, return // the connecting edge in src->sink dir return std::make_pair(out_edge, true); @@ -278,7 +278,7 @@ class bk_max_flow { } //for all out-edges } //source-tree-growing else{ - assert(get_tree(current_node) == tColorTraits::white()); + BOOST_ASSERT(get_tree(current_node) == tColorTraits::white()); out_edge_iterator ei, e_end; if(current_node != m_last_grow_vertex){ m_last_grow_vertex = current_node; @@ -302,7 +302,7 @@ class bk_max_flow { m_time_map[other_node] = m_time_map[current_node]; } } else{ - assert(get_tree(other_node)==tColorTraits::black()); + BOOST_ASSERT(get_tree(other_node)==tColorTraits::black()); //kewl, found a path from one to the other search tree, // return the connecting edge in src->sink dir return std::make_pair(in_edge, true); @@ -332,16 +332,16 @@ class bk_max_flow { * and so we process the nearest verts to the terminals first */ void augment(edge_descriptor e) { - assert(get_tree(target(e, m_g)) == tColorTraits::white()); - assert(get_tree(source(e, m_g)) == tColorTraits::black()); - assert(m_orphans.empty()); + BOOST_ASSERT(get_tree(target(e, m_g)) == tColorTraits::white()); + BOOST_ASSERT(get_tree(source(e, m_g)) == tColorTraits::black()); + BOOST_ASSERT(m_orphans.empty()); const tEdgeVal bottleneck = find_bottleneck(e); //now we push the found flow through the path //for each edge we saturate we have to look for the verts that belong to that edge, one of them becomes an orphans //now process the connecting edge m_res_cap_map[e] -= bottleneck; - assert(m_res_cap_map[e] >= 0); + BOOST_ASSERT(m_res_cap_map[e] >= 0); m_res_cap_map[m_rev_edge_map[e]] += bottleneck; //now we follow the path back to the source @@ -349,7 +349,7 @@ class bk_max_flow { while(current_node != m_source){ edge_descriptor pred = get_edge_to_parent(current_node); m_res_cap_map[pred] -= bottleneck; - assert(m_res_cap_map[pred] >= 0); + BOOST_ASSERT(m_res_cap_map[pred] >= 0); m_res_cap_map[m_rev_edge_map[pred]] += bottleneck; if(m_res_cap_map[pred] == 0){ set_no_parent(current_node); @@ -362,7 +362,7 @@ class bk_max_flow { while(current_node != m_sink){ edge_descriptor pred = get_edge_to_parent(current_node); m_res_cap_map[pred] -= bottleneck; - assert(m_res_cap_map[pred] >= 0); + BOOST_ASSERT(m_res_cap_map[pred] >= 0); m_res_cap_map[m_rev_edge_map[pred]] += bottleneck; if(m_res_cap_map[pred] == 0){ set_no_parent(current_node); @@ -421,7 +421,7 @@ class bk_max_flow { out_edge_iterator ei, e_end; for(boost::tie(ei, e_end) = out_edges(current_node, m_g); ei != e_end; ++ei){ const edge_descriptor in_edge = m_rev_edge_map[*ei]; - assert(target(in_edge, m_g) == current_node); //we should be the target of this edge + BOOST_ASSERT(target(in_edge, m_g) == current_node); //we should be the target of this edge if(m_res_cap_map[in_edge] > 0){ vertex_descriptor other_node = source(in_edge, m_g); if(get_tree(other_node) == tColorTraits::black() && has_source_connect(other_node)){ @@ -458,7 +458,7 @@ class bk_max_flow { } //source-tree-adoption else{ //now we should be in the sink-tree, check that... - assert(get_tree(current_node) == tColorTraits::white()); + BOOST_ASSERT(get_tree(current_node) == tColorTraits::white()); out_edge_iterator ei, e_end; edge_descriptor new_parent_edge; tDistanceVal min_distance = (std::numeric_limits::max)(); @@ -513,7 +513,7 @@ class bk_max_flow { m_active_nodes.pop(); m_in_active_list_map[v] = false; } else{ - assert(get_tree(v) == tColorTraits::black() || get_tree(v) == tColorTraits::white()); + BOOST_ASSERT(get_tree(v) == tColorTraits::black() || get_tree(v) == tColorTraits::white()); return v; } } @@ -523,7 +523,7 @@ class bk_max_flow { * adds v as an active vertex, but only if its not in the list already */ inline void add_active_node(vertex_descriptor v){ - assert(get_tree(v) != tColorTraits::gray()); + BOOST_ASSERT(get_tree(v) != tColorTraits::gray()); if(m_in_active_list_map[v]){ return; } else{ @@ -536,7 +536,7 @@ class bk_max_flow { * finish_node removes a node from the front of the active queue (its called in grow phase, if no more paths can be found using this node) */ inline void finish_node(vertex_descriptor v){ - assert(m_active_nodes.front() == v); + BOOST_ASSERT(m_active_nodes.front() == v); m_active_nodes.pop(); m_in_active_list_map[v] = false; m_last_grow_vertex = graph_traits::null_vertex(); @@ -548,7 +548,7 @@ class bk_max_flow { * being no more active) */ inline void remove_active_node(vertex_descriptor v){ - assert(!has_parent(v)); + BOOST_ASSERT(!has_parent(v)); } /** @@ -585,7 +585,7 @@ class bk_max_flow { * sets edge to parent vertex of v; */ inline void set_edge_to_parent(vertex_descriptor v, edge_descriptor f_edge_to_parent){ - assert(m_res_cap_map[f_edge_to_parent] > 0); + BOOST_ASSERT(m_res_cap_map[f_edge_to_parent] > 0); m_pre_map[v] = f_edge_to_parent; m_has_parent_map[v] = true; } @@ -750,7 +750,7 @@ boykov_kolmogorov_max_flow(Graph& g, function_requires >(); //write corresponding tree function_requires >(); //write distance to source/sink function_requires >(); //get index 0...|V|-1 - assert(num_vertices(g) >= 2 && src != sink); + BOOST_ASSERT(num_vertices(g) >= 2 && src != sink); detail::bk_max_flow< Graph, CapacityEdgeMap, ResidualCapacityEdgeMap, ReverseEdgeMap, diff --git a/include/boost/graph/compressed_sparse_row_graph.hpp b/include/boost/graph/compressed_sparse_row_graph.hpp index 9b5a4d52c..caa27a906 100644 --- a/include/boost/graph/compressed_sparse_row_graph.hpp +++ b/include/boost/graph/compressed_sparse_row_graph.hpp @@ -17,7 +17,7 @@ #include #include #include -#include +#include #include #if 0 #include // For some debugging code below @@ -1342,7 +1342,7 @@ inline typename BOOST_CSR_GRAPH_TYPE::edge_descriptor edge_from_index(EdgeIndex idx, const BOOST_CSR_GRAPH_TYPE& g) { typedef typename std::vector::const_iterator row_start_iter; - assert (idx < num_edges(g)); + BOOST_ASSERT (idx < num_edges(g)); row_start_iter src_plus_1 = std::upper_bound(g.m_forward.m_rowstart.begin(), g.m_forward.m_rowstart.end(), diff --git a/include/boost/graph/detail/adjacency_list.hpp b/include/boost/graph/detail/adjacency_list.hpp index 0cbf5f4e9..2ff293e11 100644 --- a/include/boost/graph/detail/adjacency_list.hpp +++ b/include/boost/graph/detail/adjacency_list.hpp @@ -35,6 +35,7 @@ #include #include #include +#include // Symbol truncation problems with MSVC, trying to shorten names. #define stored_edge se_ @@ -1216,7 +1217,7 @@ namespace boost { std::pair rng = get_parallel_edge_sublist(e, g, (OutEdgeListS*)(0)); rng.first = std::find(rng.first, rng.second, e); - assert(rng.first != rng.second); + BOOST_ASSERT(rng.first != rng.second); remove_edge(rng.first); } diff --git a/include/boost/graph/detail/compressed_sparse_row_struct.hpp b/include/boost/graph/detail/compressed_sparse_row_struct.hpp index 4fb3c2269..75ac96204 100644 --- a/include/boost/graph/detail/compressed_sparse_row_struct.hpp +++ b/include/boost/graph/detail/compressed_sparse_row_struct.hpp @@ -21,7 +21,7 @@ #include #include #include -#include +#include #include #if 0 #include // For some debugging code below @@ -255,7 +255,7 @@ namespace detail { std::vector& targets, vertices_size_type numverts, GlobalToLocal global_to_local) { - assert (sources.size() == targets.size()); + BOOST_ASSERT (sources.size() == targets.size()); // Do an in-place histogram sort (at least that's what I think it is) to // sort sources and targets m_rowstart.clear(); @@ -281,8 +281,8 @@ namespace detail { std::vector& edge_props, vertices_size_type numverts, GlobalToLocal global_to_local) { - assert (sources.size() == targets.size()); - assert (sources.size() == edge_props.size()); + BOOST_ASSERT (sources.size() == targets.size()); + BOOST_ASSERT (sources.size() == edge_props.size()); // Do an in-place histogram sort (at least that's what I think it is) to // sort sources and targets m_rowstart.clear(); diff --git a/include/boost/graph/detail/d_ary_heap.hpp b/include/boost/graph/detail/d_ary_heap.hpp index c3b3ef7fd..ba58647a3 100644 --- a/include/boost/graph/detail/d_ary_heap.hpp +++ b/include/boost/graph/detail/d_ary_heap.hpp @@ -15,7 +15,7 @@ #include #include #include -#include +#include #include #include #include @@ -213,7 +213,7 @@ namespace boost { #if 0 for (size_t i = 1; i < data.size(); ++i) { if (compare_indirect(data[i], data[parent(i)])) { - assert (!"Element is smaller than its parent"); + BOOST_ASSERT (!"Element is smaller than its parent"); } } #endif diff --git a/include/boost/graph/detail/histogram_sort.hpp b/include/boost/graph/detail/histogram_sort.hpp index 742c6f963..b359a73de 100644 --- a/include/boost/graph/detail/histogram_sort.hpp +++ b/include/boost/graph/detail/histogram_sort.hpp @@ -10,6 +10,8 @@ #ifndef BOOST_GRAPH_DETAIL_HISTOGRAM_SORT_HPP #define BOOST_GRAPH_DETAIL_HISTOGRAM_SORT_HPP +#include + namespace boost { namespace graph { namespace detail { @@ -165,7 +167,7 @@ histogram_sort_inplace(KeyIterator key_begin, while (!(i >= rowstart[key_transform(key_begin[i])] && i < insert_positions[key_transform(key_begin[i])])) { // Add a slot in the right bucket size_t target_pos = insert_positions[key_transform(key_begin[i])]++; - assert (target_pos < rowstart[key_transform(key_begin[i]) + 1]); + BOOST_ASSERT (target_pos < rowstart[key_transform(key_begin[i]) + 1]); if (target_pos == i) continue; // Swap this edge into place using std::swap; @@ -199,7 +201,7 @@ histogram_sort_inplace(KeyIterator key_begin, while (!(i >= rowstart[key_transform(key_begin[i])] && i < insert_positions[key_transform(key_begin[i])])) { // Add a slot in the right bucket size_t target_pos = insert_positions[key_transform(key_begin[i])]++; - assert (target_pos < rowstart[key_transform(key_begin[i]) + 1]); + BOOST_ASSERT (target_pos < rowstart[key_transform(key_begin[i]) + 1]); if (target_pos == i) continue; // Swap this edge into place using std::swap; diff --git a/include/boost/graph/dimacs.hpp b/include/boost/graph/dimacs.hpp index 195ad3b65..3e8407dfa 100644 --- a/include/boost/graph/dimacs.hpp +++ b/include/boost/graph/dimacs.hpp @@ -17,6 +17,7 @@ #include #include #include +#include namespace boost { namespace graph { @@ -54,27 +55,27 @@ class dimacs_basic_reader { num_edges( 0 ), seen_edges( 0 ), want_weights(false) {} edge_type edge_deref() { - assert( !read_edges.empty() ); + BOOST_ASSERT( !read_edges.empty() ); return read_edges.front(); } inline edge_type* edge_ref() { - assert( !read_edges.empty() ); + BOOST_ASSERT( !read_edges.empty() ); return &read_edges.front(); } inline edge_weight_type edge_weight_deref() { - assert( !read_edge_weights.empty() ); + BOOST_ASSERT( !read_edge_weights.empty() ); return read_edge_weights.front(); } inline dimacs_basic_reader incr( incr_mode mode ) { if( mode == edge ) { - assert( !read_edges.empty() ); + BOOST_ASSERT( !read_edges.empty() ); read_edges.pop(); } else if( mode == edge_weight ) { - assert( !read_edge_weights.empty() ); + BOOST_ASSERT( !read_edge_weights.empty() ); read_edge_weights.pop(); } @@ -100,8 +101,8 @@ class dimacs_basic_reader { read_edge_weights.push( weight ); } } - assert( read_edges.size() < 100 ); - assert( read_edge_weights.size() < 100 ); + BOOST_ASSERT( read_edges.size() < 100 ); + BOOST_ASSERT( read_edge_weights.size() < 100 ); } // the 1000000 just happens to be about how many edges can be read in diff --git a/include/boost/graph/erdos_renyi_generator.hpp b/include/boost/graph/erdos_renyi_generator.hpp index a45944168..5be06d79d 100644 --- a/include/boost/graph/erdos_renyi_generator.hpp +++ b/include/boost/graph/erdos_renyi_generator.hpp @@ -10,7 +10,7 @@ #ifndef BOOST_GRAPH_ERDOS_RENYI_GENERATOR_HPP #define BOOST_GRAPH_ERDOS_RENYI_GENERATOR_HPP -#include +#include #include #include #include @@ -155,8 +155,8 @@ namespace boost { // bernoulli_distribution would need to be run until it returns true. // Thus, this distribution can be used to step through the edges // which are actually present. - assert (src != (std::numeric_limits::max)() && - src != n); + BOOST_ASSERT (src != (std::numeric_limits::max)() && + src != n); while (src != n) { vertices_size_type increment = rand_vertex(*gen); size_t tgt_index_limit = diff --git a/include/boost/graph/graph_stats.hpp b/include/boost/graph/graph_stats.hpp index 636c49137..ad0e330ca 100644 --- a/include/boost/graph/graph_stats.hpp +++ b/include/boost/graph/graph_stats.hpp @@ -12,6 +12,7 @@ #include #include #include +#include namespace boost { namespace graph { @@ -124,7 +125,7 @@ std::map weight_degree_dist( Graph& g ) { for( std::map::iterator iter = dist.begin(); iter != dist.end(); ++iter ) { - assert( n[iter->first] != 0 ); + BOOST_ASSERT( n[iter->first] != 0 ); dist[iter->first] /= n[iter->first]; } diff --git a/include/boost/graph/graph_test.hpp b/include/boost/graph/graph_test.hpp index fc4d9f0f9..7b3a5402b 100644 --- a/include/boost/graph/graph_test.hpp +++ b/include/boost/graph/graph_test.hpp @@ -213,7 +213,7 @@ namespace boost { IsoMap iso_map(iso_vec.begin(), get(vertex_index, g)); copy_graph(g, cpy, orig_to_copy(iso_map)); - assert((verify_isomorphism(g, cpy, iso_map))); + BOOST_CHECK((verify_isomorphism(g, cpy, iso_map))); vertex_t v = add_vertex(g); diff --git a/include/boost/graph/gursoy_atun_layout.hpp b/include/boost/graph/gursoy_atun_layout.hpp index b16a01f68..9269c4b06 100644 --- a/include/boost/graph/gursoy_atun_layout.hpp +++ b/include/boost/graph/gursoy_atun_layout.hpp @@ -17,6 +17,7 @@ #include #include +#include #include #include #include @@ -169,7 +170,7 @@ gursoy_atun_step } min_distance_unset = false; } - assert (!min_distance_unset); // Graph must have at least one vertex + BOOST_ASSERT (!min_distance_unset); // Graph must have at least one vertex boost::detail::update_position_visitor< PositionMap, NodeDistanceMap, Topology, VertexListAndIncidenceGraph> diff --git a/include/boost/graph/kamada_kawai_spring_layout.hpp b/include/boost/graph/kamada_kawai_spring_layout.hpp index 0262e1fc2..f39ef90ca 100644 --- a/include/boost/graph/kamada_kawai_spring_layout.hpp +++ b/include/boost/graph/kamada_kawai_spring_layout.hpp @@ -17,6 +17,7 @@ #include #include #include +#include #include #include @@ -216,11 +217,13 @@ namespace boost { weight_type edge_length = detail::graph::compute_edge_length(g, distance, index, edge_or_side_length); + + std::cerr << "edge_length = " << edge_length << std::endl; // Compute l_{ij} and k_{ij} const weight_type K = spring_constant; - vertex_iterator ui, end = vertices(g).second; - for (ui = vertices(g).first; ui != end; ++ui) { + vertex_iterator ui, end; + for (ui = vertices(g).first, end = vertices(g).second; ui != end; ++ui) { vertex_iterator vi = ui; for (++vi; vi != end; ++vi) { weight_type dij = distance[get(index, *ui)][get(index, *vi)]; @@ -237,7 +240,7 @@ namespace boost { vertex_descriptor p = *vertices(g).first; weight_type delta_p(0); - for (ui = vertices(g).first; ui != end; ++ui) { + for (ui = vertices(g).first, end = vertices(g).second; ui != end; ++ui) { deriv_type deriv = compute_partial_derivatives(*ui); put(partial_derivatives, *ui, deriv); @@ -255,12 +258,25 @@ namespace boost { // update the delta_i values in O(n) time instead of O(n^2) // time. std::vector p_partials(num_vertices(g)); - for (ui = vertices(g).first; ui != end; ++ui) { + for (ui = vertices(g).first, end = vertices(g).second; ui != end; ++ui) { vertex_descriptor i = *ui; p_partials[get(index, i)] = compute_partial_derivative(i, p); } do { + // For debugging, compute the energy value E + double E = 0.; + for (ui = vertices(g).first, end = vertices(g).second; ui != end; ++ui) { + vertex_iterator vi = ui; + for (++vi; vi != end; ++vi) { + double dist = topology.distance(position[*ui], position[*vi]); + weight_type k_ij = spring_strength[get(index,*ui)][get(index,*vi)]; + weight_type l_ij = distance[get(index, *ui)][get(index, *vi)]; + E += .5 * k_ij * (dist - l_ij) * (dist - l_ij); + } + } + std::cerr << "E = " << E << std::endl; + // Compute the elements of the Jacobian // From // http://www.cs.panam.edu/~rfowler/papers/1994_kumar_fowler_A_Spring_UTPACSTR.pdf @@ -269,7 +285,7 @@ namespace boost { for (std::size_t i = 0; i < Point::dimensions; ++i) for (std::size_t j = 0; j < Point::dimensions; ++j) dE_d_d[i][j] = 0.; - for (ui = vertices(g).first; ui != end; ++ui) { + for (ui = vertices(g).first, end = vertices(g).second; ui != end; ++ui) { vertex_descriptor i = *ui; if (i != p) { point_difference_type diff = topology.difference(position[p], position[i]); @@ -284,6 +300,7 @@ namespace boost { dE_d_d[i][i] += k_mi * (1 + (l_mi * (diff[i] * diff[i] - dist_squared) * inv_dist_cubed)); } else { dE_d_d[i][j] += k_mi * l_mi * diff[i] * diff[j] * inv_dist_cubed; + // dE_d_d[i][j] += k_mi * l_mi * sqrt(hypot(diff[i], diff[j])) * inv_dist_cubed; } } } @@ -292,7 +309,7 @@ namespace boost { deriv_type dE_d = get(partial_derivatives, p); - // Solve dE_d_d * delta = dE_d to get delta + // Solve dE_d_d * delta = -dE_d to get delta point_difference_type delta = -linear_solver::solve(dE_d_d, dE_d); // Move p by delta @@ -307,7 +324,7 @@ namespace boost { // Select new p by updating each partial derivative and delta vertex_descriptor old_p = p; - for (ui = vertices(g).first; ui != end; ++ui) { + for (ui = vertices(g).first, end = vertices(g).second; ui != end; ++ui) { deriv_type old_deriv_p = p_partials[get(index, *ui)]; deriv_type old_p_partial = compute_partial_derivative(*ui, old_p); diff --git a/include/boost/graph/loop_erased_random_walk.hpp b/include/boost/graph/loop_erased_random_walk.hpp index 6e6752a79..712c45d7c 100644 --- a/include/boost/graph/loop_erased_random_walk.hpp +++ b/include/boost/graph/loop_erased_random_walk.hpp @@ -15,7 +15,7 @@ #include #include #include -#include +#include namespace boost { @@ -51,7 +51,7 @@ namespace boost { typedef typename boost::property_traits::value_type color_t; typedef boost::color_traits color_gen; - assert (get(color, s) == color_gen::white()); + BOOST_ASSERT (get(color, s) == color_gen::white()); path.clear(); path.push_back(s); put(color, s, color_gen::gray()); @@ -67,7 +67,7 @@ namespace boost { // Found a loop; delete from path from the first occurrence of t to the // end, coloring vertices white. typename std::vector::iterator it = std::find(path.begin(), path.end(), t); - assert (it != path.end()); + BOOST_ASSERT (it != path.end()); ++it; for (typename std::vector::iterator j = it; j != path.end(); ++j) { put(color, *j, color_gen::white()); diff --git a/include/boost/graph/mesh_graph_generator.hpp b/include/boost/graph/mesh_graph_generator.hpp index 5bf1d47f3..141eca30f 100644 --- a/include/boost/graph/mesh_graph_generator.hpp +++ b/include/boost/graph/mesh_graph_generator.hpp @@ -11,7 +11,7 @@ #include #include -#include +#include #include #include #include @@ -47,7 +47,7 @@ namespace boost { bool toroidal = true) : x(x), y(y), n(x*y), source(0), target(1), current(0,1), toroidal(toroidal), done(false) - { assert(x > 1 && y > 1); } + { BOOST_ASSERT(x > 1 && y > 1); } reference operator*() const { return current; } pointer operator->() const { return ¤t; } diff --git a/include/boost/graph/minimum_degree_ordering.hpp b/include/boost/graph/minimum_degree_ordering.hpp index 85e6e7bed..1e171da6c 100644 --- a/include/boost/graph/minimum_degree_ordering.hpp +++ b/include/boost/graph/minimum_degree_ordering.hpp @@ -12,7 +12,7 @@ #define MINIMUM_DEGREE_ORDERING_HPP #include -#include +#include #include #include #include // for integer_traits @@ -53,7 +53,7 @@ namespace boost { : data(_data), current(-(std::numeric_limits::max)()) {} void pop() { - assert(! empty()); + BOOST_ASSERT(! empty()); current = data[current]; } void push(value_type v) { diff --git a/include/boost/graph/one_bit_color_map.hpp b/include/boost/graph/one_bit_color_map.hpp index 95a9604f6..b153b732f 100644 --- a/include/boost/graph/one_bit_color_map.hpp +++ b/include/boost/graph/one_bit_color_map.hpp @@ -18,6 +18,7 @@ #include #include #include +#include #include #include @@ -65,7 +66,7 @@ get(const one_bit_color_map& pm, { BOOST_STATIC_CONSTANT(int, bits_per_char = one_bit_color_map::bits_per_char); typename property_traits::value_type i = get(pm.index, key); - assert ((std::size_t)i < pm.n); + BOOST_ASSERT ((std::size_t)i < pm.n); return one_bit_color_type((pm.data.get()[i / bits_per_char] >> (i % bits_per_char)) & 1); } @@ -77,8 +78,8 @@ put(const one_bit_color_map& pm, { BOOST_STATIC_CONSTANT(int, bits_per_char = one_bit_color_map::bits_per_char); typename property_traits::value_type i = get(pm.index, key); - assert ((std::size_t)i < pm.n); - assert (value >= 0 && value < 2); + BOOST_ASSERT ((std::size_t)i < pm.n); + BOOST_ASSERT (value >= 0 && value < 2); std::size_t byte_num = i / bits_per_char; std::size_t bit_position = (i % bits_per_char); pm.data.get()[byte_num] = diff --git a/include/boost/graph/properties.hpp b/include/boost/graph/properties.hpp index 7225ebbd9..f4c57ea25 100644 --- a/include/boost/graph/properties.hpp +++ b/include/boost/graph/properties.hpp @@ -11,7 +11,7 @@ #define BOOST_GRAPH_PROPERTIES_HPP #include -#include +#include #include #include @@ -353,7 +353,7 @@ namespace boost { > make_container_vertex_map(RandomAccessContainer& c, const PropertyGraph& g) { - assert(c.size() >= num_vertices(g)); + BOOST_ASSERT(c.size() >= num_vertices(g)); return make_iterator_vertex_map(c.begin(), g); } diff --git a/include/boost/graph/push_relabel_max_flow.hpp b/include/boost/graph/push_relabel_max_flow.hpp index fdea7a7e6..4044815d9 100644 --- a/include/boost/graph/push_relabel_max_flow.hpp +++ b/include/boost/graph/push_relabel_max_flow.hpp @@ -11,7 +11,7 @@ #define BOOST_PUSH_RELABEL_MAX_FLOW_HPP #include -#include +#include #include #include #include @@ -266,7 +266,7 @@ namespace boost { // but it is called "discharge" in the paper and in hi_pr.c. void discharge(vertex_descriptor u) { - assert(get(excess_flow, u) > 0); + BOOST_ASSERT(get(excess_flow, u) > 0); while (1) { out_edge_iterator ai, ai_end; for (boost::tie(ai, ai_end) = current[u]; ai != ai_end; ++ai) { @@ -703,8 +703,8 @@ namespace boost { algo.convert_preflow_to_flow(); - assert(algo.is_flow()); - assert(algo.is_optimal()); + BOOST_ASSERT(algo.is_flow()); + BOOST_ASSERT(algo.is_optimal()); return flow; } // push_relabel_max_flow() diff --git a/include/boost/graph/random.hpp b/include/boost/graph/random.hpp index 7e1d65969..f4001337a 100644 --- a/include/boost/graph/random.hpp +++ b/include/boost/graph/random.hpp @@ -26,7 +26,7 @@ #include #include -#include +#include namespace boost { @@ -104,7 +104,7 @@ namespace boost { chosen_weight -= w; } } - assert (false); // Should not get here + BOOST_ASSERT (false); // Should not get here } namespace detail { diff --git a/include/boost/graph/random_spanning_tree.hpp b/include/boost/graph/random_spanning_tree.hpp index 7e36388fc..5ecd4f17d 100644 --- a/include/boost/graph/random_spanning_tree.hpp +++ b/include/boost/graph/random_spanning_tree.hpp @@ -11,6 +11,7 @@ #define BOOST_GRAPH_RANDOM_SPANNING_TREE_HPP #include +#include #include #include #include @@ -34,7 +35,7 @@ namespace boost { typedef typename graph_traits::vertex_descriptor vertex_descriptor; typedef typename graph_traits::edge_descriptor edge_descriptor; - assert (num_vertices(g) >= 1); // g must also be undirected (or symmetric) and connected + BOOST_ASSERT (num_vertices(g) >= 1); // g must also be undirected (or symmetric) and connected typedef color_traits::value_type> color_gen; BGL_FORALL_VERTICES_T(v, g, Graph) put(color, v, color_gen::white()); @@ -53,7 +54,7 @@ namespace boost { ++i) { typename std::vector::const_reverse_iterator j = i; ++j; - assert (get(color, *j) == color_gen::gray()); + BOOST_ASSERT (get(color, *j) == color_gen::gray()); put(color, *j, color_gen::black()); put(pred, *j, *i); } diff --git a/include/boost/graph/rmat_graph_generator.hpp b/include/boost/graph/rmat_graph_generator.hpp index 7060673ce..8a7726514 100644 --- a/include/boost/graph/rmat_graph_generator.hpp +++ b/include/boost/graph/rmat_graph_generator.hpp @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include @@ -155,7 +156,7 @@ namespace boost { { this->gen.reset(new uniform_01(gen)); - assert(boost::test_tools::check_is_close(a + b + c + d, 1., 1.e-5)); + BOOST_ASSERT(boost::test_tools::check_is_close(a + b + c + d, 1., 1.e-5)); if (permute_vertices) generate_permutation_vector(gen, vertexPermutation, n); @@ -265,7 +266,7 @@ namespace boost { values(sort_pair()), done(false) { - assert(boost::test_tools::check_is_close(a + b + c + d, 1., 1.e-5)); + BOOST_ASSERT(boost::test_tools::check_is_close(a + b + c + d, 1., 1.e-5)); this->gen.reset(new uniform_01(gen)); @@ -366,7 +367,7 @@ namespace boost { : gen(), done(false) { - assert(boost::test_tools::check_is_close(a + b + c + d, 1., 1.e-5)); + BOOST_ASSERT(boost::test_tools::check_is_close(a + b + c + d, 1., 1.e-5)); this->gen.reset(new uniform_01(gen)); @@ -479,7 +480,7 @@ namespace boost { values(sort_pair()), done(false) { - assert(boost::test_tools::check_is_close(a + b + c + d, 1., 1.e-5)); + BOOST_ASSERT(boost::test_tools::check_is_close(a + b + c + d, 1., 1.e-5)); this->gen.reset(new uniform_01(gen)); diff --git a/include/boost/graph/stoer_wagner_min_cut.hpp b/include/boost/graph/stoer_wagner_min_cut.hpp index 39375467e..814eae0ce 100644 --- a/include/boost/graph/stoer_wagner_min_cut.hpp +++ b/include/boost/graph/stoer_wagner_min_cut.hpp @@ -6,7 +6,7 @@ #ifndef BOOST_GRAPH_STOER_WAGNER_MIN_CUT_HPP #define BOOST_GRAPH_STOER_WAGNER_MIN_CUT_HPP 1 -#include +#include #include #include #include @@ -61,7 +61,7 @@ namespace boost { typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; typedef typename boost::property_traits::value_type weight_type; - assert(pq.empty()); + BOOST_ASSERT(pq.empty()); typename KeyedUpdatablePriorityQueue::key_map keys = pq.keys(); BGL_FORALL_VERTICES_T(v, g, UndirectedGraph) { @@ -72,7 +72,7 @@ namespace boost { } } - assert(pq.size() >= 2); + BOOST_ASSERT(pq.size() >= 2); vertex_descriptor s = boost::graph_traits::null_vertex(); vertex_descriptor t = boost::graph_traits::null_vertex(); @@ -169,7 +169,7 @@ namespace boost { weight_type bestW; boost::tie(s, t, bestW) = boost::detail::stoer_wagner_phase(g, assignments, assignedVertices, weights, pq); - assert(s != t); + BOOST_ASSERT(s != t); BGL_FORALL_VERTICES_T(v, g, UndirectedGraph) { put(parities, v, parity_type(v == t ? 1 : 0)); } @@ -180,7 +180,7 @@ namespace boost { for (; n >= 2; --n) { weight_type w; boost::tie(s, t, w) = boost::detail::stoer_wagner_phase(g, assignments, assignedVertices, weights, pq); - assert(s != t); + BOOST_ASSERT(s != t); if (w < bestW) { BGL_FORALL_VERTICES_T(v, g, UndirectedGraph) { @@ -201,7 +201,7 @@ namespace boost { assignedVertices.insert(t); } - assert(pq.empty()); + BOOST_ASSERT(pq.empty()); return bestW; } diff --git a/include/boost/graph/subgraph.hpp b/include/boost/graph/subgraph.hpp index fa5ec45ef..9e0919413 100644 --- a/include/boost/graph/subgraph.hpp +++ b/include/boost/graph/subgraph.hpp @@ -16,7 +16,7 @@ #include #include #include -#include +#include #include #include #include @@ -181,7 +181,7 @@ typedef typename Traits::traversal_category traversal_category; vertex_descriptor u_local; bool in_subgraph; if (is_root()) return u_global; boost::tie(u_local, in_subgraph) = this->find_vertex(u_global); - assert(in_subgraph == true); + BOOST_ASSERT(in_subgraph == true); return u_local; } @@ -345,7 +345,7 @@ typename subgraph::vertex_descriptor add_vertex(typename subgraph::vertex_descriptor u_global, subgraph& g) { - assert(!g.is_root()); + BOOST_ASSERT(!g.is_root()); typename subgraph::vertex_descriptor u_local, v_global; typename subgraph::edge_descriptor e_global; @@ -751,7 +751,7 @@ add_vertex(subgraph& g) // TODO: Under Construction template void remove_vertex(typename subgraph::vertex_descriptor u, subgraph& g) -{ assert(false); } +{ BOOST_ASSERT(false); } #endif //=========================================================================== diff --git a/include/boost/graph/two_bit_color_map.hpp b/include/boost/graph/two_bit_color_map.hpp index 9a3872fd0..3d55eabc7 100644 --- a/include/boost/graph/two_bit_color_map.hpp +++ b/include/boost/graph/two_bit_color_map.hpp @@ -17,6 +17,7 @@ #include #include #include +#include #include #include @@ -68,7 +69,7 @@ get(const two_bit_color_map& pm, { BOOST_STATIC_CONSTANT(int, elements_per_char = two_bit_color_map::elements_per_char); typename property_traits::value_type i = get(pm.index, key); - assert ((std::size_t)i < pm.n); + BOOST_ASSERT ((std::size_t)i < pm.n); std::size_t byte_num = i / elements_per_char; std::size_t bit_position = ((i % elements_per_char) * 2); return two_bit_color_type((pm.data.get()[byte_num] >> bit_position) & 3); @@ -82,8 +83,8 @@ put(const two_bit_color_map& pm, { BOOST_STATIC_CONSTANT(int, elements_per_char = two_bit_color_map::elements_per_char); typename property_traits::value_type i = get(pm.index, key); - assert ((std::size_t)i < pm.n); - assert (value >= 0 && value < 4); + BOOST_ASSERT ((std::size_t)i < pm.n); + BOOST_ASSERT (value >= 0 && value < 4); std::size_t byte_num = i / elements_per_char; std::size_t bit_position = ((i % elements_per_char) * 2); pm.data.get()[byte_num] = diff --git a/src/read_graphviz_new.cpp b/src/read_graphviz_new.cpp index 9e87ca23c..800124831 100644 --- a/src/read_graphviz_new.cpp +++ b/src/read_graphviz_new.cpp @@ -26,6 +26,7 @@ // #define BOOST_GRAPH_SOURCE +#include #include #include #include @@ -167,10 +168,10 @@ namespace read_graphviz_detail { #endif boost::regex_search(begin, end, results, stuff_to_skip); #ifndef NDEBUG - assert (found); + BOOST_ASSERT (found); #endif boost::sub_match sm1 = results.suffix(); - assert (sm1.second == end); + BOOST_ASSERT (sm1.second == end); begin = sm1.first; } @@ -227,10 +228,10 @@ namespace read_graphviz_detail { switch (str[1]) { case '-': return token(token::dash_dash, str); case '>': return token(token::dash_greater, str); - default: assert (!"Definition of punctuation_token does not match switch statement"); + default: BOOST_ASSERT (!"Definition of punctuation_token does not match switch statement"); } } - default: assert (!"Definition of punctuation_token does not match switch statement"); + default: BOOST_ASSERT (!"Definition of punctuation_token does not match switch statement"); } } found = boost::regex_search(begin, end, results, number_token); @@ -244,7 +245,7 @@ namespace read_graphviz_detail { std::string str = results[1].str(); begin = results.suffix().first; // Remove the beginning and ending quotes - assert (str.size() >= 2); + BOOST_ASSERT (str.size() >= 2); str.erase(str.begin()); str.erase(str.end() - 1); // Unescape quotes in the middle, but nothing else (see format spec) @@ -500,7 +501,7 @@ namespace read_graphviz_detail { case token::kw_graph: parse_attr_list(current_graph_props()); break; case token::kw_node: parse_attr_list(current().def_node_props); break; case token::kw_edge: parse_attr_list(current().def_edge_props); break; - default: assert (!"Bad attr_stmt case"); + default: BOOST_ASSERT (!"Bad attr_stmt case"); } } @@ -637,7 +638,7 @@ namespace read_graphviz_detail { } properties this_edge_props = current().def_edge_props; if (peek().type == token::left_bracket) parse_attr_list(this_edge_props); - assert (nodes_in_chain.size() >= 2); // Should be in node parser otherwise + BOOST_ASSERT (nodes_in_chain.size() >= 2); // Should be in node parser otherwise for (size_t i = 0; i + 1 < nodes_in_chain.size(); ++i) { do_orig_edge(nodes_in_chain[i], nodes_in_chain[i + 1], this_edge_props); } @@ -780,7 +781,7 @@ namespace read_graphviz_detail { } } std::map::const_iterator root_graph_props_i = r.graph_props.find("___root___"); - assert (root_graph_props_i != r.graph_props.end()); // Should not happen + BOOST_ASSERT (root_graph_props_i != r.graph_props.end()); // Should not happen const properties& root_graph_props = root_graph_props_i->second; // std::cerr << "ending graph " << props_to_string(root_graph_props) << std::endl; for (properties::const_iterator i = root_graph_props.begin(); i != root_graph_props.end(); ++i) { From ae33127eed6c77668e18005de246c45016a8b973 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Thu, 6 Jan 2011 16:08:05 +0000 Subject: [PATCH 036/333] Added disambiguation of regex_replace() overloads for VC++ 7.1 [SVN r67722] --- include/boost/graph/graphviz.hpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/include/boost/graph/graphviz.hpp b/include/boost/graph/graphviz.hpp index 1e6aeaf00..950909f1c 100644 --- a/include/boost/graph/graphviz.hpp +++ b/include/boost/graph/graphviz.hpp @@ -67,7 +67,9 @@ namespace boost { if (regex_match(s, valid_unquoted_id)) { return s; } else { - return "\"" + regex_replace(s, sregex(as_xpr('"')), "\\\"") + "\""; + // The explicit template arguments here are to disambiguate the two + // overloads of regex_replace() on VC++ 7.1. + return "\"" + regex_replace(s, sregex(as_xpr('"')), "\\\"") + "\""; } } From 3624e74d13eeb499f4d4a3660e264ef653ccd17e Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Thu, 6 Jan 2011 16:24:56 +0000 Subject: [PATCH 037/333] Fixed typo [SVN r67723] --- src/read_graphviz_new.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/read_graphviz_new.cpp b/src/read_graphviz_new.cpp index 800124831..130a112c2 100644 --- a/src/read_graphviz_new.cpp +++ b/src/read_graphviz_new.cpp @@ -718,7 +718,7 @@ namespace read_graphviz_detail { std::string rhs = "true"; if (peek().type == token::equal) { get(); - if (peek().type != token::identifier) error("Wanted identifier as value of attributed"); + if (peek().type != token::identifier) error("Wanted identifier as value of attribute"); rhs = get().normalized_value; } props[lhs] = rhs; From 19679d3851cc650b00aec08ce7faec07b5825add Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Thu, 6 Jan 2011 16:30:58 +0000 Subject: [PATCH 038/333] Simplifying code for VC++ 7.1 [SVN r67724] --- include/boost/graph/named_function_params.hpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/include/boost/graph/named_function_params.hpp b/include/boost/graph/named_function_params.hpp index 092eead8c..c5e35fa54 100644 --- a/include/boost/graph/named_function_params.hpp +++ b/include/boost/graph/named_function_params.hpp @@ -589,7 +589,9 @@ BOOST_BGL_DECLARE_NAMED_PARAMS ArgPack, PriorityQueueTag, int_refw - >::type::type + >::type + param_value_type_wrapper; + typedef typename param_value_type_wrapper::type param_value_type; typedef typename boost::remove_const::type param_value_type_no_const; typedef priority_queue_maker_helper Date: Fri, 7 Jan 2011 21:36:01 +0000 Subject: [PATCH 039/333] Changed to StringAlgo for replace operation rather than Xpressive [SVN r67764] --- include/boost/graph/graphviz.hpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/include/boost/graph/graphviz.hpp b/include/boost/graph/graphviz.hpp index 950909f1c..718220ffe 100644 --- a/include/boost/graph/graphviz.hpp +++ b/include/boost/graph/graphviz.hpp @@ -67,9 +67,8 @@ namespace boost { if (regex_match(s, valid_unquoted_id)) { return s; } else { - // The explicit template arguments here are to disambiguate the two - // overloads of regex_replace() on VC++ 7.1. - return "\"" + regex_replace(s, sregex(as_xpr('"')), "\\\"") + "\""; + boost::algorithm::replace_all(s, "\"", "\\\""); + return "\"" + s + "\""; } } From ec5f6a655c32d19f6404f90e41c5473ff2355b96 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Mon, 10 Jan 2011 15:20:55 +0000 Subject: [PATCH 040/333] Fixed URL [SVN r67914] --- example/actor_clustering.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/example/actor_clustering.cpp b/example/actor_clustering.cpp index a29256479..9b1b40221 100644 --- a/example/actor_clustering.cpp +++ b/example/actor_clustering.cpp @@ -9,7 +9,7 @@ // This program performs betweenness centrality (BC) clustering on the // actor collaboration graph available at -// http://www.nd.edu/~networks/database/index.html and outputs the +// http://www.nd.edu/~networks/resources/actor/actor.dat.gz and outputs the // result of clustering in Pajek format. // // This program mimics the BC clustering algorithm program implemented From 074277924aeb942ed9f7c4897fb6586c612c5a7c Mon Sep 17 00:00:00 2001 From: Bryce Adelstein-Lelbach Date: Fri, 14 Jan 2011 02:35:58 +0000 Subject: [PATCH 041/333] Replacing the use of with across Boost. On Linux, GNU's libstdc++, which is the default stdlib for icc and clang, cannot parse the header in version 4.5+ (which thankfully neither compiler advises the use of yet), as it's original C++98-friendly implementation has been replaced with a gnu++0x implementation. is a portable implementation of , providing boost::detail::setfill, boost::detail::setbase, boost::detail::setw, boost::detail::setprecision, boost::detail::setiosflags and boost::detail::resetiosflags. [SVN r68140] --- example/bellman-example.cpp | 4 ++-- example/closeness_centrality.cpp | 4 ++-- example/clustering_coefficient.cpp | 4 ++-- example/degree_centrality.cpp | 4 ++-- example/eccentricity.cpp | 4 ++-- example/inclusive_mean_geodesic.cpp | 14 +++++++------- example/influence_prestige.cpp | 5 +++-- example/johnson-eg.cpp | 10 +++++----- example/mean_geodesic.cpp | 4 ++-- example/scaled_closeness_centrality.cpp | 4 ++-- test/bellman-test.cpp | 10 +++++----- test/johnson-test.cpp | 10 +++++----- 12 files changed, 39 insertions(+), 38 deletions(-) diff --git a/example/bellman-example.cpp b/example/bellman-example.cpp index e6ec87506..85dd5ae7f 100644 --- a/example/bellman-example.cpp +++ b/example/bellman-example.cpp @@ -9,7 +9,7 @@ #include #include #include -#include +#include #include #include @@ -95,7 +95,7 @@ main() if (r) for (i = 0; i < N; ++i) - std::cout << name[i] << ": " << std::setw(3) << distance[i] + std::cout << name[i] << ": " << boost::detail::setw(3) << distance[i] << " " << name[parent[i]] << std::endl; else std::cout << "negative cycle" << std::endl; diff --git a/example/closeness_centrality.cpp b/example/closeness_centrality.cpp index b5aa4776b..5682d8f39 100644 --- a/example/closeness_centrality.cpp +++ b/example/closeness_centrality.cpp @@ -6,7 +6,7 @@ //[closeness_centrality_example #include -#include +#include #include #include @@ -76,7 +76,7 @@ main(int argc, char *argv[]) // Print the closeness centrality of each vertex. graph_traits::vertex_iterator i, end; for(tie(i, end) = vertices(g); i != end; ++i) { - cout << setw(12) << setiosflags(ios::left) + cout << boost::detail::setw(12) << boost::detail::setiosflags(ios::left) << g[*i].name << get(cm, *i) << endl; } diff --git a/example/clustering_coefficient.cpp b/example/clustering_coefficient.cpp index 70f8e731c..2cf9bfb81 100644 --- a/example/clustering_coefficient.cpp +++ b/example/clustering_coefficient.cpp @@ -7,7 +7,7 @@ //[code_clustering_coefficient #include -#include +#include #include #include @@ -59,7 +59,7 @@ main(int argc, char *argv[]) // Print the clustering coefficient of each vertex. graph_traits::vertex_iterator i, end; for(tie(i, end) = vertices(g); i != end; ++i) { - cout << setw(12) << setiosflags(ios::left) + cout << boost::detail::setw(12) << boost::detail::setiosflags(ios::left) << g[*i].name << get(cm, *i) << endl; } cout << "mean clustering coefficient: " << cc << endl; diff --git a/example/degree_centrality.cpp b/example/degree_centrality.cpp index 7da764e1b..ab745f7fe 100644 --- a/example/degree_centrality.cpp +++ b/example/degree_centrality.cpp @@ -7,7 +7,7 @@ //[degree_centrality_example #include -#include +#include #include #include @@ -58,7 +58,7 @@ main(int argc, char *argv[]) // Print the degree centrality of each vertex. graph_traits::vertex_iterator i, end; for(tie(i, end) = vertices(g); i != end; ++i) { - cout << setiosflags(ios::left) << setw(12) + cout << boost::detail::setiosflags(ios::left) << boost::detail::setw(12) << g[*i].name << cm[*i] << endl; } diff --git a/example/eccentricity.cpp b/example/eccentricity.cpp index 3e16e6f27..2ac245c09 100644 --- a/example/eccentricity.cpp +++ b/example/eccentricity.cpp @@ -7,7 +7,7 @@ //[eccentricity_example #include -#include +#include #include #include @@ -78,7 +78,7 @@ main(int argc, char *argv[]) // Print the closeness centrality of each vertex. graph_traits::vertex_iterator i, end; for(boost::tie(i, end) = vertices(g); i != end; ++i) { - cout << setw(12) << setiosflags(ios::left) + cout << boost::detail::setw(12) << boost::detail::setiosflags(ios::left) << g[*i].name << get(em, *i) << endl; } cout << "radius: " << r << endl; diff --git a/example/inclusive_mean_geodesic.cpp b/example/inclusive_mean_geodesic.cpp index 91d5a0d47..d9c9f279d 100644 --- a/example/inclusive_mean_geodesic.cpp +++ b/example/inclusive_mean_geodesic.cpp @@ -6,7 +6,7 @@ //[inclusive_mean_geodesic_example #include -#include +#include #include #include @@ -117,15 +117,15 @@ main(int argc, char *argv[]) // Print the mean geodesic distance of each vertex and finally, // the graph itself. - cout << setw(12) << setiosflags(ios::left) << "vertex"; - cout << setw(12) << setiosflags(ios::left) << "excluding"; - cout << setw(12) << setiosflags(ios::left) << "including" << endl; + cout << boost::detail::setw(12) << boost::detail::setiosflags(ios::left) << "vertex"; + cout << boost::detail::setw(12) << boost::detail::setiosflags(ios::left) << "excluding"; + cout << boost::detail::setw(12) << boost::detail::setiosflags(ios::left) << "including" << endl; graph_traits::vertex_iterator i, end; for(tie(i, end) = vertices(g); i != end; ++i) { - cout << setw(12) << setiosflags(ios::left) + cout << boost::detail::setw(12) << boost::detail::setiosflags(ios::left) << g[*i].name - << setw(12) << get(exmap, *i) - << setw(12) << get(inmap, *i) << endl; + << boost::detail::setw(12) << get(exmap, *i) + << boost::detail::setw(12) << get(inmap, *i) << endl; } cout << "small world (excluding self-loops): " << ex << endl; cout << "small world (including self-loops): " << in << endl; diff --git a/example/influence_prestige.cpp b/example/influence_prestige.cpp index 348b0d160..6fc860d4a 100644 --- a/example/influence_prestige.cpp +++ b/example/influence_prestige.cpp @@ -6,7 +6,7 @@ //[influence_prestige_example #include -#include +#include #include #include @@ -64,7 +64,8 @@ main(int argc, char *argv[]) graph_traits::vertex_iterator i, end; for(tie(i, end) = vertices(g); i != end; ++i) { Vertex v = *i; - cout << setiosflags(ios::left) << setw(12) + cout << ::boost::detail::setiosflags(ios::left) + << ::boost::detail::setw(12) << g[v].name << "\t" << im[v] << "\t" << pm[v] << endl; diff --git a/example/johnson-eg.cpp b/example/johnson-eg.cpp index 557b17334..8ed3af0c2 100644 --- a/example/johnson-eg.cpp +++ b/example/johnson-eg.cpp @@ -9,7 +9,7 @@ #include #include #include -#include +#include #include #include #include @@ -52,15 +52,15 @@ main() std::cout << " "; for (int k = 0; k < V; ++k) - std::cout << std::setw(5) << k; + std::cout << boost::detail::setw(5) << k; std::cout << std::endl; for (int i = 0; i < V; ++i) { - std::cout << std::setw(3) << i << " -> "; + std::cout << boost::detail::setw(3) << i << " -> "; for (int j = 0; j < V; ++j) { if (D[i][j] == (std::numeric_limits::max)()) - std::cout << std::setw(5) << "inf"; + std::cout << boost::detail::setw(5) << "inf"; else - std::cout << std::setw(5) << D[i][j]; + std::cout << boost::detail::setw(5) << D[i][j]; } std::cout << std::endl; } diff --git a/example/mean_geodesic.cpp b/example/mean_geodesic.cpp index f6b6892c0..b256464d6 100644 --- a/example/mean_geodesic.cpp +++ b/example/mean_geodesic.cpp @@ -6,7 +6,7 @@ //[mean_geodesic_example #include -#include +#include #include #include @@ -78,7 +78,7 @@ main(int argc, char *argv[]) // the graph itself. graph_traits::vertex_iterator i, end; for(tie(i, end) = vertices(g); i != end; ++i) { - cout << setw(12) << setiosflags(ios::left) + cout << boost::detail::setw(12) << boost::detail::setiosflags(ios::left) << g[*i].name << get(gm, *i) << endl; } cout << "small world distance: " << sw << endl; diff --git a/example/scaled_closeness_centrality.cpp b/example/scaled_closeness_centrality.cpp index 5223da97e..7cf1e9299 100644 --- a/example/scaled_closeness_centrality.cpp +++ b/example/scaled_closeness_centrality.cpp @@ -6,7 +6,7 @@ //[scaled_closeness_centrality_example #include -#include +#include #include #include @@ -105,7 +105,7 @@ main(int argc, char *argv[]) // Print the scaled closeness centrality of each vertex. graph_traits::vertex_iterator i, end; for(tie(i, end) = vertices(g); i != end; ++i) { - cout << setw(12) << setiosflags(ios::left) + cout << boost::detail::setw(12) << boost::detail::setiosflags(ios::left) << g[*i].name << get(cm, *i) << endl; } diff --git a/test/bellman-test.cpp b/test/bellman-test.cpp index 53bba704a..fa10f867e 100644 --- a/test/bellman-test.cpp +++ b/test/bellman-test.cpp @@ -14,7 +14,7 @@ B: 2147483647 B */ #include -#include +#include #include #include #include @@ -66,9 +66,9 @@ int test_main(int, char*[]) for(int i = 0; i < numVertex; ++i) { std::cout << name[i] << ": "; if (distance[i] == inf) - std::cout << std::setw(3) << "inf"; + std::cout << boost::detail::setw(3) << "inf"; else - std::cout << std::setw(3) << distance[i]; + std::cout << boost::detail::setw(3) << distance[i]; std::cout << " " << name[parent[i]] << std::endl; } } else { @@ -87,9 +87,9 @@ int test_main(int, char*[]) for(int i = 0; i < numVertex; ++i) { std::cout << name[i] << ": "; if (distance2[i] == inf) - std::cout << std::setw(3) << "inf"; + std::cout << boost::detail::setw(3) << "inf"; else - std::cout << std::setw(3) << distance2[i]; + std::cout << boost::detail::setw(3) << distance2[i]; std::cout << " " << name[parent2[i]] << std::endl; } } else { diff --git a/test/johnson-test.cpp b/test/johnson-test.cpp index f07eccea7..0c6ab9790 100644 --- a/test/johnson-test.cpp +++ b/test/johnson-test.cpp @@ -26,7 +26,7 @@ #include #include #include -#include +#include #include #include #include @@ -63,14 +63,14 @@ int main() int D[V][V]; johnson_all_pairs_shortest_paths(g, D, distance_map(&d[0])); - std::cout << std::setw(5) <<" "; + std::cout << boost::detail::setw(5) <<" "; for (int k = 0; k < 10; ++k) - std::cout << std::setw(5) << k ; + std::cout << boost::detail::setw(5) << k ; std::cout << std::endl; for (int i = 0; i < 10; ++i) { - std::cout < Date: Sat, 15 Jan 2011 08:11:51 +0000 Subject: [PATCH 042/333] Revert [67111] (addition of boost/detail/iomanip.hpp) and all the commits that depend on it. ([68137], [68140], [68141], [68154], and [68165]). [SVN r68168] --- example/bellman-example.cpp | 4 ++-- example/closeness_centrality.cpp | 4 ++-- example/clustering_coefficient.cpp | 4 ++-- example/degree_centrality.cpp | 4 ++-- example/eccentricity.cpp | 4 ++-- example/inclusive_mean_geodesic.cpp | 14 +++++++------- example/influence_prestige.cpp | 5 ++--- example/johnson-eg.cpp | 10 +++++----- example/mean_geodesic.cpp | 4 ++-- example/scaled_closeness_centrality.cpp | 4 ++-- test/bellman-test.cpp | 10 +++++----- test/johnson-test.cpp | 10 +++++----- 12 files changed, 38 insertions(+), 39 deletions(-) diff --git a/example/bellman-example.cpp b/example/bellman-example.cpp index 85dd5ae7f..e6ec87506 100644 --- a/example/bellman-example.cpp +++ b/example/bellman-example.cpp @@ -9,7 +9,7 @@ #include #include #include -#include +#include #include #include @@ -95,7 +95,7 @@ main() if (r) for (i = 0; i < N; ++i) - std::cout << name[i] << ": " << boost::detail::setw(3) << distance[i] + std::cout << name[i] << ": " << std::setw(3) << distance[i] << " " << name[parent[i]] << std::endl; else std::cout << "negative cycle" << std::endl; diff --git a/example/closeness_centrality.cpp b/example/closeness_centrality.cpp index 5682d8f39..b5aa4776b 100644 --- a/example/closeness_centrality.cpp +++ b/example/closeness_centrality.cpp @@ -6,7 +6,7 @@ //[closeness_centrality_example #include -#include +#include #include #include @@ -76,7 +76,7 @@ main(int argc, char *argv[]) // Print the closeness centrality of each vertex. graph_traits::vertex_iterator i, end; for(tie(i, end) = vertices(g); i != end; ++i) { - cout << boost::detail::setw(12) << boost::detail::setiosflags(ios::left) + cout << setw(12) << setiosflags(ios::left) << g[*i].name << get(cm, *i) << endl; } diff --git a/example/clustering_coefficient.cpp b/example/clustering_coefficient.cpp index 2cf9bfb81..70f8e731c 100644 --- a/example/clustering_coefficient.cpp +++ b/example/clustering_coefficient.cpp @@ -7,7 +7,7 @@ //[code_clustering_coefficient #include -#include +#include #include #include @@ -59,7 +59,7 @@ main(int argc, char *argv[]) // Print the clustering coefficient of each vertex. graph_traits::vertex_iterator i, end; for(tie(i, end) = vertices(g); i != end; ++i) { - cout << boost::detail::setw(12) << boost::detail::setiosflags(ios::left) + cout << setw(12) << setiosflags(ios::left) << g[*i].name << get(cm, *i) << endl; } cout << "mean clustering coefficient: " << cc << endl; diff --git a/example/degree_centrality.cpp b/example/degree_centrality.cpp index ab745f7fe..7da764e1b 100644 --- a/example/degree_centrality.cpp +++ b/example/degree_centrality.cpp @@ -7,7 +7,7 @@ //[degree_centrality_example #include -#include +#include #include #include @@ -58,7 +58,7 @@ main(int argc, char *argv[]) // Print the degree centrality of each vertex. graph_traits::vertex_iterator i, end; for(tie(i, end) = vertices(g); i != end; ++i) { - cout << boost::detail::setiosflags(ios::left) << boost::detail::setw(12) + cout << setiosflags(ios::left) << setw(12) << g[*i].name << cm[*i] << endl; } diff --git a/example/eccentricity.cpp b/example/eccentricity.cpp index 2ac245c09..3e16e6f27 100644 --- a/example/eccentricity.cpp +++ b/example/eccentricity.cpp @@ -7,7 +7,7 @@ //[eccentricity_example #include -#include +#include #include #include @@ -78,7 +78,7 @@ main(int argc, char *argv[]) // Print the closeness centrality of each vertex. graph_traits::vertex_iterator i, end; for(boost::tie(i, end) = vertices(g); i != end; ++i) { - cout << boost::detail::setw(12) << boost::detail::setiosflags(ios::left) + cout << setw(12) << setiosflags(ios::left) << g[*i].name << get(em, *i) << endl; } cout << "radius: " << r << endl; diff --git a/example/inclusive_mean_geodesic.cpp b/example/inclusive_mean_geodesic.cpp index d9c9f279d..91d5a0d47 100644 --- a/example/inclusive_mean_geodesic.cpp +++ b/example/inclusive_mean_geodesic.cpp @@ -6,7 +6,7 @@ //[inclusive_mean_geodesic_example #include -#include +#include #include #include @@ -117,15 +117,15 @@ main(int argc, char *argv[]) // Print the mean geodesic distance of each vertex and finally, // the graph itself. - cout << boost::detail::setw(12) << boost::detail::setiosflags(ios::left) << "vertex"; - cout << boost::detail::setw(12) << boost::detail::setiosflags(ios::left) << "excluding"; - cout << boost::detail::setw(12) << boost::detail::setiosflags(ios::left) << "including" << endl; + cout << setw(12) << setiosflags(ios::left) << "vertex"; + cout << setw(12) << setiosflags(ios::left) << "excluding"; + cout << setw(12) << setiosflags(ios::left) << "including" << endl; graph_traits::vertex_iterator i, end; for(tie(i, end) = vertices(g); i != end; ++i) { - cout << boost::detail::setw(12) << boost::detail::setiosflags(ios::left) + cout << setw(12) << setiosflags(ios::left) << g[*i].name - << boost::detail::setw(12) << get(exmap, *i) - << boost::detail::setw(12) << get(inmap, *i) << endl; + << setw(12) << get(exmap, *i) + << setw(12) << get(inmap, *i) << endl; } cout << "small world (excluding self-loops): " << ex << endl; cout << "small world (including self-loops): " << in << endl; diff --git a/example/influence_prestige.cpp b/example/influence_prestige.cpp index 6fc860d4a..348b0d160 100644 --- a/example/influence_prestige.cpp +++ b/example/influence_prestige.cpp @@ -6,7 +6,7 @@ //[influence_prestige_example #include -#include +#include #include #include @@ -64,8 +64,7 @@ main(int argc, char *argv[]) graph_traits::vertex_iterator i, end; for(tie(i, end) = vertices(g); i != end; ++i) { Vertex v = *i; - cout << ::boost::detail::setiosflags(ios::left) - << ::boost::detail::setw(12) + cout << setiosflags(ios::left) << setw(12) << g[v].name << "\t" << im[v] << "\t" << pm[v] << endl; diff --git a/example/johnson-eg.cpp b/example/johnson-eg.cpp index 8ed3af0c2..557b17334 100644 --- a/example/johnson-eg.cpp +++ b/example/johnson-eg.cpp @@ -9,7 +9,7 @@ #include #include #include -#include +#include #include #include #include @@ -52,15 +52,15 @@ main() std::cout << " "; for (int k = 0; k < V; ++k) - std::cout << boost::detail::setw(5) << k; + std::cout << std::setw(5) << k; std::cout << std::endl; for (int i = 0; i < V; ++i) { - std::cout << boost::detail::setw(3) << i << " -> "; + std::cout << std::setw(3) << i << " -> "; for (int j = 0; j < V; ++j) { if (D[i][j] == (std::numeric_limits::max)()) - std::cout << boost::detail::setw(5) << "inf"; + std::cout << std::setw(5) << "inf"; else - std::cout << boost::detail::setw(5) << D[i][j]; + std::cout << std::setw(5) << D[i][j]; } std::cout << std::endl; } diff --git a/example/mean_geodesic.cpp b/example/mean_geodesic.cpp index b256464d6..f6b6892c0 100644 --- a/example/mean_geodesic.cpp +++ b/example/mean_geodesic.cpp @@ -6,7 +6,7 @@ //[mean_geodesic_example #include -#include +#include #include #include @@ -78,7 +78,7 @@ main(int argc, char *argv[]) // the graph itself. graph_traits::vertex_iterator i, end; for(tie(i, end) = vertices(g); i != end; ++i) { - cout << boost::detail::setw(12) << boost::detail::setiosflags(ios::left) + cout << setw(12) << setiosflags(ios::left) << g[*i].name << get(gm, *i) << endl; } cout << "small world distance: " << sw << endl; diff --git a/example/scaled_closeness_centrality.cpp b/example/scaled_closeness_centrality.cpp index 7cf1e9299..5223da97e 100644 --- a/example/scaled_closeness_centrality.cpp +++ b/example/scaled_closeness_centrality.cpp @@ -6,7 +6,7 @@ //[scaled_closeness_centrality_example #include -#include +#include #include #include @@ -105,7 +105,7 @@ main(int argc, char *argv[]) // Print the scaled closeness centrality of each vertex. graph_traits::vertex_iterator i, end; for(tie(i, end) = vertices(g); i != end; ++i) { - cout << boost::detail::setw(12) << boost::detail::setiosflags(ios::left) + cout << setw(12) << setiosflags(ios::left) << g[*i].name << get(cm, *i) << endl; } diff --git a/test/bellman-test.cpp b/test/bellman-test.cpp index fa10f867e..53bba704a 100644 --- a/test/bellman-test.cpp +++ b/test/bellman-test.cpp @@ -14,7 +14,7 @@ B: 2147483647 B */ #include -#include +#include #include #include #include @@ -66,9 +66,9 @@ int test_main(int, char*[]) for(int i = 0; i < numVertex; ++i) { std::cout << name[i] << ": "; if (distance[i] == inf) - std::cout << boost::detail::setw(3) << "inf"; + std::cout << std::setw(3) << "inf"; else - std::cout << boost::detail::setw(3) << distance[i]; + std::cout << std::setw(3) << distance[i]; std::cout << " " << name[parent[i]] << std::endl; } } else { @@ -87,9 +87,9 @@ int test_main(int, char*[]) for(int i = 0; i < numVertex; ++i) { std::cout << name[i] << ": "; if (distance2[i] == inf) - std::cout << boost::detail::setw(3) << "inf"; + std::cout << std::setw(3) << "inf"; else - std::cout << boost::detail::setw(3) << distance2[i]; + std::cout << std::setw(3) << distance2[i]; std::cout << " " << name[parent2[i]] << std::endl; } } else { diff --git a/test/johnson-test.cpp b/test/johnson-test.cpp index 0c6ab9790..f07eccea7 100644 --- a/test/johnson-test.cpp +++ b/test/johnson-test.cpp @@ -26,7 +26,7 @@ #include #include #include -#include +#include #include #include #include @@ -63,14 +63,14 @@ int main() int D[V][V]; johnson_all_pairs_shortest_paths(g, D, distance_map(&d[0])); - std::cout << boost::detail::setw(5) <<" "; + std::cout << std::setw(5) <<" "; for (int k = 0; k < 10; ++k) - std::cout << boost::detail::setw(5) << k ; + std::cout << std::setw(5) << k ; std::cout << std::endl; for (int i = 0; i < 10; ++i) { - std::cout < Date: Fri, 11 Feb 2011 18:39:11 +0000 Subject: [PATCH 043/333] Changed "continue" to "break" in remove_edge_if; fixes #5181 [SVN r68781] --- include/boost/graph/subgraph.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/boost/graph/subgraph.hpp b/include/boost/graph/subgraph.hpp index 9e0919413..a17c896f8 100644 --- a/include/boost/graph/subgraph.hpp +++ b/include/boost/graph/subgraph.hpp @@ -691,7 +691,7 @@ remove_edge_if(Predicate p, subgraph& g) { if (p(*ep.first)) { any_removed = true; remove_edge(*ep.first, g); - continue; /* Since iterators may be invalidated */ + break; /* Since iterators may be invalidated */ } } if (!any_removed) break; From bb1ce866f831cea1fd5002338e31ae32752b25d3 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Wed, 16 Feb 2011 16:35:42 +0000 Subject: [PATCH 044/333] Applied second patch from #5180; fixes #5180 [SVN r68949] --- include/boost/graph/subgraph.hpp | 73 +++++++++++++++----------------- 1 file changed, 33 insertions(+), 40 deletions(-) diff --git a/include/boost/graph/subgraph.hpp b/include/boost/graph/subgraph.hpp index a17c896f8..2b702a80f 100644 --- a/include/boost/graph/subgraph.hpp +++ b/include/boost/graph/subgraph.hpp @@ -78,12 +78,12 @@ class subgraph { typedef graph_traits Traits; typedef std::list*> ChildrenList; public: -// Graph requirements -typedef typename Traits::vertex_descriptor vertex_descriptor; -typedef typename Traits::edge_descriptor edge_descriptor; -typedef typename Traits::directed_category directed_category; -typedef typename Traits::edge_parallel_category edge_parallel_category; -typedef typename Traits::traversal_category traversal_category; + // Graph requirements + typedef typename Traits::vertex_descriptor vertex_descriptor; + typedef typename Traits::edge_descriptor edge_descriptor; + typedef typename Traits::directed_category directed_category; + typedef typename Traits::edge_parallel_category edge_parallel_category; + typedef typename Traits::traversal_category traversal_category; // IncidenceGraph requirements typedef typename Traits::out_edge_iterator out_edge_iterator; @@ -196,12 +196,22 @@ typedef typename Traits::traversal_category traversal_category; std::pair find_vertex(vertex_descriptor u_global) const { if (is_root()) return std::make_pair(u_global, true); - typename std::map::const_iterator - i = m_local_vertex.find(u_global); + typename LocalVertexMap::const_iterator i = m_local_vertex.find(u_global); bool valid = i != m_local_vertex.end(); return std::make_pair((valid ? (*i).second : null_vertex()), valid); } + // Is edge e (of the root graph) contained in this subgraph? + // If so, return the matching local edge. + std::pair + find_edge(edge_descriptor e_global) const { + if (is_root()) return std::make_pair(e_global, true); + typename LocalEdgeMap::const_iterator i = + m_local_edge.find(get(get(edge_index, root().m_graph), e_global)); + bool valid = i != m_local_edge.end(); + return std::make_pair((valid ? (*i).second : edge_descriptor()), valid); + } + // Return the parent graph. subgraph& parent() { return *m_parent; } const subgraph& parent() const { return *m_parent; } @@ -617,38 +627,18 @@ namespace detail { //------------------------------------------------------------------------- // implementation of remove_edge(e,g) - template - void remove_edge_recur_down(Edge e_global, subgraph& g); - template + template void children_remove_edge(Edge e_global, Children& c) { for(typename Children::iterator i = c.begin(); i != c.end(); ++i) { - if((*i)->find_vertex(source(e_global, **i)).second && - (*i)->find_vertex(target(e_global, **i)).second) - { - remove_edge_recur_down(source(e_global, **i), - target(e_global, **i), - **i); + std::pair::edge_descriptor, bool> found = + (*i)->find_edge(e_global); + if (!found.second) { + continue; } - } - } - - template - void remove_edge_recur_down(Edge e_global, subgraph& g) - { - remove_edge(g.global_to_local(e_global), g.m_graph); - children_remove_edge(e_global, g.m_children); - } - - template - void remove_edge_recur_up(Edge e_global, subgraph& g) - { - if (g.is_root()) { - remove_edge(e_global, g.m_graph); - children_remove_edge(e_global, g.m_children); - } else { - remove_edge_recur_up(e_global, *g.m_parent); + children_remove_edge(e_global, (*i)->m_children); + remove_edge(found.first, (*i)->m_graph); } } @@ -672,11 +662,14 @@ template void remove_edge(typename subgraph::edge_descriptor e, subgraph& g) { - if(g.is_root()) { - detail::remove_edge_recur_up(e, g); - } else { - detail::remove_edge_recur_up(g.local_to_global(e), g); - } + typename subgraph::edge_descriptor e_global = g.local_to_global(e); +#ifndef NDEBUG + std::pair::edge_descriptor, bool> fe = g.find_edge(e_global); + assert(fe.second && fe.first == e); +#endif //NDEBUG + subgraph &root = g.root(); // chase to root + detail::children_remove_edge(e_global, root.m_children); + remove_edge(e_global, root.m_graph); // kick edge from root } // This is slow, but there may not be a good way to do it safely otherwise From a0c90983ab2440b20e70f7adb1d75182c718a9b2 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Thu, 17 Feb 2011 20:02:58 +0000 Subject: [PATCH 045/333] Fixed escaping using patch from #5199; fixes #5199 [SVN r68972] --- doc/subgraph.html | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/subgraph.html b/doc/subgraph.html index 09d07b30b..90c6019ce 100644 --- a/doc/subgraph.html +++ b/doc/subgraph.html @@ -76,9 +76,9 @@

      Example

      and subgraphs in Figure 1, so we will need a total of six vertices.
      -typedef adjacency_list_traits Traits;
      -typedef subgraph< adjacency_list > > Graph;
      +typedef adjacency_list_traits< vecS, vecS, directedS > Traits;
      +typedef subgraph< adjacency_list< vecS, vecS, directedS,
      +  no_property, property< edge_index_t, int > > > Graph;
       
       const int N = 6;
       Graph G0(N);
      
      From d44293d8a8f14d4d28121aaf405bc5876c4f1253 Mon Sep 17 00:00:00 2001
      From: Jeremiah Willcock 
      Date: Thu, 17 Feb 2011 23:00:20 +0000
      Subject: [PATCH 046/333] Fixed buffer overflow from parallel edges in
       isomorphism(); fixes #5175
      
      [SVN r68979]
      ---
       include/boost/graph/isomorphism.hpp | 18 +++++++++++++++---
       1 file changed, 15 insertions(+), 3 deletions(-)
      
      diff --git a/include/boost/graph/isomorphism.hpp b/include/boost/graph/isomorphism.hpp
      index 9461dc31e..f58690266 100644
      --- a/include/boost/graph/isomorphism.hpp
      +++ b/include/boost/graph/isomorphism.hpp
      @@ -284,18 +284,30 @@ namespace boost {
           typedef size_type result_type;
       
           degree_vertex_invariant(const InDegreeMap& in_degree_map, const Graph& g)
      -      : m_in_degree_map(in_degree_map), m_g(g) { }
      +      : m_in_degree_map(in_degree_map),
      +        m_max_vertex_in_degree(0),
      +        m_max_vertex_out_degree(0),
      +        m_g(g) {
      +      BGL_FORALL_VERTICES_T(v, g, Graph) {
      +        m_max_vertex_in_degree =
      +          (std::max)(m_max_vertex_in_degree, get(m_in_degree_map, v));
      +        m_max_vertex_out_degree =
      +          (std::max)(m_max_vertex_out_degree, out_degree(v, g));
      +      }
      +    }
       
           size_type operator()(vertex_t v) const {
      -      return (num_vertices(m_g) + 1) * out_degree(v, m_g)
      +      return (m_max_vertex_in_degree + 1) * out_degree(v, m_g)
               + get(m_in_degree_map, v);
           }
           // The largest possible vertex invariant number
           size_type max BOOST_PREVENT_MACRO_SUBSTITUTION () const { 
      -      return num_vertices(m_g) * num_vertices(m_g) + num_vertices(m_g);
      +      return (m_max_vertex_in_degree + 2) * m_max_vertex_out_degree + 1;
           }
         private:
           InDegreeMap m_in_degree_map;
      +    size_type m_max_vertex_in_degree;
      +    size_type m_max_vertex_out_degree;
           const Graph& m_g;
         };
       
      
      From 66cd415568e26ade0704326484bdcb4ce12ff4b5 Mon Sep 17 00:00:00 2001
      From: Jeremiah Willcock 
      Date: Sat, 19 Feb 2011 04:17:48 +0000
      Subject: [PATCH 047/333] Fixed typo as suggested by Shaun Jackman
      
      [SVN r69021]
      ---
       include/boost/graph/transitive_reduction.hpp | 2 +-
       1 file changed, 1 insertion(+), 1 deletion(-)
      
      diff --git a/include/boost/graph/transitive_reduction.hpp b/include/boost/graph/transitive_reduction.hpp
      index 44dfee989..f7cb34b8c 100644
      --- a/include/boost/graph/transitive_reduction.hpp
      +++ b/include/boost/graph/transitive_reduction.hpp
      @@ -99,7 +99,7 @@ transitive_reduction(const Graph& g, GraphTR& tr,
               {
                   //and run through all vertices in topological order
                   typename std::vector::reverse_iterator
      -                rit = topo_order.rbegin();
      +                rit = topo_order.rbegin(),
                       rend = topo_order.rend();
                   for(; rit != rend; ++rit ) {
                       //looking if they are successors of *it
      
      From b52d4724c2a027d339be0a002264f8e18f13f6d5 Mon Sep 17 00:00:00 2001
      From: Jeremiah Willcock 
      Date: Fri, 25 Feb 2011 06:37:46 +0000
      Subject: [PATCH 048/333] Removed obsolete (and unused) file
      
      [SVN r69263]
      ---
       include/boost/graph/detail/is_same.hpp | 48 --------------------------
       1 file changed, 48 deletions(-)
       delete mode 100644 include/boost/graph/detail/is_same.hpp
      
      diff --git a/include/boost/graph/detail/is_same.hpp b/include/boost/graph/detail/is_same.hpp
      deleted file mode 100644
      index 07330d301..000000000
      --- a/include/boost/graph/detail/is_same.hpp
      +++ /dev/null
      @@ -1,48 +0,0 @@
      -//=======================================================================
      -// Copyright 1997, 1998, 1999, 2000 University of Notre Dame.
      -// Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek
      -//
      -// 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_GRAPH_DETAIL_IS_SAME_HPP
      -#define BOOST_GRAPH_DETAIL_IS_SAME_HPP
      -
      -// Deprecate the use of this header.
      -// TODO: Remove this file from trunk/release in 1.41/1.42.
      -#if defined(_MSC_VER) || defined(__BORLANDC__) || defined(__DMC__)
      -#  pragma message ("Warning: This header is deprecated. Please use: boost/type_traits/is_same.hpp")
      -#elif defined(__GNUC__) || defined(__HP_aCC) || defined(__SUNPRO_CC) || defined(__IBMCPP__)
      -#  warning "This header is deprecated. Please use: boost/type_traits/is_same.hpp"
      -#endif
      -
      -#include 
      -
      -namespace boost {
      -  struct false_tag;
      -  struct true_tag;
      -
      -  namespace graph_detail {
      -    
      -#if !defined BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
      -    template 
      -    struct is_same {
      -      typedef boost::false_tag is_same_tag; 
      -    };
      -    template 
      -    struct is_same {
      -      typedef boost::true_tag is_same_tag;
      -    };
      -#else
      -    template 
      -    struct is_same {
      -      enum { Unum = U::num, Vnum = V::num };
      -      typedef typename mpl::if_c< (Unum == Vnum),
      -               boost::true_tag, boost::false_tag>::type is_same_tag;
      -    };
      -#endif
      -  } // namespace graph_detail
      -} // namespace boost
      -
      -#endif
      
      From fd549fe0faf62c93c7e332c7bdfe991eb828056a Mon Sep 17 00:00:00 2001
      From: Jeremiah Willcock 
      Date: Mon, 28 Feb 2011 22:41:34 +0000
      Subject: [PATCH 049/333] Made filtered_graph work with bundled graph
       properties by fixing bundle_type template; probably fixed other adapters as
       well
      
      [SVN r69404]
      ---
       include/boost/graph/graph_traits.hpp | 13 +++++++++++++
       include/boost/graph/properties.hpp   |  3 ++-
       2 files changed, 15 insertions(+), 1 deletion(-)
      
      diff --git a/include/boost/graph/graph_traits.hpp b/include/boost/graph/graph_traits.hpp
      index fd1b0415c..257438f5a 100644
      --- a/include/boost/graph/graph_traits.hpp
      +++ b/include/boost/graph/graph_traits.hpp
      @@ -217,6 +217,11 @@ namespace boost {
           //?? not the right place ?? Lee
           typedef boost::forward_traversal_tag multi_pass_input_iterator_tag;
       
      +    // Forward declare graph_bundle_t property name (from
      +    // boost/graph/properties.hpp, which includes this file) for
      +    // bundled_result.
      +    enum graph_bundle_t {graph_bundle};
      +
           template 
           struct graph_property_type {
             typedef typename G::graph_property_type type;
      @@ -261,6 +266,14 @@ namespace boost {
                   typedef typename bundler::type type;
               };
       
      +        template
      +        class bundled_result {
      +            typedef typename graph_traits::vertex_descriptor Vertex;
      +            typedef graph_bundle_type bundler;
      +        public:
      +            typedef typename bundler::type type;
      +        };
      +
           } } // namespace graph::detail
       
           namespace graph_detail {
      diff --git a/include/boost/graph/properties.hpp b/include/boost/graph/properties.hpp
      index f4c57ea25..dd7a73576 100644
      --- a/include/boost/graph/properties.hpp
      +++ b/include/boost/graph/properties.hpp
      @@ -126,7 +126,8 @@ namespace boost {
         BOOST_DEF_PROPERTY(graph, visitor);
       
         // These tags are used for property bundles
      -  BOOST_DEF_PROPERTY(graph, bundle);
      +  // BOOST_DEF_PROPERTY(graph, bundle); -- needed in graph_traits.hpp, so enum is defined there
      +  BOOST_INSTALL_PROPERTY(graph, bundle);
         BOOST_DEF_PROPERTY(vertex, bundle);
         BOOST_DEF_PROPERTY(edge, bundle);
       
      
      From 516c833574e10e924ca3874616a595721dca30a5 Mon Sep 17 00:00:00 2001
      From: Jeremiah Willcock 
      Date: Tue, 1 Mar 2011 03:20:29 +0000
      Subject: [PATCH 050/333] Removed superseded workaround from reverse_graph
      
      [SVN r69430]
      ---
       include/boost/graph/reverse_graph.hpp | 6 ------
       1 file changed, 6 deletions(-)
      
      diff --git a/include/boost/graph/reverse_graph.hpp b/include/boost/graph/reverse_graph.hpp
      index 30d303b19..4067f2c2e 100644
      --- a/include/boost/graph/reverse_graph.hpp
      +++ b/include/boost/graph/reverse_graph.hpp
      @@ -90,12 +90,6 @@ class reverse_graph {
           typename graph::detail::bundled_result::type const&
           operator[](Descriptor x) const
           { return m_g[x]; }
      -
      -    typename boost::graph_property_type::type& operator[](graph_bundle_t)
      -    { return get_property(*this); }
      -
      -    typename boost::graph_property_type::type const& operator[](graph_bundle_t) const
      -    { return get_property(*this); }
       #endif // BOOST_GRAPH_NO_BUNDLED_PROPERTIES
       
           static vertex_descriptor null_vertex()
      
      From f52b7df417b5e87073709abc8b8f2e4b39686cf8 Mon Sep 17 00:00:00 2001
      From: Jeremiah Willcock 
      Date: Mon, 7 Mar 2011 19:28:34 +0000
      Subject: [PATCH 051/333] Added includes of  for Clang/libc++
      
      [SVN r69629]
      ---
       include/boost/graph/graph_traits.hpp | 1 +
       test/astar_search_test.cpp           | 1 +
       2 files changed, 2 insertions(+)
      
      diff --git a/include/boost/graph/graph_traits.hpp b/include/boost/graph/graph_traits.hpp
      index 257438f5a..fad82f9d2 100644
      --- a/include/boost/graph/graph_traits.hpp
      +++ b/include/boost/graph/graph_traits.hpp
      @@ -12,6 +12,7 @@
       
       #include 
       #include 
      +#include  /* Primarily for std::pair */
       #include 
       #include 
       #include 
      diff --git a/test/astar_search_test.cpp b/test/astar_search_test.cpp
      index 36fb0a47d..b108bcb25 100644
      --- a/test/astar_search_test.cpp
      +++ b/test/astar_search_test.cpp
      @@ -15,6 +15,7 @@
       #include 
       #include 
       #include 
      +#include 
       #include 
       #include 
       #include 
      
      From 06bdbbcbba0319f9dc1b57f729481dc138342867 Mon Sep 17 00:00:00 2001
      From: Jeremiah Willcock 
      Date: Tue, 8 Mar 2011 20:53:50 +0000
      Subject: [PATCH 052/333] Changed concepts to use proper names for property
       types
      
      [SVN r69726]
      ---
       include/boost/graph/graph_concepts.hpp | 4 ++--
       1 file changed, 2 insertions(+), 2 deletions(-)
      
      diff --git a/include/boost/graph/graph_concepts.hpp b/include/boost/graph/graph_concepts.hpp
      index 7c2b2795b..f382edf7f 100644
      --- a/include/boost/graph/graph_concepts.hpp
      +++ b/include/boost/graph/graph_concepts.hpp
      @@ -342,7 +342,7 @@ typename T::ThereReallyIsNoMemberByThisNameInT vertices(T const&);
               }
               G g;
               typename graph_traits::vertex_descriptor v;
      -        typename vertex_property::type vp;
      +        typename vertex_property_type::type vp;
           };
       
           BOOST_concept(EdgeMutablePropertyGraph,(G))
      @@ -356,7 +356,7 @@ typename T::ThereReallyIsNoMemberByThisNameInT vertices(T const&);
               G g;
               std::pair p;
               typename graph_traits::vertex_descriptor u, v;
      -        typename edge_property::type ep;
      +        typename edge_property_type::type ep;
           };
       
           BOOST_concept(AdjacencyMatrix,(G))
      
      From 4b1c5fe438b7152dea3b1264d069155a211effb2 Mon Sep 17 00:00:00 2001
      From: Jeremiah Willcock 
      Date: Sat, 2 Apr 2011 18:43:03 +0000
      Subject: [PATCH 053/333] Fixed types in bundled property docs; fixes #5410
      
      [SVN r70875]
      ---
       doc/bundles.html | 6 +++---
       1 file changed, 3 insertions(+), 3 deletions(-)
      
      diff --git a/doc/bundles.html b/doc/bundles.html
      index 54e1fd35f..340b94830 100644
      --- a/doc/bundles.html
      +++ b/doc/bundles.html
      @@ -143,7 +143,7 @@ 

      Accessing bundled properties

      map[v].zipcodes.push_back(12180); Map::edge_descriptor e = *out_edges(v, map).first; map[e].name = "I-87"; -map[e].miles = 10; +map[e].miles = 10.; map[e].speed_limit = 65; map[e].lanes = 4; map[e].divided = true; @@ -186,8 +186,8 @@

      Properties maps from bundled properties

      get(vertex_index, map))));
      -

      The type of the returned property map is property_map<Map, int Highway::*>::type -or property_map<Map, int Highway::*>::const_type, depending on whether the graph +

      The type of the returned property map is property_map<Map, double Highway::*>::type +or property_map<Map, double Highway::*>::const_type, depending on whether the graph map is non-constant or constant.

      You may also access the entire vertex or edge bundle as a property map From 1fa0cd9a26aa62b2b57cb98c7ae2d9b61648342c Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Sun, 10 Apr 2011 20:01:06 +0000 Subject: [PATCH 054/333] Fixed C++0x array ambiguity [SVN r71166] --- test/random_spanning_tree_test.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/random_spanning_tree_test.cpp b/test/random_spanning_tree_test.cpp index db31e1424..48ae405f2 100644 --- a/test/random_spanning_tree_test.cpp +++ b/test/random_spanning_tree_test.cpp @@ -48,7 +48,7 @@ void write_spanning_tree(const Graph& g, PredMap pred, WeightMap weight, string int main(int, char**) { - array sizes = {{ 5, 5 }}; + boost::array sizes = {{ 5, 5 }}; graph_type g(sizes); shared_array_property_map::const_type> pred(num_vertices(g), get(vertex_index, g)); From 3131ffa45420a5badeab5a13b2bdcf1c14341201 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Thu, 14 Apr 2011 02:30:56 +0000 Subject: [PATCH 055/333] Added note about broken example [SVN r71238] --- example/min_max_paths.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/example/min_max_paths.cpp b/example/min_max_paths.cpp index 42a740b68..f32dd76e2 100644 --- a/example/min_max_paths.cpp +++ b/example/min_max_paths.cpp @@ -6,6 +6,9 @@ // accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) //======================================================================= + +#error "This example appears to be incorrect; it uses edge weights that are smaller than 0 using the comparison operator passed to Dijkstra's algorithm, which is not allowed." + #include #include From 19b05b0caeaafc2a69c72e104bbf7d2e69fe7c9f Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Fri, 15 Apr 2011 22:11:40 +0000 Subject: [PATCH 056/333] Fixed typo [SVN r71300] --- doc/floyd_warshall_shortest.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/floyd_warshall_shortest.html b/doc/floyd_warshall_shortest.html index ab407a6c0..7d110a80a 100644 --- a/doc/floyd_warshall_shortest.html +++ b/doc/floyd_warshall_shortest.html @@ -134,7 +134,7 @@

      Named Parameters

      The value used to initialize the distance for each vertex before starting the algorithm, and to represent the distance between vertices -for which there is not path. Should be larger than any possible valid +for which there is no path. Should be larger than any possible valid path length. The argument type must match the value type of the WeightMap.
      From b407ea93098e7d0b872ac9e136d5007a00792617 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Mon, 25 Apr 2011 21:10:58 +0000 Subject: [PATCH 057/333] Fixes [SVN r71489] --- doc/write-graphviz.html | 40 ++++++++++++++++++++-------------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/doc/write-graphviz.html b/doc/write-graphviz.html index 5ae376c52..9af6e7b7b 100644 --- a/doc/write-graphviz.html +++ b/doc/write-graphviz.html @@ -134,7 +134,7 @@

      public: label_writer(Name _name) : name(_name) {} template <class VertexOrEdge> - void operator()(std::ostream& out, const VertexOrEdge& v) const { + void operator()(std::ostream& out, const VertexOrEdge& v) const { out << "[label=\"" << name[v] << "\"]"; } private: @@ -154,13 +154,13 @@

      A PropertyWriter for graphs is a functor which is called with one parameter of type std::ostream and should print a series of graph properties. The following -code excerpt is an example of a PropertyWriter for a graph. +code excerpt is an example of a PropertyWriter for a graph:
         struct sample_graph_writer {
      -    void operator()(std::ostream& out) const {
      -      out << "graph [bgcolor=lightgrey]" << std::endl;
      -      out << "node [shape=circle color=white]" << std::endl;
      -      out << "edge [style=dashed]" << std::endl;
      +    void operator()(std::ostream& out) const {
      +      out << "graph [bgcolor=lightgrey]" << std::endl;
      +      out << "node [shape=circle color=white]" << std::endl;
      +      out << "edge [style=dashed]" << std::endl;
           }
         };
       }
      @@ -168,9 +168,9 @@ 

      There exists a class default_writer, which can be used as both -vertex/edge and graph property writer, and does nothing. It comes handy when -only edge properties must be written, but function interface requries to pass -vertex property writer as well. +vertex/edge and graph property writer, and does nothing. It is useful when +only edge properties must be written, but the function interface also requires a +vertex property writer.

      Parameters

      OUT: std::ostream& out @@ -181,38 +181,38 @@

      Parameters

      IN: VertexAndEdgeListGraph& g
      A directed or undirected graph. The graph's type must be a model of - VertexAndEdgeListGraph. Also the + VertexAndEdgeListGraph. In most cases, the graph must have an internal vertex_index property map.
      IN: VertexPropertyWriter vpw
      - A functor that models PropertyWriter concept to print + A functor that models PropertyWriter to print properties of a vertex.
      Default: default_writer()
      IN: EdgePropertyWriter epw
      - A functor that models PropertyWriter concept to print + A functor that models PropertyWriter to print properties of an edge.
      Default: default_writer()
      IN: GraphPropertyWriter epw
      - A functor that models PropertyWriter concept to print - properties of a graph.
      + A functor that models PropertyWriter to print + properties of the graph.
      Default: default_writer()
      -IN: dynamic_properties& dp +IN: dynamic_properties& dp
      Contains all of the vertex and edge properties that should be emitted by the GraphViz writer.
      -IN: const std::string& node_id +IN: const std::string& node_id
      The name of the property map that provides identifiers for the vertices in the graph.
      @@ -221,15 +221,15 @@

      Parameters

      IN: VertexID vertex_id
      - A property map that models Readable Property Map whose key type is the vertex descriptor of the graph and whose value type can be written to a stream. The value should be a unique descriptor that can be used to name a node in a Graphviz file (so it should not, for instance, have any spaces in it).
      -Default: If no dynamic_properties object is provided, get(vertex_index, g). Otherwise, a dynamic property map that accesses the property map named node_id. + A property map that models Readable Property Map, whose key type is the vertex descriptor of the graph, and whose value type can be written to a stream. The value should be a unique descriptor for each vertex, and will be used to name each node in the Graphviz file (it will be escaped properly for Graphviz output).
      +Default: If no dynamic_properties object is provided, get(vertex_index, g). Otherwise, a dynamic property map that accesses the property map in dp whose name is given by the node_id parameter.

      Example

      -This example demonstrates using BGL-graphviz interface to write -a BGL graph into a graphviz format file. +This example demonstrates using the BGL-Graphviz interface to write +a BGL graph into a Graphviz format file.
       #include <boost/graph/graphviz.hpp>
      
      From a4af894285fcff0be9154004c3e137774d4fee84 Mon Sep 17 00:00:00 2001
      From: Jeremiah Willcock 
      Date: Fri, 13 May 2011 23:50:01 +0000
      Subject: [PATCH 058/333] Changed to explicit stack as suggested by Aaron
       Windsor
      
      [SVN r71929]
      ---
       include/boost/graph/chrobak_payne_drawing.hpp | 18 ++++++++++++++----
       1 file changed, 14 insertions(+), 4 deletions(-)
      
      diff --git a/include/boost/graph/chrobak_payne_drawing.hpp b/include/boost/graph/chrobak_payne_drawing.hpp
      index 9e3a2f368..498c6f674 100644
      --- a/include/boost/graph/chrobak_payne_drawing.hpp
      +++ b/include/boost/graph/chrobak_payne_drawing.hpp
      @@ -34,12 +34,22 @@ namespace boost
                                   VertexToVertexMap left,
                                   VertexToVertexMap right)
           {
      -      if (v != graph_traits::null_vertex())
      -        {
      +      typedef typename graph_traits::vertex_descriptor vertex_descriptor;
      +      // Suggestion of explicit stack from Aaron Windsor to avoid system stack
      +      // overflows.
      +      typedef std::pair stack_entry;
      +      std::stack st;
      +      st.push(stack_entry(v, offset));
      +      while (!st.empty()) {
      +        vertex_descriptor v = st.top().first;
      +        std::size_t offset = st.top().second;
      +        st.pop();
      +        if (v != graph_traits::null_vertex()) {
                 x[v] += delta_x[v] + offset;
      -          accumulate_offsets(left[v], x[v], g, x, delta_x, left, right);
      -          accumulate_offsets(right[v], x[v], g, x, delta_x, left, right);
      +          st.push(stack_entry(left[v], x[v]));
      +          st.push(stack_entry(right[v], x[v]));
               }
      +      }
           }
       
         } /*namespace detail*/ } /*namespace graph*/
      
      From c5780610c63958329db0fbbb80afb0933319f71f Mon Sep 17 00:00:00 2001
      From: Jeremiah Willcock 
      Date: Fri, 24 Jun 2011 22:49:29 +0000
      Subject: [PATCH 059/333] Changed grid_graph to directed to match differing
       edge indices in documentation
      
      [SVN r72747]
      ---
       include/boost/graph/grid_graph.hpp | 2 +-
       1 file changed, 1 insertion(+), 1 deletion(-)
      
      diff --git a/include/boost/graph/grid_graph.hpp b/include/boost/graph/grid_graph.hpp
      index 9eff52591..08236391b 100644
      --- a/include/boost/graph/grid_graph.hpp
      +++ b/include/boost/graph/grid_graph.hpp
      @@ -268,7 +268,7 @@ namespace boost {
           typedef transform_iterator adjacency_iterator;
       
           // categories
      -    typedef undirected_tag directed_category;
      +    typedef directed_tag directed_category;
           typedef disallow_parallel_edge_tag edge_parallel_category;    
           struct traversal_category : virtual public incidence_graph_tag,
                                       virtual public adjacency_graph_tag,
      
      From 2c3505aec9749ea158237c37a188a0b9b2e49a49 Mon Sep 17 00:00:00 2001
      From: Jeremiah Willcock 
      Date: Fri, 1 Jul 2011 19:36:08 +0000
      Subject: [PATCH 060/333] Fixed ith_bandwidth for directed graphs; changed
       bandwidth to use the graph edges rather than scanning the out edges of every
       vertex; other small fixes
      
      [SVN r72837]
      ---
       doc/bandwidth.html                |  4 ++--
       include/boost/graph/bandwidth.hpp | 22 +++++++++++++---------
       2 files changed, 15 insertions(+), 11 deletions(-)
      
      diff --git a/doc/bandwidth.html b/doc/bandwidth.html
      index b02f770d9..93c2d20b2 100644
      --- a/doc/bandwidth.html
      +++ b/doc/bandwidth.html
      @@ -31,10 +31,10 @@ 

      bandwidth(const Graph& g, VertexIndexMap index_map)

      -The bandwidth of an undirected graph is the maximum +The bandwidth of a graph is the maximum distance between two adjacent vertices, with distance measured on a line upon which the vertices have been placed at unit intervals. To -put it another way, if the vertices of an undirected graph +put it another way, if the vertices of a graph G=(V,E) are each assigned an index from zero to |V| - 1 given by index[v], then the bandwidth of G is

      diff --git a/include/boost/graph/bandwidth.hpp b/include/boost/graph/bandwidth.hpp index 0bfeefb99..e8e7bf2cf 100644 --- a/include/boost/graph/bandwidth.hpp +++ b/include/boost/graph/bandwidth.hpp @@ -21,15 +21,14 @@ namespace boost { VertexIndexMap index) { BOOST_USING_STD_MAX(); - typedef typename graph_traits::vertices_size_type size_type; - size_type b = 0; + using std::abs; + typedef typename graph_traits::vertices_size_type vertices_size_type; + vertices_size_type b = 0; typename graph_traits::out_edge_iterator e, end; for (boost::tie(e, end) = out_edges(i, g); e != end; ++e) { int f_i = get(index, i); int f_j = get(index, target(*e, g)); - using namespace std; // to call abs() unqualified - if(f_i > f_j) - b = max BOOST_PREVENT_MACRO_SUBSTITUTION (b, size_type(f_i - f_j)); + b = max BOOST_PREVENT_MACRO_SUBSTITUTION (b, vertices_size_type(abs(f_i - f_j))); } return b; } @@ -47,10 +46,15 @@ namespace boost { bandwidth(const Graph& g, VertexIndexMap index) { BOOST_USING_STD_MAX(); - typename graph_traits::vertices_size_type b = 0; - typename graph_traits::vertex_iterator i, end; - for (boost::tie(i, end) = vertices(g); i != end; ++i) - b = max BOOST_PREVENT_MACRO_SUBSTITUTION (b, ith_bandwidth(*i, g, index)); + using std::abs; + typedef typename graph_traits::vertices_size_type vertices_size_type; + vertices_size_type b = 0; + typename graph_traits::edge_iterator i, end; + for (boost::tie(i, end) = edges(g); i != end; ++i) { + int f_i = get(index, source(*i, g)); + int f_j = get(index, target(*i, g)); + b = max BOOST_PREVENT_MACRO_SUBSTITUTION (b, vertices_size_type(abs(f_i - f_j))); + } return b; } From 55b82bd1f24dca90e3cc06eb49e1627dc29472e9 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Thu, 7 Jul 2011 21:07:41 +0000 Subject: [PATCH 061/333] Applied patch from #5659, plus made similar changes to other algorithms that have inf parameters; did not add inf parameters to algorithms that did not already have them; fixes #5659 [SVN r72960] --- include/boost/graph/astar_search.hpp | 10 ++++++---- include/boost/graph/dag_shortest_paths.hpp | 8 +++++--- include/boost/graph/dijkstra_shortest_paths.hpp | 8 +++++--- .../dijkstra_shortest_paths_no_color_map.hpp | 8 +++++--- include/boost/graph/floyd_warshall_shortest.hpp | 16 ++++++++++------ include/boost/graph/relax.hpp | 6 +++++- 6 files changed, 36 insertions(+), 20 deletions(-) diff --git a/include/boost/graph/astar_search.hpp b/include/boost/graph/astar_search.hpp index ae60113da..042ffec4a 100644 --- a/include/boost/graph/astar_search.hpp +++ b/include/boost/graph/astar_search.hpp @@ -325,6 +325,7 @@ namespace boost { typename detail::map_maker::map_type distance_map_type; typedef typename boost::property_traits::value_type D; + const D inf = arg_pack[_distance_inf | (std::numeric_limits::max)()]; astar_search (g, s, h, @@ -336,8 +337,8 @@ namespace boost { detail::override_const_property(arg_pack, _vertex_index_map, g, vertex_index), detail::make_color_map_from_arg_pack(g, arg_pack), arg_pack[_distance_compare | std::less()], - arg_pack[_distance_combine | closed_plus()], - arg_pack[_distance_inf | (std::numeric_limits::max)()], + arg_pack[_distance_combine | closed_plus(inf)], + inf, arg_pack[_distance_zero | D()]); } @@ -358,6 +359,7 @@ namespace boost { arg_pack_type, tag::weight_map, edge_weight_t, VertexListGraph>::type weight_map_type; typedef typename boost::property_traits::value_type D; + const D inf = arg_pack[_distance_inf | (std::numeric_limits::max)()]; astar_search_no_init (g, s, h, arg_pack[_visitor | make_astar_visitor(null_visitor())], @@ -368,8 +370,8 @@ namespace boost { detail::override_const_property(arg_pack, _vertex_index_map, g, vertex_index), detail::make_color_map_from_arg_pack(g, arg_pack), arg_pack[_distance_compare | std::less()], - arg_pack[_distance_combine | closed_plus()], - arg_pack[_distance_inf | (std::numeric_limits::max)()], + arg_pack[_distance_combine | closed_plus(inf)], + inf, arg_pack[_distance_zero | D()]); } diff --git a/include/boost/graph/dag_shortest_paths.hpp b/include/boost/graph/dag_shortest_paths.hpp index a46de9145..325d1516c 100644 --- a/include/boost/graph/dag_shortest_paths.hpp +++ b/include/boost/graph/dag_shortest_paths.hpp @@ -88,14 +88,16 @@ namespace boost { { typedef typename property_traits::value_type D; dummy_property_map p_map; + D inf = + choose_param(get_param(params, distance_inf_t()), + (std::numeric_limits::max)()); dag_shortest_paths (g, s, distance, weight, color, choose_param(get_param(params, vertex_predecessor), p_map), vis, choose_param(get_param(params, distance_compare_t()), std::less()), - choose_param(get_param(params, distance_combine_t()), closed_plus()), - choose_param(get_param(params, distance_inf_t()), - (std::numeric_limits::max)()), + choose_param(get_param(params, distance_combine_t()), closed_plus(inf)), + inf, choose_param(get_param(params, distance_zero_t()), D())); } diff --git a/include/boost/graph/dijkstra_shortest_paths.hpp b/include/boost/graph/dijkstra_shortest_paths.hpp index 5b39cb385..e0848e502 100644 --- a/include/boost/graph/dijkstra_shortest_paths.hpp +++ b/include/boost/graph/dijkstra_shortest_paths.hpp @@ -420,6 +420,9 @@ namespace boost { dummy_property_map p_map; typedef typename property_traits::value_type D; + D inf = choose_param(get_param(params, distance_inf_t()), + (std::numeric_limits::max)()); + dijkstra_shortest_paths (g, s, choose_param(get_param(params, vertex_predecessor), p_map), @@ -427,9 +430,8 @@ namespace boost { choose_param(get_param(params, distance_compare_t()), std::less()), choose_param(get_param(params, distance_combine_t()), - closed_plus()), - choose_param(get_param(params, distance_inf_t()), - (std::numeric_limits::max)()), + closed_plus(inf)), + inf, choose_param(get_param(params, distance_zero_t()), D()), choose_param(get_param(params, graph_visitor), diff --git a/include/boost/graph/dijkstra_shortest_paths_no_color_map.hpp b/include/boost/graph/dijkstra_shortest_paths_no_color_map.hpp index 443984ff0..ca2a1ebd8 100644 --- a/include/boost/graph/dijkstra_shortest_paths_no_color_map.hpp +++ b/include/boost/graph/dijkstra_shortest_paths_no_color_map.hpp @@ -186,6 +186,9 @@ namespace boost { dummy_property_map predecessor_map; typedef typename property_traits::value_type DistanceType; + DistanceType inf = + choose_param(get_param(params, distance_inf_t()), + (std::numeric_limits::max)()); dijkstra_shortest_paths_no_color_map (graph, start_vertex, choose_param(get_param(params, vertex_predecessor), predecessor_map), @@ -193,9 +196,8 @@ namespace boost { choose_param(get_param(params, distance_compare_t()), std::less()), choose_param(get_param(params, distance_combine_t()), - closed_plus()), - choose_param(get_param(params, distance_inf_t()), - (std::numeric_limits::max)()), + closed_plus(inf)), + inf, choose_param(get_param(params, distance_zero_t()), DistanceType()), choose_param(get_param(params, graph_visitor), diff --git a/include/boost/graph/floyd_warshall_shortest.hpp b/include/boost/graph/floyd_warshall_shortest.hpp index 48dba7126..3e95e1b06 100644 --- a/include/boost/graph/floyd_warshall_shortest.hpp +++ b/include/boost/graph/floyd_warshall_shortest.hpp @@ -163,14 +163,16 @@ namespace boost const bgl_named_params& params) { typedef typename property_traits::value_type WM; + WM inf = + choose_param(get_param(params, distance_inf_t()), + std::numeric_limits::max BOOST_PREVENT_MACRO_SUBSTITUTION()); return floyd_warshall_initialized_all_pairs_shortest_paths(g, d, choose_param(get_param(params, distance_compare_t()), std::less()), choose_param(get_param(params, distance_combine_t()), - closed_plus()), - choose_param(get_param(params, distance_inf_t()), - std::numeric_limits::max BOOST_PREVENT_MACRO_SUBSTITUTION()), + closed_plus(inf)), + inf, choose_param(get_param(params, distance_zero_t()), WM())); } @@ -185,13 +187,15 @@ namespace boost { typedef typename property_traits::value_type WM; + WM inf = + choose_param(get_param(params, distance_inf_t()), + std::numeric_limits::max BOOST_PREVENT_MACRO_SUBSTITUTION()); return floyd_warshall_all_pairs_shortest_paths(g, d, w, choose_param(get_param(params, distance_compare_t()), std::less()), choose_param(get_param(params, distance_combine_t()), - closed_plus()), - choose_param(get_param(params, distance_inf_t()), - std::numeric_limits::max BOOST_PREVENT_MACRO_SUBSTITUTION()), + closed_plus(inf)), + inf, choose_param(get_param(params, distance_zero_t()), WM())); } diff --git a/include/boost/graph/relax.hpp b/include/boost/graph/relax.hpp index 1d2250a80..889f8206d 100644 --- a/include/boost/graph/relax.hpp +++ b/include/boost/graph/relax.hpp @@ -22,9 +22,13 @@ namespace boost { template struct closed_plus { + const T inf; + + closed_plus() : inf(std::numeric_limits::max()) { } + closed_plus(T inf) : inf(inf) { } + T operator()(const T& a, const T& b) const { using namespace std; - const T inf = (std::numeric_limits::max)(); if (a == inf) return inf; if (b == inf) return inf; return a + b; From 9cf1345871dca6cd7bc0c261f35bea4758cb8471 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Mon, 11 Jul 2011 19:54:19 +0000 Subject: [PATCH 062/333] Added built-in reverse edge map for max-flow [SVN r73006] --- include/boost/graph/grid_graph.hpp | 45 ++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/include/boost/graph/grid_graph.hpp b/include/boost/graph/grid_graph.hpp index 08236391b..ab6440850 100644 --- a/include/boost/graph/grid_graph.hpp +++ b/include/boost/graph/grid_graph.hpp @@ -89,6 +89,32 @@ namespace boost { typedef type const_type; }; + //========================== + // Reverse Edge Property Map + //========================== + + template + struct grid_graph_reverse_edge_map { + public: + typedef Descriptor value_type; + typedef Descriptor reference_type; + typedef reference_type reference; + typedef Descriptor key_type; + typedef readable_property_map_tag category; + + grid_graph_reverse_edge_map() { } + + value_type operator[](const key_type& key) const { + return (value_type(key.second, key.first)); + } + }; + + template + struct property_map { + typedef grid_graph_reverse_edge_map type; + typedef type const_type; + }; + //================= // Function Objects //================= @@ -971,6 +997,14 @@ namespace boost { BOOST_GRID_GRAPH_TYPE_MEM edges_size_type>(graph)); } + template + friend inline grid_graph_reverse_edge_map< + BOOST_GRID_GRAPH_TYPE_MEM edge_descriptor> + get(edge_reverse_t, const BOOST_GRID_GRAPH_TYPE& graph) { + return (grid_graph_reverse_edge_map< + BOOST_GRID_GRAPH_TYPE_MEM edge_descriptor>()); + } + template @@ -986,6 +1020,17 @@ namespace boost { typename Index> friend struct grid_graph_index_map; + template + friend inline Descriptor + get(const grid_graph_reverse_edge_map& rev_map, + const typename grid_graph_reverse_edge_map::key_type& key) + { + return (rev_map[key]); + } + + template + friend struct grid_graph_reverse_edge_map; + }; // grid_graph } // namespace boost From f98a8afdd641e0267e72a5240e932d1a32e97675 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Tue, 12 Jul 2011 01:26:09 +0000 Subject: [PATCH 063/333] Fixed to work with graphs whose vertex_index maps are not the identity [SVN r73009] --- include/boost/graph/push_relabel_max_flow.hpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/include/boost/graph/push_relabel_max_flow.hpp b/include/boost/graph/push_relabel_max_flow.hpp index 4044815d9..0e4577c2a 100644 --- a/include/boost/graph/push_relabel_max_flow.hpp +++ b/include/boost/graph/push_relabel_max_flow.hpp @@ -450,7 +450,7 @@ namespace boost { for (boost::tie(u_iter, u_end) = vertices(g); u_iter != u_end; ++u_iter) { u = *u_iter; put(color, u, ColorTraits::white()); - parent[u] = u; + parent[get(index, u)] = u; current[u] = out_edges(u, g); } // eliminate flow cycles and topologically order the vertices @@ -468,7 +468,7 @@ namespace boost { vertex_descriptor v = target(a, g); if (get(color, v) == ColorTraits::white()) { put(color, v, ColorTraits::gray()); - parent[v] = u; + parent[get(index, v)] = u; u = v; break; } else if (get(color, v) == ColorTraits::gray()) { @@ -523,12 +523,12 @@ namespace boost { bos_null = false; tos = u; } else { - topo_next[u] = tos; + topo_next[get(index, u)] = tos; tos = u; } } if (u != r) { - u = parent[u]; + u = parent[get(index, u)]; ++current[u].first; } else break; @@ -540,7 +540,7 @@ namespace boost { // return excess flows // note that the sink is not on the stack if (! bos_null) { - for (u = tos; u != bos; u = topo_next[u]) { + for (u = tos; u != bos; u = topo_next[get(index, u)]) { boost::tie(ai, a_end) = out_edges(u, g); while (get(excess_flow, u) > 0 && ai != a_end) { if (get(capacity, *ai) == 0 && is_residual_edge(*ai)) From 6edd466d865b72d274b71001ef18f6eeee26e803 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Tue, 12 Jul 2011 02:47:34 +0000 Subject: [PATCH 064/333] Weakened concept requirements [SVN r73010] --- include/boost/graph/boykov_kolmogorov_max_flow.hpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/include/boost/graph/boykov_kolmogorov_max_flow.hpp b/include/boost/graph/boykov_kolmogorov_max_flow.hpp index 6a4c4482f..3ae4c69d8 100644 --- a/include/boost/graph/boykov_kolmogorov_max_flow.hpp +++ b/include/boost/graph/boykov_kolmogorov_max_flow.hpp @@ -556,7 +556,7 @@ class bk_max_flow { * white() for sink tree, gray() for no tree */ inline tColorValue get_tree(vertex_descriptor v) const { - return m_tree_map[v]; + return get(m_tree_map, v); } /** @@ -564,7 +564,7 @@ class bk_max_flow { * for sink tree, gray() for no tree */ inline void set_tree(vertex_descriptor v, tColorValue t){ - m_tree_map[v] = t; + put(m_tree_map, v, t); } /** @@ -743,11 +743,11 @@ boykov_kolmogorov_max_flow(Graph& g, function_requires >(); //to have vertices(), num_vertices(), function_requires >(); //to have edges() function_requires >(); //to have source(), target() and out_edges() - function_requires >(); //read flow-values from edges + function_requires >(); //read flow-values from edges function_requires >(); //write flow-values to residuals - function_requires >(); //read out reverse edges + function_requires >(); //read out reverse edges function_requires >(); //store predecessor there - function_requires >(); //write corresponding tree + function_requires >(); //write corresponding tree function_requires >(); //write distance to source/sink function_requires >(); //get index 0...|V|-1 BOOST_ASSERT(num_vertices(g) >= 2 && src != sink); From b6c54fa390828163173390c70f38f5c776fc01be Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Wed, 13 Jul 2011 01:04:47 +0000 Subject: [PATCH 065/333] Weakened property map requirements further, removing uses of [] on property maps [SVN r73026] --- .../graph/boykov_kolmogorov_max_flow.hpp | 183 +++++++++--------- 1 file changed, 93 insertions(+), 90 deletions(-) diff --git a/include/boost/graph/boykov_kolmogorov_max_flow.hpp b/include/boost/graph/boykov_kolmogorov_max_flow.hpp index 3ae4c69d8..89bcfff2a 100644 --- a/include/boost/graph/boykov_kolmogorov_max_flow.hpp +++ b/include/boost/graph/boykov_kolmogorov_max_flow.hpp @@ -125,14 +125,14 @@ class bk_max_flow { // the residual capacity equal to the capacity edge_iterator ei, e_end; for(boost::tie(ei, e_end) = edges(m_g); ei != e_end; ++ei) { - m_res_cap_map[*ei] = m_cap_map[*ei]; - BOOST_ASSERT(m_rev_edge_map[m_rev_edge_map[*ei]] == *ei); //check if the reverse edge map is build up properly + put(m_res_cap_map, *ei, get(m_cap_map, *ei)); + BOOST_ASSERT(get(m_rev_edge_map, get(m_rev_edge_map, *ei)) == *ei); //check if the reverse edge map is build up properly } //init the search trees with the two terminals set_tree(m_source, tColorTraits::black()); set_tree(m_sink, tColorTraits::white()); - m_time_map[m_source] = 1; - m_time_map[m_sink] = 1; + put(m_time_map, m_source, 1); + put(m_time_map, m_sink, 1); } tEdgeVal max_flow(){ @@ -168,8 +168,8 @@ class bk_max_flow { edge_descriptor from_source = *ei; vertex_descriptor current_node = target(from_source, m_g); if(current_node == m_sink){ - tEdgeVal cap = m_res_cap_map[from_source]; - m_res_cap_map[from_source] = 0; + tEdgeVal cap = get(m_res_cap_map, from_source); + put(m_res_cap_map, from_source, 0); m_flow += cap; continue; } @@ -177,52 +177,52 @@ class bk_max_flow { bool is_there; boost::tie(to_sink, is_there) = lookup_edge(current_node, m_sink, m_g); if(is_there){ - tEdgeVal cap_from_source = m_res_cap_map[from_source]; - tEdgeVal cap_to_sink = m_res_cap_map[to_sink]; + tEdgeVal cap_from_source = get(m_res_cap_map, from_source); + tEdgeVal cap_to_sink = get(m_res_cap_map, to_sink); if(cap_from_source > cap_to_sink){ set_tree(current_node, tColorTraits::black()); add_active_node(current_node); set_edge_to_parent(current_node, from_source); - m_dist_map[current_node] = 1; - m_time_map[current_node] = 1; + put(m_dist_map, current_node, 1); + put(m_time_map, current_node, 1); // add stuff to flow and update residuals. we dont need to // update reverse_edges, as incoming/outgoing edges to/from // source/sink don't count for max-flow - m_res_cap_map[from_source] -= cap_to_sink; - m_res_cap_map[to_sink] = 0; + put(m_res_cap_map, from_source, get(m_res_cap_map, from_source) - cap_to_sink); + put(m_res_cap_map, to_sink, 0); m_flow += cap_to_sink; } else if(cap_to_sink > 0){ set_tree(current_node, tColorTraits::white()); add_active_node(current_node); set_edge_to_parent(current_node, to_sink); - m_dist_map[current_node] = 1; - m_time_map[current_node] = 1; + put(m_dist_map, current_node, 1); + put(m_time_map, current_node, 1); // add stuff to flow and update residuals. we dont need to update // reverse_edges, as incoming/outgoing edges to/from source/sink // don't count for max-flow - m_res_cap_map[to_sink] -= cap_from_source; - m_res_cap_map[from_source] = 0; + put(m_res_cap_map, to_sink, get(m_res_cap_map, to_sink) - cap_from_source); + put(m_res_cap_map, from_source, 0); m_flow += cap_from_source; } - } else if(m_res_cap_map[from_source]){ + } else if(get(m_res_cap_map, from_source)){ // there is no sink connect, so we can't augment this path, but to // avoid adding m_source to the active nodes, we just activate this // node and set the approciate things set_tree(current_node, tColorTraits::black()); set_edge_to_parent(current_node, from_source); - m_dist_map[current_node] = 1; - m_time_map[current_node] = 1; + put(m_dist_map, current_node, 1); + put(m_time_map, current_node, 1); add_active_node(current_node); } } for(boost::tie(ei, e_end) = out_edges(m_sink, m_g); ei != e_end; ++ei){ - edge_descriptor to_sink = m_rev_edge_map[*ei]; + edge_descriptor to_sink = get(m_rev_edge_map, *ei); vertex_descriptor current_node = source(to_sink, m_g); - if(m_res_cap_map[to_sink]){ + if(get(m_res_cap_map, to_sink)){ set_tree(current_node, tColorTraits::white()); set_edge_to_parent(current_node, to_sink); - m_dist_map[current_node] = 1; - m_time_map[current_node] = 1; + put(m_dist_map, current_node, 1); + put(m_time_map, current_node, 1); add_active_node(current_node); } } @@ -252,21 +252,21 @@ class bk_max_flow { } for(; m_last_grow_edge_it != m_last_grow_edge_end; ++m_last_grow_edge_it) { edge_descriptor out_edge = *m_last_grow_edge_it; - if(m_res_cap_map[out_edge] > 0){ //check if we have capacity left on this edge + if(get(m_res_cap_map, out_edge) > 0){ //check if we have capacity left on this edge vertex_descriptor other_node = target(out_edge, m_g); if(get_tree(other_node) == tColorTraits::gray()){ //it's a free node set_tree(other_node, tColorTraits::black()); //aquire other node to our search tree set_edge_to_parent(other_node, out_edge); //set us as parent - m_dist_map[other_node] = m_dist_map[current_node] + 1; //and update the distance-heuristic - m_time_map[other_node] = m_time_map[current_node]; + put(m_dist_map, other_node, get(m_dist_map, current_node) + 1); //and update the distance-heuristic + put(m_time_map, other_node, get(m_time_map, current_node)); add_active_node(other_node); } else if(get_tree(other_node) == tColorTraits::black()) { // we do this to get shorter paths. check if we are nearer to // the source as its parent is if(is_closer_to_terminal(current_node, other_node)){ set_edge_to_parent(other_node, out_edge); - m_dist_map[other_node] = m_dist_map[current_node] + 1; - m_time_map[other_node] = m_time_map[current_node]; + put(m_dist_map, other_node, get(m_dist_map, current_node) + 1); + put(m_time_map, other_node, get(m_time_map, current_node)); } } else{ BOOST_ASSERT(get_tree(other_node)==tColorTraits::white()); @@ -285,21 +285,21 @@ class bk_max_flow { boost::tie(m_last_grow_edge_it, m_last_grow_edge_end) = out_edges(current_node, m_g); } for(; m_last_grow_edge_it != m_last_grow_edge_end; ++m_last_grow_edge_it){ - edge_descriptor in_edge = m_rev_edge_map[*m_last_grow_edge_it]; - if(m_res_cap_map[in_edge] > 0){ //check if there is capacity left + edge_descriptor in_edge = get(m_rev_edge_map, *m_last_grow_edge_it); + if(get(m_res_cap_map, in_edge) > 0){ //check if there is capacity left vertex_descriptor other_node = source(in_edge, m_g); if(get_tree(other_node) == tColorTraits::gray()){ //it's a free node set_tree(other_node, tColorTraits::white()); //aquire that node to our search tree set_edge_to_parent(other_node, in_edge); //set us as parent add_active_node(other_node); //activate that node - m_dist_map[other_node] = m_dist_map[current_node] + 1; //set its distance - m_time_map[other_node] = m_time_map[current_node]; //and time + put(m_dist_map, other_node, get(m_dist_map, current_node) + 1); //set its distance + put(m_time_map, other_node, get(m_time_map, current_node));//and time } else if(get_tree(other_node) == tColorTraits::white()){ if(is_closer_to_terminal(current_node, other_node)){ //we are closer to the sink than its parent is, so we "adopt" him set_edge_to_parent(other_node, in_edge); - m_dist_map[other_node] = m_dist_map[current_node] + 1; - m_time_map[other_node] = m_time_map[current_node]; + put(m_dist_map, other_node, get(m_dist_map, current_node) + 1); + put(m_time_map, other_node, get(m_time_map, current_node)); } } else{ BOOST_ASSERT(get_tree(other_node)==tColorTraits::black()); @@ -340,18 +340,18 @@ class bk_max_flow { //now we push the found flow through the path //for each edge we saturate we have to look for the verts that belong to that edge, one of them becomes an orphans //now process the connecting edge - m_res_cap_map[e] -= bottleneck; - BOOST_ASSERT(m_res_cap_map[e] >= 0); - m_res_cap_map[m_rev_edge_map[e]] += bottleneck; + put(m_res_cap_map, e, get(m_res_cap_map, e) - bottleneck); + BOOST_ASSERT(get(m_res_cap_map, e) >= 0); + put(m_res_cap_map, get(m_rev_edge_map, e), get(m_res_cap_map, get(m_rev_edge_map, e)) + bottleneck); //now we follow the path back to the source vertex_descriptor current_node = source(e, m_g); while(current_node != m_source){ edge_descriptor pred = get_edge_to_parent(current_node); - m_res_cap_map[pred] -= bottleneck; - BOOST_ASSERT(m_res_cap_map[pred] >= 0); - m_res_cap_map[m_rev_edge_map[pred]] += bottleneck; - if(m_res_cap_map[pred] == 0){ + put(m_res_cap_map, pred, get(m_res_cap_map, pred) - bottleneck); + BOOST_ASSERT(get(m_res_cap_map, pred) >= 0); + put(m_res_cap_map, get(m_rev_edge_map, pred), get(m_res_cap_map, get(m_rev_edge_map, pred)) + bottleneck); + if(get(m_res_cap_map, pred) == 0){ set_no_parent(current_node); m_orphans.push_front(current_node); } @@ -361,10 +361,10 @@ class bk_max_flow { current_node = target(e, m_g); while(current_node != m_sink){ edge_descriptor pred = get_edge_to_parent(current_node); - m_res_cap_map[pred] -= bottleneck; - BOOST_ASSERT(m_res_cap_map[pred] >= 0); - m_res_cap_map[m_rev_edge_map[pred]] += bottleneck; - if(m_res_cap_map[pred] == 0){ + put(m_res_cap_map, pred, get(m_res_cap_map, pred) - bottleneck); + BOOST_ASSERT(get(m_res_cap_map, pred) >= 0); + put(m_res_cap_map, get(m_rev_edge_map, pred), get(m_res_cap_map, get(m_rev_edge_map, pred)) + bottleneck); + if(get(m_res_cap_map, pred) == 0){ set_no_parent(current_node); m_orphans.push_front(current_node); } @@ -380,19 +380,19 @@ class bk_max_flow { */ inline tEdgeVal find_bottleneck(edge_descriptor e){ BOOST_USING_STD_MIN(); - tEdgeVal minimum_cap = m_res_cap_map[e]; + tEdgeVal minimum_cap = get(m_res_cap_map, e); vertex_descriptor current_node = source(e, m_g); //first go back in the source tree while(current_node != m_source){ edge_descriptor pred = get_edge_to_parent(current_node); - minimum_cap = min BOOST_PREVENT_MACRO_SUBSTITUTION(minimum_cap, m_res_cap_map[pred]); + minimum_cap = min BOOST_PREVENT_MACRO_SUBSTITUTION(minimum_cap, get(m_res_cap_map, pred)); current_node = source(pred, m_g); } //then go forward in the sink-tree current_node = target(e, m_g); while(current_node != m_sink){ edge_descriptor pred = get_edge_to_parent(current_node); - minimum_cap = min BOOST_PREVENT_MACRO_SUBSTITUTION(minimum_cap, m_res_cap_map[pred]); + minimum_cap = min BOOST_PREVENT_MACRO_SUBSTITUTION(minimum_cap, get(m_res_cap_map, pred)); current_node = target(pred, m_g); } return minimum_cap; @@ -420,13 +420,13 @@ class bk_max_flow { edge_descriptor new_parent_edge; out_edge_iterator ei, e_end; for(boost::tie(ei, e_end) = out_edges(current_node, m_g); ei != e_end; ++ei){ - const edge_descriptor in_edge = m_rev_edge_map[*ei]; + const edge_descriptor in_edge = get(m_rev_edge_map, *ei); BOOST_ASSERT(target(in_edge, m_g) == current_node); //we should be the target of this edge - if(m_res_cap_map[in_edge] > 0){ + if(get(m_res_cap_map, in_edge) > 0){ vertex_descriptor other_node = source(in_edge, m_g); if(get_tree(other_node) == tColorTraits::black() && has_source_connect(other_node)){ - if(m_dist_map[other_node] < min_distance){ - min_distance = m_dist_map[other_node]; + if(get(m_dist_map, other_node) < min_distance){ + min_distance = get(m_dist_map, other_node); new_parent_edge = in_edge; } } @@ -434,15 +434,15 @@ class bk_max_flow { } if(min_distance != (std::numeric_limits::max)()){ set_edge_to_parent(current_node, new_parent_edge); - m_dist_map[current_node] = min_distance + 1; - m_time_map[current_node] = m_time; + put(m_dist_map, current_node, min_distance + 1); + put(m_time_map, current_node, m_time); } else{ - m_time_map[current_node] = 0; + put(m_time_map, current_node, 0); for(boost::tie(ei, e_end) = out_edges(current_node, m_g); ei != e_end; ++ei){ - edge_descriptor in_edge = m_rev_edge_map[*ei]; + edge_descriptor in_edge = get(m_rev_edge_map, *ei); vertex_descriptor other_node = source(in_edge, m_g); if(get_tree(other_node) == tColorTraits::black() && has_parent(other_node)){ - if(m_res_cap_map[in_edge] > 0){ + if(get(m_res_cap_map, in_edge) > 0){ add_active_node(other_node); } if(source(get_edge_to_parent(other_node), m_g) == current_node){ @@ -464,26 +464,26 @@ class bk_max_flow { tDistanceVal min_distance = (std::numeric_limits::max)(); for(boost::tie(ei, e_end) = out_edges(current_node, m_g); ei != e_end; ++ei){ const edge_descriptor out_edge = *ei; - if(m_res_cap_map[out_edge] > 0){ + if(get(m_res_cap_map, out_edge) > 0){ const vertex_descriptor other_node = target(out_edge, m_g); if(get_tree(other_node) == tColorTraits::white() && has_sink_connect(other_node)) - if(m_dist_map[other_node] < min_distance){ - min_distance = m_dist_map[other_node]; + if(get(m_dist_map, other_node) < min_distance){ + min_distance = get(m_dist_map, other_node); new_parent_edge = out_edge; } } } if(min_distance != (std::numeric_limits::max)()){ set_edge_to_parent(current_node, new_parent_edge); - m_dist_map[current_node] = min_distance + 1; - m_time_map[current_node] = m_time; + put(m_dist_map, current_node, min_distance + 1); + put(m_time_map, current_node, m_time); } else{ - m_time_map[current_node] = 0; + put(m_time_map, current_node, 0); for(boost::tie(ei, e_end) = out_edges(current_node, m_g); ei != e_end; ++ei){ const edge_descriptor out_edge = *ei; const vertex_descriptor other_node = target(out_edge, m_g); if(get_tree(other_node) == tColorTraits::white() && has_parent(other_node)){ - if(m_res_cap_map[out_edge] > 0){ + if(get(m_res_cap_map, out_edge) > 0){ add_active_node(other_node); } if(target(get_edge_to_parent(other_node), m_g) == current_node){ @@ -511,7 +511,7 @@ class bk_max_flow { //if it has no parent, this node can't be active (if its not source or sink) if(!has_parent(v) && v != m_source && v != m_sink){ m_active_nodes.pop(); - m_in_active_list_map[v] = false; + put(m_in_active_list_map, v, false); } else{ BOOST_ASSERT(get_tree(v) == tColorTraits::black() || get_tree(v) == tColorTraits::white()); return v; @@ -524,10 +524,10 @@ class bk_max_flow { */ inline void add_active_node(vertex_descriptor v){ BOOST_ASSERT(get_tree(v) != tColorTraits::gray()); - if(m_in_active_list_map[v]){ + if(get(m_in_active_list_map, v)){ return; } else{ - m_in_active_list_map[v] = true; + put(m_in_active_list_map, v, true); m_active_nodes.push(v); } } @@ -538,7 +538,7 @@ class bk_max_flow { inline void finish_node(vertex_descriptor v){ BOOST_ASSERT(m_active_nodes.front() == v); m_active_nodes.pop(); - m_in_active_list_map[v] = false; + put(m_in_active_list_map, v, false); m_last_grow_vertex = graph_traits::null_vertex(); } @@ -571,23 +571,23 @@ class bk_max_flow { * returns edge to parent vertex of v; */ inline edge_descriptor get_edge_to_parent(vertex_descriptor v) const{ - return m_pre_map[v]; + return get(m_pre_map, v); } /** * returns true if the edge stored in m_pre_map[v] is a valid entry */ inline bool has_parent(vertex_descriptor v) const{ - return m_has_parent_map[v]; + return get(m_has_parent_map, v); } /** * sets edge to parent vertex of v; */ inline void set_edge_to_parent(vertex_descriptor v, edge_descriptor f_edge_to_parent){ - BOOST_ASSERT(m_res_cap_map[f_edge_to_parent] > 0); - m_pre_map[v] = f_edge_to_parent; - m_has_parent_map[v] = true; + BOOST_ASSERT(get(m_res_cap_map, f_edge_to_parent) > 0); + put(m_pre_map, v, f_edge_to_parent); + put(m_has_parent_map, v, true); } /** @@ -595,7 +595,7 @@ class bk_max_flow { * entry an additional map) */ inline void set_no_parent(vertex_descriptor v){ - m_has_parent_map[v] = false; + put(m_has_parent_map, v, false); } /** @@ -607,13 +607,13 @@ class bk_max_flow { tDistanceVal current_distance = 0; vertex_descriptor current_vertex = v; while(true){ - if(m_time_map[current_vertex] == m_time){ + if(get(m_time_map, current_vertex) == m_time){ //we found a node which was already checked this round. use it for distance calculations - current_distance += m_dist_map[current_vertex]; + current_distance += get(m_dist_map, current_vertex); break; } if(current_vertex == m_sink){ - m_time_map[m_sink] = m_time; + put(m_time_map, m_sink, m_time); break; } if(has_parent(current_vertex)){ @@ -626,9 +626,10 @@ class bk_max_flow { } } current_vertex=v; - while(m_time_map[current_vertex] != m_time){ - m_dist_map[current_vertex] = current_distance--; - m_time_map[current_vertex] = m_time; + while(get(m_time_map, current_vertex) != m_time){ + put(m_dist_map, current_vertex, current_distance); + --current_distance; + put(m_time_map, current_vertex, m_time); current_vertex = target(get_edge_to_parent(current_vertex), m_g); } return true; @@ -643,13 +644,13 @@ class bk_max_flow { tDistanceVal current_distance = 0; vertex_descriptor current_vertex = v; while(true){ - if(m_time_map[current_vertex] == m_time){ + if(get(m_time_map, current_vertex) == m_time){ //we found a node which was already checked this round. use it for distance calculations - current_distance += m_dist_map[current_vertex]; + current_distance += get(m_dist_map, current_vertex); break; } if(current_vertex == m_source){ - m_time_map[m_source] = m_time; + put(m_time_map, m_source, m_time); break; } if(has_parent(current_vertex)){ @@ -662,9 +663,10 @@ class bk_max_flow { } } current_vertex=v; - while(m_time_map[current_vertex] != m_time){ - m_dist_map[current_vertex] = current_distance-- ; - m_time_map[current_vertex] = m_time; + while(get(m_time_map, current_vertex) != m_time){ + put(m_dist_map, current_vertex, current_distance); + --current_distance; + put(m_time_map, current_vertex, m_time); current_vertex = source(get_edge_to_parent(current_vertex), m_g); } return true; @@ -675,7 +677,8 @@ class bk_max_flow { */ inline bool is_closer_to_terminal(vertex_descriptor p, vertex_descriptor q){ //checks the timestamps first, to build no cycles, and after that the real distance - return (m_time_map[q] <= m_time_map[p] && m_dist_map[q] > m_dist_map[p]+1); + return (get(m_time_map, q) <= get(m_time_map, p) && + get(m_dist_map, q) > get(m_dist_map, p)+1); } //////// @@ -744,11 +747,11 @@ boykov_kolmogorov_max_flow(Graph& g, function_requires >(); //to have edges() function_requires >(); //to have source(), target() and out_edges() function_requires >(); //read flow-values from edges - function_requires >(); //write flow-values to residuals + function_requires >(); //write flow-values to residuals function_requires >(); //read out reverse edges - function_requires >(); //store predecessor there + function_requires >(); //store predecessor there function_requires >(); //write corresponding tree - function_requires >(); //write distance to source/sink + function_requires >(); //write distance to source/sink function_requires >(); //get index 0...|V|-1 BOOST_ASSERT(num_vertices(g) >= 2 && src != sink); From 8b4ac5cc39d119881e14a313760f446725846a2c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=BCrgen=20Hunold?= Date: Sat, 23 Jul 2011 09:24:35 +0000 Subject: [PATCH 066/333] Enable visibility support. Refs #2114. [SVN r73308] --- include/boost/graph/dll_import_export.hpp | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/include/boost/graph/dll_import_export.hpp b/include/boost/graph/dll_import_export.hpp index cc369d1d1..d03fcd3f2 100644 --- a/include/boost/graph/dll_import_export.hpp +++ b/include/boost/graph/dll_import_export.hpp @@ -13,15 +13,13 @@ #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 +#if defined(BOOST_ALL_DYN_LINK) || defined(BOOST_GRAPH_DYN_LINK) +# ifdef BOOST_GRAPH_SOURCE +# define BOOST_GRAPH_DECL BOOST_SYMBOL_EXPORT +# else +# define BOOST_GRAPH_DECL BOOST_SYMBOL_IMPORT +# endif // BOOST_GRAPH_SOURCE +#endif // DYN_LINK #ifndef BOOST_GRAPH_DECL # define BOOST_GRAPH_DECL From c416132bfec8b23b59032528dc611b5008aab51b Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Fri, 29 Jul 2011 01:12:57 +0000 Subject: [PATCH 067/333] Fixed HTML documentation for isomorphism algorithm; refs #5633 [SVN r73422] --- doc/isomorphism.html | 39 ++++++++++++++++----------------------- 1 file changed, 16 insertions(+), 23 deletions(-) diff --git a/doc/isomorphism.html b/doc/isomorphism.html index 2738280aa..8fe17392a 100644 --- a/doc/isomorphism.html +++ b/doc/isomorphism.html @@ -101,31 +101,24 @@

      Named Parameters

      Python: Must be a vertex_vertex_map for the first graph.
      -IN: vertex_invariant1(VertexInvariant1 i) +IN: vertex_invariant1(VertexInvariant1 i1) +IN: vertex_invariant2(VertexInvariant2 i2)
      -A mapping i from vertices to integers such that if there is -some isomorphism that maps v onto v' then i(v) == -i(v'). The VertexInvariant type must be a BinaryFunction -where the first argument is a vertex descriptor, the second argument is a -graph, and the result type is an integer. The vertex invariant must -work with the types for graph 1. +Mappings from vertices to integers which restrict which vertices may be +considered isomorphic. If a candidate isomorphism maps v1 to v2 +but i1(v1) != i2(v2), that candidate is rejected. +This mapping can be used either to speed up the search (as is done by the +default value, which requires that the degrees of v1 and v2 are +equal) or to impose extra conditions on the result. The +VertexInvariant1 and VertexInvariant2 types must model UnaryFunction, with +the argument type of vertex_invariant1 being Graph1's vertex +descriptor type, the argument type of vertex_invariant2 being +Graph2's vertex descriptor type, and both functions having integral +result types. The values returned by these two functions must be in the range +[0, vertex_max_invariant).
      -Default: degree_vertex_invariant
      -Python: Unsupported parameter. -
      - -IN: vertex_invariant2(VertexInvariant2 i) -
      -A mapping i from vertices to integers such that if there is -some isomorphism that maps v onto v' then i(v) == -i(v'). The VertexInvariant type must be a BinaryFunction -where the first argument is a vertex descriptor, the second argument is a -graph, and the result type is an integer. The vertex invariant must -work with the types for both graph 2. -
      -Default: degree_vertex_invariant
      +Default: degree_vertex_invariant for both arguments
      Python: Unsupported parameter.
      From b021084901d4eac3aa3bc217ff494ad283009396 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Fri, 29 Jul 2011 01:16:43 +0000 Subject: [PATCH 068/333] Added caveat about PDF file; refs #5633 [SVN r73423] --- doc/isomorphism.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/isomorphism.html b/doc/isomorphism.html index 8fe17392a..3b86077b1 100644 --- a/doc/isomorphism.html +++ b/doc/isomorphism.html @@ -59,7 +59,7 @@

      algorithm in [46,48]. The file -isomorphism-impl.pdf contains a +isomorphism-impl.pdf contains a (somewhat out-of-date) "literate" description of the implementation. The algorithm used is simple but slow. A more efficient (and much more complex) algorithm is described in [ Date: Fri, 29 Jul 2011 01:30:53 +0000 Subject: [PATCH 069/333] Applied patch from #5506; fixes #5506 [SVN r73424] --- include/boost/graph/graphml.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/boost/graph/graphml.hpp b/include/boost/graph/graphml.hpp index 6afa12c96..2239d9666 100644 --- a/include/boost/graph/graphml.hpp +++ b/include/boost/graph/graphml.hpp @@ -263,7 +263,7 @@ write_graphml(std::ostream& out, const Graph& g, VertexIndexMap vertex_index, { std::string key_id = "key" + lexical_cast(key_count++); if (i->second->key() == typeid(Graph)) - vertex_key_ids[i->first] = key_id; + graph_key_ids[i->first] = key_id; else if (i->second->key() == typeid(vertex_descriptor)) vertex_key_ids[i->first] = key_id; else if (i->second->key() == typeid(edge_descriptor)) From fcf644620145691c66bfceec09e6e298f6586a71 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Fri, 29 Jul 2011 01:44:48 +0000 Subject: [PATCH 070/333] Removed calls to exit(); fixes #5185 [SVN r73425] --- include/boost/graph/read_dimacs.hpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/include/boost/graph/read_dimacs.hpp b/include/boost/graph/read_dimacs.hpp index 4e82f84ed..06f1a335f 100644 --- a/include/boost/graph/read_dimacs.hpp +++ b/include/boost/graph/read_dimacs.hpp @@ -281,8 +281,7 @@ int read_dimacs_max_flow_internal(Graph& g, std::printf ( "\nline %ld of input - %s\n", no_lines, err_message[err_no] ); - std::exit (1); - return (0); /* to avoid warning */ + return -1; } /* -------------------- end of parser -------------------*/ From f0343d2264a0512cd8741644bc6f129d2fd1e572 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Tue, 9 Aug 2011 19:23:16 +0000 Subject: [PATCH 071/333] Fixed grid graph for case where VertexIndex is smaller than int [SVN r73630] --- include/boost/graph/grid_graph.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/boost/graph/grid_graph.hpp b/include/boost/graph/grid_graph.hpp index ab6440850..6cc104ee5 100644 --- a/include/boost/graph/grid_graph.hpp +++ b/include/boost/graph/grid_graph.hpp @@ -377,7 +377,7 @@ namespace boost { // Stop at the end of this dimension if necessary. new_position = (std::min)(new_position, - length(dimension_index) - 1); + vertices_size_type(length(dimension_index) - 1)); } vertex[dimension_index] = new_position; From fee2e45a8c155a2177aef24a921359d0427a8eb4 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Tue, 9 Aug 2011 19:32:20 +0000 Subject: [PATCH 072/333] Fixed vertex count computation for case where number of vertices does not fit into an int [SVN r73631] --- include/boost/graph/grid_graph.hpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/include/boost/graph/grid_graph.hpp b/include/boost/graph/grid_graph.hpp index 6cc104ee5..f63f3d01e 100644 --- a/include/boost/graph/grid_graph.hpp +++ b/include/boost/graph/grid_graph.hpp @@ -697,7 +697,8 @@ namespace boost { void precalculate() { m_num_vertices = std::accumulate(m_dimension_lengths.begin(), - m_dimension_lengths.end(), 1, + m_dimension_lengths.end(), + vertices_size_type(1), std::multiplies()); // Calculate number of edges in each dimension From c0bc3e3aea27e99b44bf291415b11e169e3b1948 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Mon, 22 Aug 2011 01:42:12 +0000 Subject: [PATCH 073/333] Fixed documentation based on issues found by Ragavendran Gopalakrishnan [SVN r73996] --- doc/constructing_algorithms.html | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/constructing_algorithms.html b/doc/constructing_algorithms.html index 0067ee3e5..cbea2963d 100644 --- a/doc/constructing_algorithms.html +++ b/doc/constructing_algorithms.html @@ -106,7 +106,7 @@

      Constructing graph algorithms with BGL

      graph algorithm as a template function, the concept checks, and some typedefs. The implementation is straightforward, the only step not discussed above is the color initialization step, where we set the -color of all the vertices to ``uncolored''. +color of all the vertices to "uncolored."

      @@ -125,8 +125,8 @@ 

      Constructing graph algorithms with BGL

      function_requires< VertexListGraphConcept<VertexListGraph> >(); function_requires< ReadWritePropertyMapConcept<Color, vertex_descriptor> >(); function_requires< IntegerConcept<ColorType> >(); - function_requires< size_type, ReadablePropertyMapConcept<Order> >(); - typedef typename same_type<OrderType, vertex_descriptor>::type req_same; + function_requires< ReadablePropertyMapConcept<Order, size_type> >(); + BOOST_STATIC_ASSERT((is_same<OrderType, vertex_descriptor>::value)); size_type max_color = 0; const size_type V = num_vertices(G); From 9c7f42c58a057a1a113db99731e607c1b1cf2d5f Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Mon, 22 Aug 2011 01:43:07 +0000 Subject: [PATCH 074/333] Changed to custom edge_descriptor type in reverse_graph to avoid ambiguities when using a std::pair edge_descriptor from an underlying graph [SVN r73997] --- include/boost/graph/reverse_graph.hpp | 115 ++++++++++++++++++++------ 1 file changed, 88 insertions(+), 27 deletions(-) diff --git a/include/boost/graph/reverse_graph.hpp b/include/boost/graph/reverse_graph.hpp index 4067f2c2e..6c804208d 100644 --- a/include/boost/graph/reverse_graph.hpp +++ b/include/boost/graph/reverse_graph.hpp @@ -8,6 +8,7 @@ #include #include +#include #include #include #include @@ -23,10 +24,44 @@ struct reverse_graph_tag { }; namespace detail { + template + class reverse_graph_edge_descriptor { + public: + EdgeDesc underlying_desc; + + public: + explicit reverse_graph_edge_descriptor(const EdgeDesc& underlying_desc = EdgeDesc()) + : underlying_desc(underlying_desc) {} + + friend bool operator==(const reverse_graph_edge_descriptor& a, const reverse_graph_edge_descriptor& b) { + return a.underlying_desc == b.underlying_desc; + } + friend bool operator!=(const reverse_graph_edge_descriptor& a, const reverse_graph_edge_descriptor& b) { + return a.underlying_desc != b.underlying_desc; + } + }; + + template + struct reverse_graph_edge_descriptor_maker { + typedef reverse_graph_edge_descriptor result_type; + + reverse_graph_edge_descriptor operator()(const EdgeDesc& ed) const { + return reverse_graph_edge_descriptor(ed); + } + }; + + template + std::pair, Iter>, + transform_iterator, Iter> > + reverse_edge_iter_pair(const std::pair& ip) { + return std::make_pair(make_transform_iterator(ip.first, reverse_graph_edge_descriptor_maker()), + make_transform_iterator(ip.second, reverse_graph_edge_descriptor_maker())); + } + template struct choose_rev_edge_iter { }; template <> struct choose_rev_edge_iter { template struct bind_ { - typedef typename graph_traits::edge_iterator type; + typedef transform_iterator::edge_descriptor>, typename graph_traits::edge_iterator> type; }; }; template <> struct choose_rev_edge_iter { @@ -49,17 +84,17 @@ class reverse_graph { // Graph requirements typedef typename Traits::vertex_descriptor vertex_descriptor; - typedef typename Traits::edge_descriptor edge_descriptor; + typedef detail::reverse_graph_edge_descriptor edge_descriptor; typedef typename Traits::directed_category directed_category; typedef typename Traits::edge_parallel_category edge_parallel_category; typedef typename Traits::traversal_category traversal_category; // IncidenceGraph requirements - typedef typename Traits::in_edge_iterator out_edge_iterator; + typedef transform_iterator, typename Traits::in_edge_iterator> out_edge_iterator; typedef typename Traits::degree_size_type degree_size_type; // BidirectionalGraph requirements - typedef typename Traits::out_edge_iterator in_edge_iterator; + typedef transform_iterator, typename Traits::out_edge_iterator> in_edge_iterator; // AdjacencyGraph requirements typedef typename adjacency_iterator_generator::edge_iterator, typename reverse_graph::edge_iterator> edges(const reverse_graph& g) { - return edges(g.m_g); + return detail::reverse_edge_iter_pair::edge_descriptor>(edges(g.m_g)); } template -inline std::pair::in_edge_iterator, - typename graph_traits::in_edge_iterator> +inline std::pair::out_edge_iterator, + typename reverse_graph::out_edge_iterator> out_edges(const typename graph_traits::vertex_descriptor u, const reverse_graph& g) { - return in_edges(u, g.m_g); + return detail::reverse_edge_iter_pair::edge_descriptor>(in_edges(u, g.m_g)); } template @@ -211,12 +246,12 @@ edge(const typename graph_traits::vertex_descriptor u, } template -inline std::pair::out_edge_iterator, - typename graph_traits::out_edge_iterator> +inline std::pair::in_edge_iterator, + typename reverse_graph::in_edge_iterator> in_edges(const typename graph_traits::vertex_descriptor u, const reverse_graph& g) { - return out_edges(u, g.m_g); + return detail::reverse_edge_iter_pair::edge_descriptor>(out_edges(u, g.m_g)); } template @@ -243,21 +278,52 @@ in_degree(const typename graph_traits::vertex_descriptor u, template inline typename graph_traits::vertex_descriptor -source(const Edge& e, const reverse_graph& g) +source(const detail::reverse_graph_edge_descriptor& e, const reverse_graph& g) { - return target(e, g.m_g); + return target(e.underlying_desc, g.m_g); } template inline typename graph_traits::vertex_descriptor -target(const Edge& e, const reverse_graph& g) +target(const detail::reverse_graph_edge_descriptor& e, const reverse_graph& g) { - return source(e, g.m_g); + return source(e.underlying_desc, g.m_g); } namespace detail { + template + struct reverse_graph_edge_property_map { + private: + PM underlying_pm; + + public: + typedef reverse_graph_edge_descriptor::key_type> key_type; + typedef typename property_traits::value_type value_type; + typedef typename property_traits::reference reference; + typedef typename property_traits::category category; + + explicit reverse_graph_edge_property_map(const PM& pm): underlying_pm(pm) {} + + friend reference + get(const reverse_graph_edge_property_map& m, + const key_type& e) { + return get(m.underlying_pm, e.underlying_desc); + } + + friend void + put(const reverse_graph_edge_property_map& m, + const key_type& e, + const value_type& v) { + put(m.underlying_pm, e.underlying_desc, v); + } + + reference operator[](const key_type& k) { + return (this->underlying_pm)[k.underlying_desc]; + } + }; + struct reverse_graph_vertex_property_selector { template struct bind_ { @@ -273,8 +339,8 @@ namespace detail { struct bind_ { typedef typename ReverseGraph::base_type Graph; typedef property_map PMap; - typedef typename PMap::type type; - typedef typename PMap::const_type const_type; + typedef reverse_graph_edge_property_map type; + typedef reverse_graph_edge_property_map const_type; }; }; @@ -294,7 +360,7 @@ template typename property_map, Property>::type get(Property p, reverse_graph& g) { - return get(p, g.m_g); + return typename property_map, Property>::type(get(p, g.m_g)); } template @@ -302,7 +368,7 @@ typename property_map, Property>::const_type get(Property p, const reverse_graph& g) { const BidirGraph& gref = g.m_g; // in case GRef is non-const - return get(p, gref); + return typename property_map, Property>::const_type(get(p, gref)); } template @@ -311,15 +377,15 @@ typename property_traits< >::value_type get(Property p, const reverse_graph& g, const Key& k) { - return get(p, g.m_g, k); + return get(get(p, g), k); } template void -put(Property p, const reverse_graph& g, const Key& k, +put(Property p, reverse_graph& g, const Key& k, const Value& val) { - put(p, g.m_g, k, val); + put(get(p, g), k, val); } template& g, Tag tag) } // namespace boost -#if BOOST_WORKAROUND(BOOST_MSVC, < 1300) -// Stay out of the way of the concept checking class -# undef BidirectionalGraph -#endif - #endif From b156db0c9e5b240a8bafa64f8dd561f30bfed28b Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Mon, 22 Aug 2011 01:44:08 +0000 Subject: [PATCH 075/333] Fixed traits class name [SVN r73999] --- test/test_construction.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/test_construction.hpp b/test/test_construction.hpp index 4a5a4bbf2..6fcd95dfc 100644 --- a/test/test_construction.hpp +++ b/test/test_construction.hpp @@ -65,7 +65,7 @@ template void build_property_graph(Graph const&, boost::mpl::true_, boost::mpl::false_) { using namespace boost; BOOST_CONCEPT_ASSERT((VertexMutablePropertyGraphConcept)); - typedef typename vertex_property::type VertexProp; + typedef typename vertex_property_type::type VertexProp; std::cout << "...build mutable\n"; From 48b3020f7d3f994da43c7bacb45f6a3904315dab Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Fri, 26 Aug 2011 17:33:02 +0000 Subject: [PATCH 076/333] Added parentheses around call to numeric_limits::max; fixes #5813 [SVN r74075] --- include/boost/graph/relax.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/boost/graph/relax.hpp b/include/boost/graph/relax.hpp index 889f8206d..468579609 100644 --- a/include/boost/graph/relax.hpp +++ b/include/boost/graph/relax.hpp @@ -24,7 +24,7 @@ namespace boost { { const T inf; - closed_plus() : inf(std::numeric_limits::max()) { } + closed_plus() : inf((std::numeric_limits::max)()) { } closed_plus(T inf) : inf(inf) { } T operator()(const T& a, const T& b) const { From 90678ab0fa4c074f8a0b561369a033611a1c68b6 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Sat, 27 Aug 2011 19:35:05 +0000 Subject: [PATCH 077/333] Fixed inspection report issues [SVN r74094] --- include/boost/graph/subgraph.hpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/include/boost/graph/subgraph.hpp b/include/boost/graph/subgraph.hpp index 2b702a80f..b98c39026 100644 --- a/include/boost/graph/subgraph.hpp +++ b/include/boost/graph/subgraph.hpp @@ -23,6 +23,7 @@ #include #include +#include #include namespace boost { @@ -665,7 +666,7 @@ remove_edge(typename subgraph::edge_descriptor e, subgraph& g) typename subgraph::edge_descriptor e_global = g.local_to_global(e); #ifndef NDEBUG std::pair::edge_descriptor, bool> fe = g.find_edge(e_global); - assert(fe.second && fe.first == e); + BOOST_ASSERT(fe.second && fe.first == e); #endif //NDEBUG subgraph &root = g.root(); // chase to root detail::children_remove_edge(e_global, root.m_children); From fd37deb67bd399f521f267eaac9ca60857e43e91 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Sun, 4 Sep 2011 18:47:27 +0000 Subject: [PATCH 078/333] Added requirement to link to Boost.Regex [SVN r74232] --- doc/read_graphviz.html | 4 ++-- doc/read_graphviz.rst | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/doc/read_graphviz.html b/doc/read_graphviz.html index b2d7a0b1a..8163c6d05 100644 --- a/doc/read_graphviz.html +++ b/doc/read_graphviz.html @@ -181,8 +181,8 @@

      Example

      Building the GraphViz Readers

      To use the GraphViz readers, you will need to build and link against -the "boost_graph" library. The library can be built by following the -Boost Jam Build Instructions for the subdirectory libs/graph/build.

      +the "boost_graph" and "boost_regex" libraries. These libraries can be built by following the +Boost Jam Build Instructions for the subdirectories libs/graph/build and libs/regex/build.

      Notes

      diff --git a/doc/read_graphviz.rst b/doc/read_graphviz.rst index 053d1ef22..b8bd341dd 100644 --- a/doc/read_graphviz.rst +++ b/doc/read_graphviz.rst @@ -182,8 +182,8 @@ GraphViz reader to populate an ``adjacency_list`` graph Building the GraphViz Readers ----------------------------- To use the GraphViz readers, you will need to build and link against -the "boost_graph" library. The library can be built by following the -`Boost Jam Build Instructions`_ for the subdirectory ``libs/graph/build``. +the "boost_graph" and "boost_regex" libraries. These libraries can be built by following the +`Boost Jam Build Instructions`_ for the subdirectories ``libs/graph/build`` and ``libs/regex/build``. Notes From 4778a4b359766b9729ab450a769b5a332042de0a Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Mon, 12 Sep 2011 15:01:25 +0000 Subject: [PATCH 079/333] Fixed link [SVN r74357] --- doc/r_c_shortest_paths.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/r_c_shortest_paths.html b/doc/r_c_shortest_paths.html index 9964e3fec..f33f8acc7 100755 --- a/doc/r_c_shortest_paths.html +++ b/doc/r_c_shortest_paths.html @@ -123,7 +123,7 @@

      Introduction and Problem Description

      Desaulniers, G.; Desrosiers, J.; Solomon, M. (eds.) (2005):
      Column Generation
      Springer, New York, pp. 33–65
      -(available online +(available online here)

      From 4a19d6d288f14e998ebeca71697a955bfd153602 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Wed, 28 Sep 2011 19:04:30 +0000 Subject: [PATCH 080/333] Applied patch from #5919; fixes #5919 [SVN r74602] --- include/boost/graph/named_graph.hpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/include/boost/graph/named_graph.hpp b/include/boost/graph/named_graph.hpp index dda608d78..38f4ca0e1 100644 --- a/include/boost/graph/named_graph.hpp +++ b/include/boost/graph/named_graph.hpp @@ -346,7 +346,9 @@ inline void BGL_NAMED_GRAPH::added_vertex(Vertex vertex) template inline void BGL_NAMED_GRAPH::removing_vertex(Vertex vertex) { - named_vertices.erase(vertex); + typedef typename BGL_NAMED_GRAPH::vertex_name_type vertex_name_type; + const vertex_name_type& vertex_name = extract_name(derived()[vertex]); + named_vertices.erase(vertex_name); } template From 27e567204706b7f93489a4892da4564724c0381b Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Fri, 7 Oct 2011 21:28:22 +0000 Subject: [PATCH 081/333] Fixed typo [SVN r74783] --- doc/using_adjacency_list.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/using_adjacency_list.html b/doc/using_adjacency_list.html index 03206ecc3..9b077cd8d 100644 --- a/doc/using_adjacency_list.html +++ b/doc/using_adjacency_list.html @@ -326,7 +326,7 @@

      Directed and Undirected Adjacency List graph. See Section Undirected Graphs for a description of the difference between directed and undirected -graphs in BGL. The bidirectealS selector specifies that the +graphs in BGL. The bidirectionalS selector specifies that the graph will provide the in_edges() function as well as the out_edges() function. This imposes twice as much space overhead per edge, which is why in_edges() is optional. From ffff89b1a213637b1947e5d55e10c27968c5057c Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Wed, 19 Oct 2011 20:03:00 +0000 Subject: [PATCH 082/333] Refactored and added test graph from Andre Dau [SVN r75066] --- test/biconnected_components_test.cpp | 49 +++++++++++++++++++--------- 1 file changed, 33 insertions(+), 16 deletions(-) diff --git a/test/biconnected_components_test.cpp b/test/biconnected_components_test.cpp index ee37375fc..6ec321a9f 100644 --- a/test/biconnected_components_test.cpp +++ b/test/biconnected_components_test.cpp @@ -77,23 +77,11 @@ check_articulation_points(const Graph& g, std::vector art_points) } else std::cout << "OK." << std::endl; } -int test_main(int argc, char* argv[]) -{ - std::size_t n = 100; - std::size_t m = 500; - std::size_t seed = 1; +typedef adjacency_list Graph; +typedef graph_traits::vertex_descriptor Vertex; - if (argc > 1) n = lexical_cast(argv[1]); - if (argc > 2) m = lexical_cast(argv[2]); - if (argc > 3) seed = lexical_cast(argv[3]); - - typedef adjacency_list Graph; - typedef graph_traits::vertex_descriptor Vertex; - - Graph g(n); - minstd_rand gen(seed); - generate_random_graph(g, n, m, gen); +bool test_graph(Graph& g) { // Returns false on failure std::vector art_points; std::cout << "Computing biconnected components & articulation points... "; @@ -127,5 +115,34 @@ int test_main(int argc, char* argv[]) out << "}\n"; } + return any_errors; +} + +int test_main(int argc, char* argv[]) +{ + std::size_t n = 100; + std::size_t m = 500; + std::size_t seed = 1; + + if (argc > 1) n = lexical_cast(argv[1]); + if (argc > 2) m = lexical_cast(argv[2]); + if (argc > 3) seed = lexical_cast(argv[3]); + + { + Graph g(n); + minstd_rand gen(seed); + generate_random_graph(g, n, m, gen); + if (test_graph(g)) return 1; + } + + { + Graph g(4); + add_edge(2, 3, g); + add_edge(0, 3, g); + add_edge(0, 2, g); + add_edge(1, 0, g); + if (test_graph(g)) return 1; + } + return 0; } From 2edbcb500f03e9ad3caf9dca1c8cc2389872aafd Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Wed, 19 Oct 2011 20:03:54 +0000 Subject: [PATCH 083/333] Fixed strange use of pred map, and changed algorithm to be more similar to Tarjan paper cited in bibliography; fixes #6033 [SVN r75067] --- .../boost/graph/biconnected_components.hpp | 79 +++++++++---------- 1 file changed, 38 insertions(+), 41 deletions(-) diff --git a/include/boost/graph/biconnected_components.hpp b/include/boost/graph/biconnected_components.hpp index 034596364..a120c18a6 100644 --- a/include/boost/graph/biconnected_components.hpp +++ b/include/boost/graph/biconnected_components.hpp @@ -35,19 +35,21 @@ namespace boost (ComponentMap comp, std::size_t& c, DiscoverTimeMap dtm, std::size_t& dfs_time, LowPointMap lowpt, PredecessorMap pred, OutputIterator out, Stack& S, DFSVisitor vis) - : comp(comp), c(c), dtm(dtm), dfs_time(dfs_time), lowpt(lowpt), + : comp(comp), c(c), children_of_root(0), dtm(dtm), + dfs_time(dfs_time), lowpt(lowpt), pred(pred), out(out), S(S), vis(vis) { } template void initialize_vertex(const Vertex& u, Graph& g) { + put(pred, u, u); vis.initialize_vertex(u, g); } template void start_vertex(const Vertex& u, Graph& g) { - put(pred, u, u); + children_of_root = 0; vis.start_vertex(u, g); } @@ -68,8 +70,14 @@ namespace boost template void tree_edge(const Edge& e, Graph& g) { + typename boost::graph_traits::vertex_descriptor src = source(e, g); + typename boost::graph_traits::vertex_descriptor tgt = target(e, g); + S.push(e); - put(pred, target(e, g), source(e, g)); + put(pred, tgt, src); + if ( get(pred, src) == src ) { + ++children_of_root; + } vis.tree_edge(e, g); } @@ -78,11 +86,14 @@ namespace boost { BOOST_USING_STD_MIN(); - if ( target(e, g) != get(pred, source(e, g)) ) { + typename boost::graph_traits::vertex_descriptor src = source(e, g); + typename boost::graph_traits::vertex_descriptor tgt = target(e, g); + if ( ( tgt != get(pred, src) || get(pred, src) == src ) && + get(dtm, tgt) < get(dtm, src) ) { S.push(e); - put(lowpt, source(e, g), - min BOOST_PREVENT_MACRO_SUBSTITUTION(get(lowpt, source(e, g)), - get(dtm, target(e, g)))); + put(lowpt, src, + min BOOST_PREVENT_MACRO_SUBSTITUTION(get(lowpt, src), + get(dtm, tgt))); } vis.back_edge(e, g); } @@ -98,49 +109,35 @@ namespace boost { BOOST_USING_STD_MIN(); Vertex parent = get(pred, u); - const std::size_t dtm_of_dubious_parent = get(dtm, parent); - bool is_art_point = false; - if ( dtm_of_dubious_parent > get(dtm, u) ) { - parent = get(pred, parent); - is_art_point = true; - put(pred, get(pred, u), u); - put(pred, u, parent); + if (parent == u) { // Root of tree is special + if (children_of_root >= 2) { + *out++ = u; + } + return; } - - if ( parent == u ) { // at top - if ( get(dtm, u) + 1 == dtm_of_dubious_parent ) - is_art_point = false; - } else { - put(lowpt, parent, - min BOOST_PREVENT_MACRO_SUBSTITUTION(get(lowpt, parent), - get(lowpt, u))); - - if (get(lowpt, u) >= get(dtm, parent)) { - if ( get(dtm, parent) > get(dtm, get(pred, parent)) ) { - put(pred, u, get(pred, parent)); - put(pred, parent, u); - } - - while ( get(dtm, source(S.top(), g)) >= get(dtm, u) ) { - put(comp, S.top(), c); - S.pop(); - } + put(lowpt, parent, + min BOOST_PREVENT_MACRO_SUBSTITUTION(get(lowpt, parent), + get(lowpt, u))); + if ( get(lowpt, u) >= get(dtm, parent) ) { + if ( get(pred, parent) != parent ) { + *out++ = parent; + } + while ( get(dtm, source(S.top(), g)) >= get(dtm, u) ) { put(comp, S.top(), c); - S.pop(); - ++c; - if ( S.empty() ) { - put(pred, u, parent); - put(pred, parent, u); - } + S.pop(); } + assert (source(S.top(), g) == parent); + assert (target(S.top(), g) == u); + put(comp, S.top(), c); + S.pop(); + ++c; } - if ( is_art_point ) - *out++ = u; vis.finish_vertex(u, g); } ComponentMap comp; std::size_t& c; + std::size_t children_of_root; DiscoverTimeMap dtm; std::size_t& dfs_time; LowPointMap lowpt; From 6f91f83d2e64aad05e7d80b081764ad854789aea Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Thu, 20 Oct 2011 21:32:45 +0000 Subject: [PATCH 084/333] Removed incorrect != 0 test on boost::optional; fixes #6044 [SVN r75074] --- include/boost/pending/relaxed_heap.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/boost/pending/relaxed_heap.hpp b/include/boost/pending/relaxed_heap.hpp index b3ab2ed20..13f7af4c0 100644 --- a/include/boost/pending/relaxed_heap.hpp +++ b/include/boost/pending/relaxed_heap.hpp @@ -163,7 +163,7 @@ class relaxed_heap void remove(const value_type& x) { group* a = &index_to_group[get(id, x) / log_n]; - assert(groups[get(id, x)] != 0); + assert(groups[get(id, x)]); a->value = x; a->kind = smallest_key; promote(a); From 63249fa231252d429b4816b3e503ca8ad82a0273 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Thu, 27 Oct 2011 01:17:35 +0000 Subject: [PATCH 085/333] Removed hash specialization [SVN r75124] --- include/boost/graph/detail/adjacency_list.hpp | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/include/boost/graph/detail/adjacency_list.hpp b/include/boost/graph/detail/adjacency_list.hpp index 2ff293e11..100c44ba7 100644 --- a/include/boost/graph/detail/adjacency_list.hpp +++ b/include/boost/graph/detail/adjacency_list.hpp @@ -2759,17 +2759,6 @@ namespace boost { #if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) namespace boost { - #if BOOST_WORKAROUND( _STLPORT_VERSION, >= 0x500 ) - // STLport 5 already defines a hash specialization. - #else - template <> - struct hash< void* > // Need this when vertex_descriptor=void* - { - std::size_t - operator()(void* v) const { return (std::size_t)v; } - }; - #endif - template struct hash< boost::detail::stored_edge > { From d6643f50f38349288e74b865c998b32ebefbb2a7 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Thu, 27 Oct 2011 19:51:37 +0000 Subject: [PATCH 086/333] Added missing "end for"; fixes #6061 [SVN r75140] --- doc/prim_minimum_spanning_tree.html | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/prim_minimum_spanning_tree.html b/doc/prim_minimum_spanning_tree.html index c42d1e7ff..324f41962 100644 --- a/doc/prim_minimum_spanning_tree.html +++ b/doc/prim_minimum_spanning_tree.html @@ -67,6 +67,7 @@

      for each vertex u in V[G] color[u] := WHITE d[u] := infinity + end for color[s] := GRAY d[s] := 0 ENQUEUE(PQ, s) From 3619e54948465280d52bbdcfaeccb8b447a7c83e Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Sat, 29 Oct 2011 06:11:02 +0000 Subject: [PATCH 087/333] Fixed degree_vertex_invariant::max; fixes #5881 [SVN r75165] --- include/boost/graph/isomorphism.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/boost/graph/isomorphism.hpp b/include/boost/graph/isomorphism.hpp index f58690266..706e403db 100644 --- a/include/boost/graph/isomorphism.hpp +++ b/include/boost/graph/isomorphism.hpp @@ -153,7 +153,7 @@ namespace boost { { std::vector multiplicity(max_invariant, 0); BGL_FORALL_VERTICES_T(v, G1, Graph1) - ++multiplicity[invariant1(v)]; + ++multiplicity.at(invariant1(v)); sort(V_mult, compare_multiplicity(invariant1, &multiplicity[0])); } @@ -302,7 +302,7 @@ namespace boost { } // The largest possible vertex invariant number size_type max BOOST_PREVENT_MACRO_SUBSTITUTION () const { - return (m_max_vertex_in_degree + 2) * m_max_vertex_out_degree + 1; + return (m_max_vertex_in_degree + 1) * (m_max_vertex_out_degree + 1); } private: InDegreeMap m_in_degree_map; From 2b2f2d464e39e4faed5fc95fed03d463f6caf6a1 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Thu, 10 Nov 2011 15:04:27 +0000 Subject: [PATCH 088/333] Qualified more calls to tie; fixes #6112 [SVN r75431] --- example/canonical_ordering.cpp | 2 +- example/closeness_centrality.cpp | 2 +- example/clustering_coefficient.cpp | 2 +- example/degree_centrality.cpp | 2 +- example/implicit_graph.cpp | 10 ++-- example/inclusive_mean_geodesic.cpp | 2 +- example/influence_prestige.cpp | 2 +- example/kuratowski_subgraph.cpp | 2 +- example/make_biconnected_planar.cpp | 4 +- example/make_maximal_planar.cpp | 6 +- example/matching_example.cpp | 4 +- example/mean_geodesic.cpp | 2 +- example/planar_face_traversal.cpp | 2 +- example/scaled_closeness_centrality.cpp | 2 +- example/straight_line_drawing.cpp | 2 +- include/boost/graph/chrobak_payne_drawing.hpp | 2 +- include/boost/graph/closeness_centrality.hpp | 2 +- include/boost/graph/degree_centrality.hpp | 2 +- include/boost/graph/detail/geodesic.hpp | 2 +- include/boost/graph/geodesic_distance.hpp | 2 +- .../boost/graph/is_kuratowski_subgraph.hpp | 10 ++-- .../boost/graph/is_straight_line_drawing.hpp | 2 +- include/boost/graph/make_maximal_planar.hpp | 4 +- .../boost/graph/planar_canonical_ordering.hpp | 2 +- include/boost/graph/planar_face_traversal.hpp | 4 +- include/boost/graph/push_relabel_max_flow.hpp | 4 +- include/boost/graph/tiernan_all_cycles.hpp | 6 +- include/boost/graph/write_dimacs.hpp | 2 +- test/all_planar_input_files_test.cpp | 4 +- test/basic_planarity_test.cpp | 2 +- test/bellman-test.cpp | 2 +- test/isomorphism.cpp | 57 +++++++++++++++++++ test/labeled_graph.cpp | 2 +- test/make_bicon_planar_test.cpp | 6 +- test/make_connected_test.cpp | 4 +- test/make_maximal_planar_test.cpp | 6 +- test/parallel_edges_loops_test.cpp | 6 +- test/test_construction.hpp | 2 +- test/transitive_closure_test2.cpp | 2 +- 39 files changed, 120 insertions(+), 63 deletions(-) mode change 100755 => 100644 example/matching_example.cpp diff --git a/example/canonical_ordering.cpp b/example/canonical_ordering.cpp index 770b251e3..129af6ac2 100644 --- a/example/canonical_ordering.cpp +++ b/example/canonical_ordering.cpp @@ -54,7 +54,7 @@ int main(int argc, char** argv) property_map::type e_index = get(edge_index, g); graph_traits::edges_size_type edge_count = 0; graph_traits::edge_iterator ei, ei_end; - for(tie(ei, ei_end) = edges(g); ei != ei_end; ++ei) + for(boost::tie(ei, ei_end) = edges(g); ei != ei_end; ++ei) put(e_index, *ei, edge_count++); diff --git a/example/closeness_centrality.cpp b/example/closeness_centrality.cpp index b5aa4776b..ea921114c 100644 --- a/example/closeness_centrality.cpp +++ b/example/closeness_centrality.cpp @@ -75,7 +75,7 @@ main(int argc, char *argv[]) // Print the closeness centrality of each vertex. graph_traits::vertex_iterator i, end; - for(tie(i, end) = vertices(g); i != end; ++i) { + for(boost::tie(i, end) = vertices(g); i != end; ++i) { cout << setw(12) << setiosflags(ios::left) << g[*i].name << get(cm, *i) << endl; } diff --git a/example/clustering_coefficient.cpp b/example/clustering_coefficient.cpp index 70f8e731c..c4a451f13 100644 --- a/example/clustering_coefficient.cpp +++ b/example/clustering_coefficient.cpp @@ -58,7 +58,7 @@ main(int argc, char *argv[]) // Print the clustering coefficient of each vertex. graph_traits::vertex_iterator i, end; - for(tie(i, end) = vertices(g); i != end; ++i) { + for(boost::tie(i, end) = vertices(g); i != end; ++i) { cout << setw(12) << setiosflags(ios::left) << g[*i].name << get(cm, *i) << endl; } diff --git a/example/degree_centrality.cpp b/example/degree_centrality.cpp index 7da764e1b..a8aae31cb 100644 --- a/example/degree_centrality.cpp +++ b/example/degree_centrality.cpp @@ -57,7 +57,7 @@ main(int argc, char *argv[]) // Print the degree centrality of each vertex. graph_traits::vertex_iterator i, end; - for(tie(i, end) = vertices(g); i != end; ++i) { + for(boost::tie(i, end) = vertices(g); i != end; ++i) { cout << setiosflags(ios::left) << setw(12) << g[*i].name << cm[*i] << endl; } diff --git a/example/implicit_graph.cpp b/example/implicit_graph.cpp index 6efdeac97..7b0c0fc2c 100644 --- a/example/implicit_graph.cpp +++ b/example/implicit_graph.cpp @@ -473,18 +473,18 @@ int main (int argc, char const *argv[]) { // 5 vertices std::cout << "Vertices, outgoing edges, and adjacent vertices" << std::endl; vertex_iterator vi, vi_end; - for (tie(vi, vi_end) = vertices(g); vi != vi_end; vi++) { + for (boost::tie(vi, vi_end) = vertices(g); vi != vi_end; vi++) { vertex_descriptor u = *vi; std::cout << "Vertex " << u << ": "; // Adjacenct edges out_edge_iterator ei, ei_end; - for (tie(ei, ei_end) = out_edges(u, g); ei != ei_end; ei++) + for (boost::tie(ei, ei_end) = out_edges(u, g); ei != ei_end; ei++) std::cout << *ei << " "; std::cout << " Adjacent vertices "; // Adjacent vertices // Here we want our adjacency_iterator and not boost::adjacency_iterator. ::adjacency_iterator ai, ai_end; - for (tie(ai, ai_end) = adjacent_vertices(u, g); ai != ai_end; ai++) { + for (boost::tie(ai, ai_end) = adjacent_vertices(u, g); ai != ai_end; ai++) { std::cout << *ai << " "; } std::cout << std::endl; @@ -503,7 +503,7 @@ int main (int argc, char const *argv[]) { // 5 edges std::cout << "Edges and weights" << std::endl; edge_iterator ei, ei_end; - for (tie(ei, ei_end) = edges(g); ei != ei_end; ei++) { + for (boost::tie(ei, ei_end) = edges(g); ei != ei_end; ei++) { edge_descriptor e = *ei; std::cout << e << " weight " << get(edge_weight, g, e) << std::endl; } @@ -528,7 +528,7 @@ int main (int argc, char const *argv[]) { distance_map(&dist[0]) ); std::cout << "Dijkstra search from vertex " << source << std::endl; - for (tie(vi, vi_end) = vertices(g); vi != vi_end; ++vi) { + for (boost::tie(vi, vi_end) = vertices(g); vi != vi_end; ++vi) { vertex_descriptor u = *vi; std::cout << "Vertex " << u << ": " << "parent "<< pred[*vi] << ", " diff --git a/example/inclusive_mean_geodesic.cpp b/example/inclusive_mean_geodesic.cpp index 91d5a0d47..d825a27dc 100644 --- a/example/inclusive_mean_geodesic.cpp +++ b/example/inclusive_mean_geodesic.cpp @@ -121,7 +121,7 @@ main(int argc, char *argv[]) cout << setw(12) << setiosflags(ios::left) << "excluding"; cout << setw(12) << setiosflags(ios::left) << "including" << endl; graph_traits::vertex_iterator i, end; - for(tie(i, end) = vertices(g); i != end; ++i) { + for(boost::tie(i, end) = vertices(g); i != end; ++i) { cout << setw(12) << setiosflags(ios::left) << g[*i].name << setw(12) << get(exmap, *i) diff --git a/example/influence_prestige.cpp b/example/influence_prestige.cpp index 348b0d160..e7d26f134 100644 --- a/example/influence_prestige.cpp +++ b/example/influence_prestige.cpp @@ -62,7 +62,7 @@ main(int argc, char *argv[]) // Print the degree centrality of each vertex graph_traits::vertex_iterator i, end; - for(tie(i, end) = vertices(g); i != end; ++i) { + for(boost::tie(i, end) = vertices(g); i != end; ++i) { Vertex v = *i; cout << setiosflags(ios::left) << setw(12) << g[v].name << "\t" diff --git a/example/kuratowski_subgraph.cpp b/example/kuratowski_subgraph.cpp index 5b080f46f..8f55a3e65 100644 --- a/example/kuratowski_subgraph.cpp +++ b/example/kuratowski_subgraph.cpp @@ -55,7 +55,7 @@ int main(int argc, char** argv) property_map::type e_index = get(edge_index, g); graph_traits::edges_size_type edge_count = 0; graph_traits::edge_iterator ei, ei_end; - for(tie(ei, ei_end) = edges(g); ei != ei_end; ++ei) + for(boost::tie(ei, ei_end) = edges(g); ei != ei_end; ++ei) put(e_index, *ei, edge_count++); diff --git a/example/make_biconnected_planar.cpp b/example/make_biconnected_planar.cpp index 3c4a7745b..d0c0dd8eb 100644 --- a/example/make_biconnected_planar.cpp +++ b/example/make_biconnected_planar.cpp @@ -51,7 +51,7 @@ int main(int argc, char** argv) property_map::type e_index = get(edge_index, g); graph_traits::edges_size_type edge_count = 0; graph_traits::edge_iterator ei, ei_end; - for(tie(ei, ei_end) = edges(g); ei != ei_end; ++ei) + for(boost::tie(ei, ei_end) = edges(g); ei != ei_end; ++ei) put(e_index, *ei, edge_count++); @@ -86,7 +86,7 @@ int main(int argc, char** argv) // Re-initialize the edge index, since we just added a few edges edge_count = 0; - for(tie(ei, ei_end) = edges(g); ei != ei_end; ++ei) + for(boost::tie(ei, ei_end) = edges(g); ei != ei_end; ++ei) put(e_index, *ei, edge_count++); // Re-size the storage for the biconnected components, since we diff --git a/example/make_maximal_planar.cpp b/example/make_maximal_planar.cpp index 70fd9b3f1..50d42e8de 100644 --- a/example/make_maximal_planar.cpp +++ b/example/make_maximal_planar.cpp @@ -74,7 +74,7 @@ int main(int argc, char** argv) property_map::type e_index = get(edge_index, g); graph_traits::edges_size_type edge_count = 0; graph_traits::edge_iterator ei, ei_end; - for(tie(ei, ei_end) = edges(g); ei != ei_end; ++ei) + for(boost::tie(ei, ei_end) = edges(g); ei != ei_end; ++ei) put(e_index, *ei, edge_count++); @@ -94,7 +94,7 @@ int main(int argc, char** argv) // Re-initialize the edge index, since we just added a few edges edge_count = 0; - for(tie(ei, ei_end) = edges(g); ei != ei_end; ++ei) + for(boost::tie(ei, ei_end) = edges(g); ei != ei_end; ++ei) put(e_index, *ei, edge_count++); @@ -116,7 +116,7 @@ int main(int argc, char** argv) // Re-initialize the edge index, since we just added a few edges edge_count = 0; - for(tie(ei, ei_end) = edges(g); ei != ei_end; ++ei) + for(boost::tie(ei, ei_end) = edges(g); ei != ei_end; ++ei) put(e_index, *ei, edge_count++); // Test for planarity one final time; compute the planar embedding as a diff --git a/example/matching_example.cpp b/example/matching_example.cpp old mode 100755 new mode 100644 index f1d47d954..704f1df1f --- a/example/matching_example.cpp +++ b/example/matching_example.cpp @@ -83,7 +83,7 @@ int main() std::cout << "The matching is:" << std::endl; graph_traits::vertex_iterator vi, vi_end; - for(tie(vi,vi_end) = vertices(g); vi != vi_end; ++vi) + for(boost::tie(vi,vi_end) = vertices(g); vi != vi_end; ++vi) if (mate[*vi] != graph_traits::null_vertex() && *vi < mate[*vi]) std::cout << "{" << *vi << ", " << mate[*vi] << "}" << std::endl; @@ -109,7 +109,7 @@ int main() std::cout << "The matching is:" << std::endl; - for(tie(vi,vi_end) = vertices(g); vi != vi_end; ++vi) + for(boost::tie(vi,vi_end) = vertices(g); vi != vi_end; ++vi) if (mate[*vi] != graph_traits::null_vertex() && *vi < mate[*vi]) std::cout << "{" << *vi << ", " << mate[*vi] << "}" << std::endl; diff --git a/example/mean_geodesic.cpp b/example/mean_geodesic.cpp index f6b6892c0..ca246b0a2 100644 --- a/example/mean_geodesic.cpp +++ b/example/mean_geodesic.cpp @@ -77,7 +77,7 @@ main(int argc, char *argv[]) // Print the mean geodesic distance of each vertex and finally, // the graph itself. graph_traits::vertex_iterator i, end; - for(tie(i, end) = vertices(g); i != end; ++i) { + for(boost::tie(i, end) = vertices(g); i != end; ++i) { cout << setw(12) << setiosflags(ios::left) << g[*i].name << get(gm, *i) << endl; } diff --git a/example/planar_face_traversal.cpp b/example/planar_face_traversal.cpp index 8d4daab46..fe96d2de4 100644 --- a/example/planar_face_traversal.cpp +++ b/example/planar_face_traversal.cpp @@ -94,7 +94,7 @@ int main(int argc, char** argv) property_map::type e_index = get(edge_index, g); graph_traits::edges_size_type edge_count = 0; graph_traits::edge_iterator ei, ei_end; - for(tie(ei, ei_end) = edges(g); ei != ei_end; ++ei) + for(boost::tie(ei, ei_end) = edges(g); ei != ei_end; ++ei) put(e_index, *ei, edge_count++); diff --git a/example/scaled_closeness_centrality.cpp b/example/scaled_closeness_centrality.cpp index 5223da97e..a2ade80c6 100644 --- a/example/scaled_closeness_centrality.cpp +++ b/example/scaled_closeness_centrality.cpp @@ -104,7 +104,7 @@ main(int argc, char *argv[]) // Print the scaled closeness centrality of each vertex. graph_traits::vertex_iterator i, end; - for(tie(i, end) = vertices(g); i != end; ++i) { + for(boost::tie(i, end) = vertices(g); i != end; ++i) { cout << setw(12) << setiosflags(ios::left) << g[*i].name << get(cm, *i) << endl; } diff --git a/example/straight_line_drawing.cpp b/example/straight_line_drawing.cpp index 06d1145fc..15aa82968 100644 --- a/example/straight_line_drawing.cpp +++ b/example/straight_line_drawing.cpp @@ -122,7 +122,7 @@ int main(int argc, char** argv) std::cout << "The straight line drawing is: " << std::endl; graph_traits::vertex_iterator vi, vi_end; - for(tie(vi,vi_end) = vertices(g); vi != vi_end; ++vi) + for(boost::tie(vi,vi_end) = vertices(g); vi != vi_end; ++vi) { coord_t coord(get(straight_line_drawing,*vi)); std::cout << *vi << " -> (" << coord.x << ", " << coord.y << ")" diff --git a/include/boost/graph/chrobak_payne_drawing.hpp b/include/boost/graph/chrobak_payne_drawing.hpp index 498c6f674..6060171f8 100644 --- a/include/boost/graph/chrobak_payne_drawing.hpp +++ b/include/boost/graph/chrobak_payne_drawing.hpp @@ -240,7 +240,7 @@ namespace boost (*ordering_begin,0,g,x,delta_x,left,right); vertex_iterator_t vi, vi_end; - for(tie(vi,vi_end) = vertices(g); vi != vi_end; ++vi) + for(boost::tie(vi,vi_end) = vertices(g); vi != vi_end; ++vi) { vertex_t v(*vi); drawing[v].x = x[v]; diff --git a/include/boost/graph/closeness_centrality.hpp b/include/boost/graph/closeness_centrality.hpp index 77cea7b0e..d0dcabe15 100644 --- a/include/boost/graph/closeness_centrality.hpp +++ b/include/boost/graph/closeness_centrality.hpp @@ -126,7 +126,7 @@ all_closeness_centralities(const Graph& g, typedef typename property_traits::value_type Centrality; typename graph_traits::vertex_iterator i, end; - for(tie(i, end) = vertices(g); i != end; ++i) { + for(boost::tie(i, end) = vertices(g); i != end; ++i) { DistanceMap dm = get(dist, *i); Centrality c = closeness_centrality(g, dm, measure); put(cent, *i, c); diff --git a/include/boost/graph/degree_centrality.hpp b/include/boost/graph/degree_centrality.hpp index 24ecb6c51..e3d7346cc 100644 --- a/include/boost/graph/degree_centrality.hpp +++ b/include/boost/graph/degree_centrality.hpp @@ -101,7 +101,7 @@ all_degree_centralities(const Graph& g, CentralityMap cent, Measure measure) typedef typename property_traits::value_type Centrality; VertexIterator i, end; - for(tie(i, end) = vertices(g); i != end; ++i) { + for(boost::tie(i, end) = vertices(g); i != end; ++i) { Centrality c = degree_centrality(g, *i, measure); put(cent, *i, c); } diff --git a/include/boost/graph/detail/geodesic.hpp b/include/boost/graph/detail/geodesic.hpp index 99edaf9e3..57e2a2088 100644 --- a/include/boost/graph/detail/geodesic.hpp +++ b/include/boost/graph/detail/geodesic.hpp @@ -65,7 +65,7 @@ namespace detail { // zero, so it shouldn't be too problematic. Distance ret = init; VertexIterator i, end; - for(tie(i, end) = vertices(g); i != end; ++i) { + for(boost::tie(i, end) = vertices(g); i != end; ++i) { Vertex v = *i; if(get(dist, v) != DistanceNumbers::infinity()) { ret = combine(ret, get(dist, v)); diff --git a/include/boost/graph/geodesic_distance.hpp b/include/boost/graph/geodesic_distance.hpp index a4d702749..121ca4fb2 100644 --- a/include/boost/graph/geodesic_distance.hpp +++ b/include/boost/graph/geodesic_distance.hpp @@ -156,7 +156,7 @@ all_mean_geodesics(const Graph& g, Result inf = numeric_values::infinity(); Result sum = numeric_values::zero(); VertexIterator i, end; - for(tie(i, end) = vertices(g); i != end; ++i) { + for(boost::tie(i, end) = vertices(g); i != end; ++i) { DistanceMap dm = get(dist, *i); Result r = mean_geodesic(g, dm, measure); put(geo, *i, r); diff --git a/include/boost/graph/is_kuratowski_subgraph.hpp b/include/boost/graph/is_kuratowski_subgraph.hpp index fab0b0246..8791b4cf1 100644 --- a/include/boost/graph/is_kuratowski_subgraph.hpp +++ b/include/boost/graph/is_kuratowski_subgraph.hpp @@ -33,7 +33,7 @@ namespace boost { typename graph_traits::vertex_iterator vi, vi_end, inner_vi; Graph K_5(5); - for(tie(vi,vi_end) = vertices(K_5); vi != vi_end; ++vi) + for(boost::tie(vi,vi_end) = vertices(K_5); vi != vi_end; ++vi) for(inner_vi = next(vi); inner_vi != vi_end; ++inner_vi) add_edge(*vi, *inner_vi, K_5); return K_5; @@ -47,7 +47,7 @@ namespace boost vi, vi_end, bipartition_start, inner_vi; Graph K_3_3(6); bipartition_start = next(next(next(vertices(K_3_3).first))); - for(tie(vi, vi_end) = vertices(K_3_3); vi != bipartition_start; ++vi) + for(boost::tie(vi, vi_end) = vertices(K_3_3); vi != bipartition_start; ++vi) for(inner_vi= bipartition_start; inner_vi != vi_end; ++inner_vi) add_edge(*vi, *inner_vi, K_3_3); return K_3_3; @@ -158,7 +158,7 @@ namespace boost { vertex_iterator_t vi, vi_end; - for(tie(vi,vi_end) = vertices(g); vi != vi_end; ++vi) + for(boost::tie(vi,vi_end) = vertices(g); vi != vi_end; ++vi) { vertex_t v(*vi); @@ -242,7 +242,7 @@ namespace boost if (max_size == 3) { // check to see whether we should go on to find a K_5 - for(tie(vi,vi_end) = vertices(g); vi != vi_end; ++vi) + for(boost::tie(vi,vi_end) = vertices(g); vi != vi_end; ++vi) if (neighbors[*vi].size() == 4) { target_graph = detail::tg_k_5; @@ -261,7 +261,7 @@ namespace boost v_list_t main_vertices; vertex_iterator_t vi, vi_end; - for(tie(vi,vi_end) = vertices(g); vi != vi_end; ++vi) + for(boost::tie(vi,vi_end) = vertices(g); vi != vi_end; ++vi) { if (!neighbors[*vi].empty()) main_vertices.push_back(*vi); diff --git a/include/boost/graph/is_straight_line_drawing.hpp b/include/boost/graph/is_straight_line_drawing.hpp index 6b7c39054..74775b44f 100644 --- a/include/boost/graph/is_straight_line_drawing.hpp +++ b/include/boost/graph/is_straight_line_drawing.hpp @@ -126,7 +126,7 @@ namespace boost active_map_t active_edges; edge_iterator_t ei, ei_end; - for(tie(ei,ei_end) = edges(g); ei != ei_end; ++ei) + for(boost::tie(ei,ei_end) = edges(g); ei != ei_end; ++ei) { edge_t e(*ei); vertex_t s(source(e,g)); diff --git a/include/boost/graph/make_maximal_planar.hpp b/include/boost/graph/make_maximal_planar.hpp index 70a1e08ab..8248573b4 100644 --- a/include/boost/graph/make_maximal_planar.hpp +++ b/include/boost/graph/make_maximal_planar.hpp @@ -62,7 +62,7 @@ namespace boost degree(degree_vector.begin(), vm) { vertex_iterator_t vi, vi_end; - for(tie(vi,vi_end) = vertices(g); vi != vi_end; ++vi) + for(boost::tie(vi,vi_end) = vertices(g); vi != vi_end; ++vi) put(degree, *vi, out_degree(*vi, g)); } @@ -117,7 +117,7 @@ namespace boost // Mark all of the min degree vertex's neighbors adjacency_iterator_t ai, ai_end; - for(tie(ai,ai_end) = adjacent_vertices(vertices_on_face.front(),g); + for(boost::tie(ai,ai_end) = adjacent_vertices(vertices_on_face.front(),g); ai != ai_end; ++ai ) { diff --git a/include/boost/graph/planar_canonical_ordering.hpp b/include/boost/graph/planar_canonical_ordering.hpp index d43ea4785..6cb7bdb82 100644 --- a/include/boost/graph/planar_canonical_ordering.hpp +++ b/include/boost/graph/planar_canonical_ordering.hpp @@ -67,7 +67,7 @@ namespace boost vertex_t first_vertex = *vertices(g).first; vertex_t second_vertex; adjacency_iterator_t ai, ai_end; - for(tie(ai,ai_end) = adjacent_vertices(first_vertex,g); ai != ai_end; ++ai) + for(boost::tie(ai,ai_end) = adjacent_vertices(first_vertex,g); ai != ai_end; ++ai) { if (*ai == first_vertex) continue; diff --git a/include/boost/graph/planar_face_traversal.hpp b/include/boost/graph/planar_face_traversal.hpp index 2f8a2ee33..bcd565528 100644 --- a/include/boost/graph/planar_face_traversal.hpp +++ b/include/boost/graph/planar_face_traversal.hpp @@ -98,7 +98,7 @@ namespace boost // PlanarEmbedding so that get(next_edge, e)[v] is the edge that comes // after e in the clockwise embedding around vertex v. - for(tie(vi,vi_end) = vertices(g); vi != vi_end; ++vi) + for(boost::tie(vi,vi_end) = vertices(g); vi != vi_end; ++vi) { vertex_t v(*vi); pi_begin = embedding[v].begin(); @@ -122,7 +122,7 @@ namespace boost std::vector edges_cache; std::vector vertices_in_edge; - for(tie(fi,fi_end) = edges(g); fi != fi_end; ++fi) + for(boost::tie(fi,fi_end) = edges(g); fi != fi_end; ++fi) { edge_t e(*fi); edges_cache.push_back(e); diff --git a/include/boost/graph/push_relabel_max_flow.hpp b/include/boost/graph/push_relabel_max_flow.hpp index 0e4577c2a..10215ff16 100644 --- a/include/boost/graph/push_relabel_max_flow.hpp +++ b/include/boost/graph/push_relabel_max_flow.hpp @@ -550,8 +550,8 @@ namespace boost { } // do the bottom u = bos; - ai = out_edges(u, g).first; - while (get(excess_flow, u) > 0) { + boost::tie(ai, a_end) = out_edges(u, g); + while (get(excess_flow, u) > 0 && ai != a_end) { if (get(capacity, *ai) == 0 && is_residual_edge(*ai)) push_flow(*ai); ++ai; diff --git a/include/boost/graph/tiernan_all_cycles.hpp b/include/boost/graph/tiernan_all_cycles.hpp index f750eb177..d45567962 100644 --- a/include/boost/graph/tiernan_all_cycles.hpp +++ b/include/boost/graph/tiernan_all_cycles.hpp @@ -193,7 +193,7 @@ namespace detail u = p.back(), v = p.front(); OutIterator i, end; - for(tie(i, end) = out_edges(u, g); i != end; ++i) { + for(boost::tie(i, end) = out_edges(u, g); i != end; ++i) { if((target(*i, g) == v)) { return true; } @@ -220,7 +220,7 @@ namespace detail // AdjacencyIterator i, end; OutIterator i, end; - for(tie(i, end) = out_edges(u, g); i != end; ++i) { + for(boost::tie(i, end) = out_edges(u, g); i != end; ++i) { Vertex v = target(*i, g); // if we can actually extend along this edge, @@ -324,7 +324,7 @@ tiernan_all_cycles(const Graph& g, typedef typename graph_traits::vertex_iterator VertexIterator; VertexIterator i, end; - for(tie(i, end) = vertices(g); i != end; ++i) { + for(boost::tie(i, end) = vertices(g); i != end; ++i) { detail::all_cycles_from_vertex(g, *i, vis, minlen, maxlen); } } diff --git a/include/boost/graph/write_dimacs.hpp b/include/boost/graph/write_dimacs.hpp index 0b8af17df..a9a890465 100644 --- a/include/boost/graph/write_dimacs.hpp +++ b/include/boost/graph/write_dimacs.hpp @@ -64,7 +64,7 @@ void write_dimacs_max_flow(const Graph& g, //output the edges edge_iterator ei, e_end; - for(tie(ei,e_end) = edges(g); ei!=e_end; ++ei){ + for(boost::tie(ei,e_end) = edges(g); ei!=e_end; ++ei){ out << "a " << idx[ source(*ei, g) ] + 1 << " " << idx[ target(*ei, g) ] + 1 << " " << get(capacity,*ei) << std::endl; } } diff --git a/test/all_planar_input_files_test.cpp b/test/all_planar_input_files_test.cpp index ff9aabdec..5fec2e362 100644 --- a/test/all_planar_input_files_test.cpp +++ b/test/all_planar_input_files_test.cpp @@ -137,7 +137,7 @@ int test_graph(const std::string& dimacs_filename) // Initialize the interior edge index property_map::type e_index = get(edge_index, g); e_size_t edge_count = 0; - for(tie(ei, ei_end) = edges(g); ei != ei_end; ++ei) + for(boost::tie(ei, ei_end) = edges(g); ei != ei_end; ++ei) put(e_index, *ei, edge_count++); // Initialize the interior vertex index - not needed if the vertices @@ -145,7 +145,7 @@ int test_graph(const std::string& dimacs_filename) /* property_map::type v_index = get(vertex_index, g); v_size_t vertex_count = 0; - for(tie(vi, vi_end) = vertices(g); vi != vi_end; ++vi) + for(boost::tie(vi, vi_end) = vertices(g); vi != vi_end; ++vi) put(v_index, *vi, vertex_count++); */ diff --git a/test/basic_planarity_test.cpp b/test/basic_planarity_test.cpp index 3c956d7eb..21ae969a6 100644 --- a/test/basic_planarity_test.cpp +++ b/test/basic_planarity_test.cpp @@ -25,7 +25,7 @@ struct VertexIndexUpdater typename property_map::type index = get(vertex_index, g); typename graph_traits::vertex_iterator vi, vi_end; typename graph_traits::vertices_size_type cnt = 0; - for(tie(vi,vi_end) = vertices(g); vi != vi_end; ++vi) + for(boost::tie(vi,vi_end) = vertices(g); vi != vi_end; ++vi) put(index, *vi, cnt++); } }; diff --git a/test/bellman-test.cpp b/test/bellman-test.cpp index 53bba704a..7fa948aaf 100644 --- a/test/bellman-test.cpp +++ b/test/bellman-test.cpp @@ -42,7 +42,7 @@ int test_main(int, char*[]) weight_pmap = get(edge_weight, g); int i = 0; - for(tie(ei, ei_end) = edges(g); ei != ei_end; ++ei, ++i) + for(boost::tie(ei, ei_end) = edges(g); ei != ei_end; ++ei, ++i) weight_pmap[*ei] = weight[i]; std::vector parent(numVertex); diff --git a/test/isomorphism.cpp b/test/isomorphism.cpp index 3650fdbba..a151cca1d 100644 --- a/test/isomorphism.cpp +++ b/test/isomorphism.cpp @@ -93,6 +93,63 @@ void generate_random_digraph(Graph& g, double edge_probability) } } +void test_isomorphism2() +{ + typedef adjacency_list graph1; + typedef adjacency_list > graph2; + + graph1 g1(2); + add_edge(vertex(0, g1), vertex(1, g1), g1); + add_edge(vertex(1, g1), vertex(1, g1), g1); + graph2 g2; + randomly_permute_graph(g1, g2); + + int v_idx = 0; + for (graph2::vertex_iterator v = vertices(g2).first; + v != vertices(g2).second; ++v) { + put(vertex_index_t(), g2, *v, v_idx++); + } + + std::map mapping; + + bool isomorphism_correct; + clock_t start = clock(); + BOOST_CHECK(isomorphism_correct = isomorphism + (g1, g2, isomorphism_map(make_assoc_property_map(mapping)))); + clock_t end = clock(); + + std::cout << "Elapsed time (clock cycles): " << (end - start) << std::endl; + + bool verify_correct; + BOOST_CHECK(verify_correct = + verify_isomorphism(g1, g2, make_assoc_property_map(mapping))); + + if (!isomorphism_correct || !verify_correct) { + // Output graph 1 + { + std::ofstream out("isomorphism_failure.bg1"); + out << num_vertices(g1) << std::endl; + for (graph1::edge_iterator e = edges(g1).first; + e != edges(g1).second; ++e) { + out << get(vertex_index_t(), g1, source(*e, g1)) << ' ' + << get(vertex_index_t(), g1, target(*e, g1)) << std::endl; + } + } + + // Output graph 2 + { + std::ofstream out("isomorphism_failure.bg2"); + out << num_vertices(g2) << std::endl; + for (graph2::edge_iterator e = edges(g2).first; + e != edges(g2).second; ++e) { + out << get(vertex_index_t(), g2, source(*e, g2)) << ' ' + << get(vertex_index_t(), g2, target(*e, g2)) << std::endl; + } + } + } +} + void test_isomorphism(int n, double edge_probability) { typedef adjacency_list graph1; diff --git a/test/labeled_graph.cpp b/test/labeled_graph.cpp index 455675d52..df16aa0f4 100644 --- a/test/labeled_graph.cpp +++ b/test/labeled_graph.cpp @@ -62,7 +62,7 @@ void label_graph(Graph& g) typedef typename graph_traits::vertex_iterator Iter; Iter f, l; int x = 0; - for(tie(f, l) = vertices(g); f != l; ++f, ++x) { + for(boost::tie(f, l) = vertices(g); f != l; ++f, ++x) { label_vertex(*f, x, g); } } diff --git a/test/make_bicon_planar_test.cpp b/test/make_bicon_planar_test.cpp index 1eacf0a04..9e31c4c11 100644 --- a/test/make_bicon_planar_test.cpp +++ b/test/make_bicon_planar_test.cpp @@ -25,7 +25,7 @@ void reset_edge_index(Graph& g) typename property_map::type index = get(edge_index, g); typename graph_traits::edge_iterator ei, ei_end; typename graph_traits::edges_size_type cnt = 0; - for(tie(ei,ei_end) = edges(g); ei != ei_end; ++ei) + for(boost::tie(ei,ei_end) = edges(g); ei != ei_end; ++ei) put(index, *ei, cnt++); } @@ -54,7 +54,7 @@ struct UpdateVertexIndex typename property_map::type index = get(vertex_index, g); typename graph_traits::vertex_iterator vi, vi_end; typename graph_traits::vertices_size_type cnt = 0; - for(tie(vi,vi_end) = vertices(g); vi != vi_end; ++vi) + for(boost::tie(vi,vi_end) = vertices(g); vi != vi_end; ++vi) put(index, *vi, cnt++); } }; @@ -87,7 +87,7 @@ void test_line_graph(VertexIndexUpdater vertex_index_updater, int size) embedding_t embedding(embedding_storage.begin(), get(vertex_index, g)); typename graph_traits::vertex_iterator vi, vi_end; - for(tie(vi,vi_end) = vertices(g); vi != vi_end; ++vi) + for(boost::tie(vi,vi_end) = vertices(g); vi != vi_end; ++vi) std::copy(out_edges(*vi,g).first, out_edges(*vi,g).second, std::back_inserter(embedding[*vi])); BOOST_CHECK(biconnected_components(g, make_vector_property_map(get(edge_index,g))) > 1); diff --git a/test/make_connected_test.cpp b/test/make_connected_test.cpp index a33ee9a8e..40517f0f7 100644 --- a/test/make_connected_test.cpp +++ b/test/make_connected_test.cpp @@ -24,7 +24,7 @@ void reset_edge_index(Graph& g) typename property_map::type index = get(edge_index, g); typename graph_traits::edge_iterator ei, ei_end; typename graph_traits::edges_size_type cnt = 0; - for(tie(ei,ei_end) = edges(g); ei != ei_end; ++ei) + for(boost::tie(ei,ei_end) = edges(g); ei != ei_end; ++ei) put(index, *ei, cnt++); } @@ -36,7 +36,7 @@ void reset_vertex_index(Graph& g) typename property_map::type index = get(vertex_index, g); typename graph_traits::vertex_iterator vi, vi_end; typename graph_traits::vertices_size_type cnt = 0; - for(tie(vi,vi_end) = vertices(g); vi != vi_end; ++vi) + for(boost::tie(vi,vi_end) = vertices(g); vi != vi_end; ++vi) put(index, *vi, cnt++); } diff --git a/test/make_maximal_planar_test.cpp b/test/make_maximal_planar_test.cpp index 7d5c6a570..7b174f43d 100644 --- a/test/make_maximal_planar_test.cpp +++ b/test/make_maximal_planar_test.cpp @@ -24,7 +24,7 @@ void reset_edge_index(Graph& g) typename property_map::type index = get(edge_index, g); typename graph_traits::edge_iterator ei, ei_end; typename graph_traits::edges_size_type cnt = 0; - for(tie(ei,ei_end) = edges(g); ei != ei_end; ++ei) + for(boost::tie(ei,ei_end) = edges(g); ei != ei_end; ++ei) put(index, *ei, cnt++); } @@ -56,7 +56,7 @@ struct UpdateVertexIndex typename property_map::type index = get(vertex_index, g); typename graph_traits::vertex_iterator vi, vi_end; typename graph_traits::vertices_size_type cnt = 0; - for(tie(vi,vi_end) = vertices(g); vi != vi_end; ++vi) + for(boost::tie(vi,vi_end) = vertices(g); vi != vi_end; ++vi) put(index, *vi, cnt++); } }; @@ -89,7 +89,7 @@ void test_cycle(VertexIndexUpdater vertex_index_updater, int size) embedding_t embedding(embedding_storage.begin(), get(vertex_index, g)); typename graph_traits::vertex_iterator vi, vi_end; - for(tie(vi,vi_end) = vertices(g); vi != vi_end; ++vi) + for(boost::tie(vi,vi_end) = vertices(g); vi != vi_end; ++vi) std::copy(out_edges(*vi,g).first, out_edges(*vi,g).second, std::back_inserter(embedding[*vi])); BOOST_CHECK(boyer_myrvold_planarity_test(g)); diff --git a/test/parallel_edges_loops_test.cpp b/test/parallel_edges_loops_test.cpp index 42cd77fc5..52bb4e926 100644 --- a/test/parallel_edges_loops_test.cpp +++ b/test/parallel_edges_loops_test.cpp @@ -111,7 +111,7 @@ void read_dimacs(Graph& g, const std::string& filename) vertex_iterator_t vi, vi_end; long count = 0; long mult_count = 0; - for(tie(vi, vi_end) = vertices(g); vi != vi_end; ++vi) + for(boost::tie(vi, vi_end) = vertices(g); vi != vi_end; ++vi) { if (count % vertex_stride == 0) { @@ -210,7 +210,7 @@ int test_graph(const std::string& dimacs_filename) // Initialize the interior edge index property_map::type e_index = get(edge_index, g); e_size_t edge_count = 0; - for(tie(ei, ei_end) = edges(g); ei != ei_end; ++ei) + for(boost::tie(ei, ei_end) = edges(g); ei != ei_end; ++ei) put(e_index, *ei, edge_count++); // Initialize the interior vertex index - not needed if the vertices @@ -218,7 +218,7 @@ int test_graph(const std::string& dimacs_filename) /* property_map::type v_index = get(vertex_index, g); v_size_t vertex_count = 0; - for(tie(vi, vi_end) = vertices(g); vi != vi_end; ++vi) + for(boost::tie(vi, vi_end) = vertices(g); vi != vi_end; ++vi) put(v_index, *vi, vertex_count++); */ diff --git a/test/test_construction.hpp b/test/test_construction.hpp index 6fcd95dfc..2f0939055 100644 --- a/test/test_construction.hpp +++ b/test/test_construction.hpp @@ -93,7 +93,7 @@ void connect_graph(Graph& g, VertexSet const& verts, boost::mpl::false_) { std::cout << "...connect_normal\n"; Pair *f, *l; - for(tie(f, l) = edge_pairs(); f != l; ++f) { + for(boost::tie(f, l) = edge_pairs(); f != l; ++f) { Pair const& e = *f; add_edge(verts[e.first], verts[e.second], g); } diff --git a/test/transitive_closure_test2.cpp b/test/transitive_closure_test2.cpp index 1dde3e449..02d38f36e 100644 --- a/test/transitive_closure_test2.cpp +++ b/test/transitive_closure_test2.cpp @@ -29,7 +29,7 @@ int main(int argc, char *argv[]) { << endl; cout << "transitive closure: "; graph_t::edge_iterator i,iend; - for(tie(i,iend) = edges(g_TC);i!=iend;++i) { + for(boost::tie(i,iend) = edges(g_TC);i!=iend;++i) { cout << source(*i,g_TC) << "->" << target(*i,g_TC) << " "; } cout << endl; From 366cd32060920387ad79b6be11693783ffdffdb3 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Fri, 18 Nov 2011 20:06:07 +0000 Subject: [PATCH 089/333] Added comparison operators; fixes #6137 [SVN r75547] --- include/boost/graph/reverse_graph.hpp | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/include/boost/graph/reverse_graph.hpp b/include/boost/graph/reverse_graph.hpp index 6c804208d..97bf247bd 100644 --- a/include/boost/graph/reverse_graph.hpp +++ b/include/boost/graph/reverse_graph.hpp @@ -39,6 +39,18 @@ struct reverse_graph_tag { }; friend bool operator!=(const reverse_graph_edge_descriptor& a, const reverse_graph_edge_descriptor& b) { return a.underlying_desc != b.underlying_desc; } + friend bool operator<(const reverse_graph_edge_descriptor& a, const reverse_graph_edge_descriptor& b) { + return a.underlying_desc < b.underlying_desc; + } + friend bool operator>(const reverse_graph_edge_descriptor& a, const reverse_graph_edge_descriptor& b) { + return a.underlying_desc > b.underlying_desc; + } + friend bool operator<=(const reverse_graph_edge_descriptor& a, const reverse_graph_edge_descriptor& b) { + return a.underlying_desc <= b.underlying_desc; + } + friend bool operator>=(const reverse_graph_edge_descriptor& a, const reverse_graph_edge_descriptor& b) { + return a.underlying_desc >= b.underlying_desc; + } }; template From 345a6b964b5a5b02070a6caca48465084bf2d145 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Thu, 8 Dec 2011 01:43:39 +0000 Subject: [PATCH 090/333] Removed debugging output; fixes #6239 [SVN r75861] --- include/boost/graph/kamada_kawai_spring_layout.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/boost/graph/kamada_kawai_spring_layout.hpp b/include/boost/graph/kamada_kawai_spring_layout.hpp index f39ef90ca..f8a210cab 100644 --- a/include/boost/graph/kamada_kawai_spring_layout.hpp +++ b/include/boost/graph/kamada_kawai_spring_layout.hpp @@ -218,7 +218,7 @@ namespace boost { detail::graph::compute_edge_length(g, distance, index, edge_or_side_length); - std::cerr << "edge_length = " << edge_length << std::endl; + // std::cerr << "edge_length = " << edge_length << std::endl; // Compute l_{ij} and k_{ij} const weight_type K = spring_constant; @@ -275,7 +275,7 @@ namespace boost { E += .5 * k_ij * (dist - l_ij) * (dist - l_ij); } } - std::cerr << "E = " << E << std::endl; + // std::cerr << "E = " << E << std::endl; // Compute the elements of the Jacobian // From From 03193c2fb468f8241249a564b476da825b42e8af Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Thu, 8 Dec 2011 01:59:21 +0000 Subject: [PATCH 091/333] Added documentation for edge_predecessor_recorder and fixed several typos in other doc pages [SVN r75862] --- doc/distance_recorder.html | 2 +- doc/edge_predecessor_recorder.html | 197 +++++++++++++++++++++++++++++ doc/predecessor_recorder.html | 4 +- doc/table_of_contents.html | 1 + 4 files changed, 201 insertions(+), 3 deletions(-) create mode 100644 doc/edge_predecessor_recorder.html diff --git a/doc/distance_recorder.html b/doc/distance_recorder.html index fe7cd559f..a6b05fe27 100644 --- a/doc/distance_recorder.html +++ b/doc/distance_recorder.html @@ -153,7 +153,7 @@

      See Also

      Visitor concepts

      The following are other event visitors: predecessor_recorder, + href="./predecessor_recorder.html">predecessor_recorder, time_stamper, and property_writer. diff --git a/doc/edge_predecessor_recorder.html b/doc/edge_predecessor_recorder.html new file mode 100644 index 000000000..9ed626b63 --- /dev/null +++ b/doc/edge_predecessor_recorder.html @@ -0,0 +1,197 @@ + + + +Boost Graph Library: edge_predecessor_recorder + +C++ Boost + +
      + +

      +
      +edge_predecessor_recorder<PredEdgeMap, EventTag>
      +
      +

      + +This is an EventVisitor that records +the predecessor (or parent) edge of a vertex in a property +map. This is particularly useful in graph search algorithms where +recording the predecessors is an efficient way to encode the search +tree that was traversed during the search. The edge predecessor recorder is +typically used with the on_tree_edge or +on_relax_edge events and cannot be used with vertex events. This +visitor is meant to be used instead of predecessor_recorder when a +graph has parallel edges and it is necessary to know which incoming edge a +search algorithm +used to get to a particular vertex. + +

      +edge_predecessor_recorder can be used with graph algorithms by +wrapping it with an algorithm-specific adaptor, such as bfs_visitor and dfs_visitor. Also, this event +visitor can be combined with other event visitors using +std::pair to form an EventVisitorList. + +

      +Algorithms such as Dijkstra's and breadth-first search will not assign +a predecessor edge to the source vertex (which is the root of the search +tree). It is often useful to initialize the source vertex's +predecessor to a special value, thereby identifying the root vertex. +When using an algorithm like +depth-first search that creates a forest (multiple search trees) it +is useful to do the same for every vertex. This +way all the root nodes can be distinguished. + + + + +

      Model of

      + +EventVisitor + + +

      Where Defined

      + +

      + +boost/graph/visitors.hpp + +

      Template Parameters

      + +

      + + + + + + + + + + + + + + + +
      ParameterDescriptionDefault
      PredEdgeMap +A WritablePropertyMap +where the key and value types are the vertex and edge descriptor types, respectively, of the graph. + 
      EventTag +The tag to specify when the edge_predecessor_recorder should be +applied during the graph algorithm. EventTag must be an +edge event. + 
      + +

      Associated Types

      + + + + + + + + + + + + +
      TypeDescription
      edge_predecessor_recorder::event_filter +This will be the same type as the template parameter EventTag. +
      + +

      Member Functions

      + +

      + + + + + + + + + + + + + + + + +
      MemberDescription
      +edge_predecessor_recorder(PredEdgeMap pa); + +Construct an edge predecessor recorder object with predecessor property map +pa. +
      +template <class Edge, class Graph>
      +void operator()(Edge e, const Graph& g); +
      +Given edge e = (u,v), this records e as the +predecessor (or parent) edge of v. +
      + +

      Non-Member Functions

      + + + + + + + + +
      FunctionDescription
      +template <class PredEdgeMap, class Tag>
      +edge_predecessor_recorder<PredEdgeMap, Tag>
      +record_edge_predecessors(PredEdgeMap pa, Tag); +
      +A convenient way to create a edge_predecessor_recorder. +
      + +

      See Also

      + +Visitor concepts +

      +The following are other event visitors: distance_recorder, +time_stamper, +and property_writer. + + +
      +


      + + +
      Copyright © 2000-2001 +Jeremy Siek, +Indiana University (jsiek@osl.iu.edu)
      +Lie-Quan Lee, Indiana University (llee@cs.indiana.edu)
      +Andrew Lumsdaine, +Indiana University (lums@osl.iu.edu) +
      + + + + + + diff --git a/doc/predecessor_recorder.html b/doc/predecessor_recorder.html index 75fe44a6f..6f600eafd 100644 --- a/doc/predecessor_recorder.html +++ b/doc/predecessor_recorder.html @@ -31,7 +31,7 @@

      predecessor_recorder can be used with graph algorithms by -wrapping it with the algorithm specific adaptor, such as bfs_visitor and dfs_visitor. Also, this event visitor can be combined with other event visitors using @@ -44,7 +44,7 @@

      predecessor to itself, thereby identifying the root vertex as the only vertex which is its own parent. When using an algorithm like depth-first search that creates a forest (multiple search trees) it -is useful to intialize the predecessor of every vertex to itself. This +is useful to initialize the predecessor of every vertex to itself. This way all the root nodes can be distinguished. diff --git a/doc/table_of_contents.html b/doc/table_of_contents.html index db02575c8..6032e9ccf 100644 --- a/doc/table_of_contents.html +++ b/doc/table_of_contents.html @@ -90,6 +90,7 @@

      Table of Contents: the Boost Graph Library
    2. Event Visitors
      1. predecessor_recorder +
      2. edge_predecessor_recorder
      3. distance_recorder
      4. time_stamper
      5. property_writer From 2a5874c7b9fdc235ac4d942aa2a66d3f3ad9dbed Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Thu, 8 Dec 2011 02:00:04 +0000 Subject: [PATCH 092/333] Fixed typo [SVN r75863] --- doc/isomorphism-impl.w | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/isomorphism-impl.w b/doc/isomorphism-impl.w index 58b4bed89..e50337d1c 100644 --- a/doc/isomorphism-impl.w +++ b/doc/isomorphism-impl.w @@ -174,7 +174,7 @@ need to consider those vertices that have the same vertex invariant number. The number of vertices in a graph with the same vertex invariant number $i$ is called the \emph{invariant multiplicity} for $i$. In this implementation, by default we use the out-degree of the -vertex as the vertex invariant, though the user can also supply there +vertex as the vertex invariant, though the user can also supply their own invariant function. The ability of the invariant function to prune the search space varies widely with the type of graph. From 17f92dd61e81feabb3c4eb2576a82219b9d84fb1 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Fri, 9 Dec 2011 17:53:43 +0000 Subject: [PATCH 093/333] Added include of ; fixes #6246 [SVN r75878] --- include/boost/graph/chrobak_payne_drawing.hpp | 1 + 1 file changed, 1 insertion(+) diff --git a/include/boost/graph/chrobak_payne_drawing.hpp b/include/boost/graph/chrobak_payne_drawing.hpp index 6060171f8..ef6ae5c9c 100644 --- a/include/boost/graph/chrobak_payne_drawing.hpp +++ b/include/boost/graph/chrobak_payne_drawing.hpp @@ -11,6 +11,7 @@ #include #include +#include #include #include //for next and prior #include From fc1619d91e784181ff9e95e680717e92de47abbc Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Sun, 11 Dec 2011 07:19:19 +0000 Subject: [PATCH 094/333] Fixed copying of reverse_graphs to compensate for new reverse_edge_descriptor class [SVN r75891] --- include/boost/graph/copy.hpp | 25 ++++++++++++++++++++++--- include/boost/graph/reverse_graph.hpp | 27 +++++++++++++++++++++++---- 2 files changed, 45 insertions(+), 7 deletions(-) diff --git a/include/boost/graph/copy.hpp b/include/boost/graph/copy.hpp index 8ef01238c..668068681 100644 --- a/include/boost/graph/copy.hpp +++ b/include/boost/graph/copy.hpp @@ -44,6 +44,7 @@ #include #include #include +#include #include #include #include @@ -53,6 +54,21 @@ namespace boost { namespace detail { + // Hack to make transpose_graph work with the same interface as before + template + struct remove_reverse_edge_descriptor { + typedef Desc type; + static Desc convert(const Desc& d) {return d;} + }; + + template + struct remove_reverse_edge_descriptor > { + typedef Desc type; + static Desc convert(const reverse_graph_edge_descriptor& d) { + return d.underlying_desc; + } + }; + // Default edge and vertex property copiers template @@ -112,6 +128,7 @@ namespace boost { CopyVertex copy_vertex, CopyEdge copy_edge, Orig2CopyVertexIndexMap orig2copy, IndexMap) { + typedef remove_reverse_edge_descriptor::edge_descriptor> cvt; typename graph_traits::vertex_iterator vi, vi_end; for (boost::tie(vi, vi_end) = vertices(g_in); vi != vi_end; ++vi) { typename graph_traits::vertex_descriptor @@ -126,7 +143,7 @@ namespace boost { boost::tie(new_e, inserted) = add_edge(get(orig2copy, source(*ei, g_in)), get(orig2copy, target(*ei, g_in)), g_out); - copy_edge(*ei, new_e); + copy_edge(cvt::convert(*ei), new_e); } } }; @@ -141,6 +158,7 @@ namespace boost { CopyVertex copy_vertex, CopyEdge copy_edge, Orig2CopyVertexIndexMap orig2copy, IndexMap) { + typedef remove_reverse_edge_descriptor::edge_descriptor> cvt; typename graph_traits::vertex_iterator vi, vi_end; for (boost::tie(vi, vi_end) = vertices(g_in); vi != vi_end; ++vi) { typename graph_traits::vertex_descriptor @@ -156,7 +174,7 @@ namespace boost { boost::tie(new_e, inserted) = add_edge(get(orig2copy, source(*ei, g_in)), get(orig2copy, target(*ei, g_in)), g_out); - copy_edge(*ei, new_e); + copy_edge(cvt::convert(*ei), new_e); } } } @@ -173,6 +191,7 @@ namespace boost { Orig2CopyVertexIndexMap orig2copy, IndexMap index_map) { + typedef remove_reverse_edge_descriptor::edge_descriptor> cvt; typedef color_traits Color; std::vector color(num_vertices(g_in), Color::white()); @@ -192,7 +211,7 @@ namespace boost { boost::tie(new_e, inserted) = add_edge(get(orig2copy, source(*ei,g_in)), get(orig2copy, target(*ei,g_in)), g_out); - copy_edge(*ei, new_e); + copy_edge(cvt::convert(*ei), new_e); } } color[get(index_map, *vi)] = Color::black(); diff --git a/include/boost/graph/reverse_graph.hpp b/include/boost/graph/reverse_graph.hpp index 97bf247bd..393750a09 100644 --- a/include/boost/graph/reverse_graph.hpp +++ b/include/boost/graph/reverse_graph.hpp @@ -28,6 +28,7 @@ struct reverse_graph_tag { }; class reverse_graph_edge_descriptor { public: EdgeDesc underlying_desc; + typedef EdgeDesc base_descriptor_type; public: explicit reverse_graph_edge_descriptor(const EdgeDesc& underlying_desc = EdgeDesc()) @@ -70,6 +71,18 @@ struct reverse_graph_tag { }; make_transform_iterator(ip.second, reverse_graph_edge_descriptor_maker())); } + // Get the underlying descriptor from a vertex or edge descriptor + template + struct get_underlying_descriptor_from_reverse_descriptor { + typedef Desc type; + static Desc convert(const Desc& d) {return d;} + }; + template + struct get_underlying_descriptor_from_reverse_descriptor > { + typedef Desc type; + static Desc convert(const reverse_graph_edge_descriptor& d) {return d.underlying_desc;} + }; + template struct choose_rev_edge_iter { }; template <> struct choose_rev_edge_iter { template struct bind_ { @@ -129,14 +142,20 @@ class reverse_graph { #ifndef BOOST_GRAPH_NO_BUNDLED_PROPERTIES // Bundled properties support template - typename graph::detail::bundled_result::type& + typename graph::detail::bundled_result< + BidirectionalGraph, + typename detail::get_underlying_descriptor_from_reverse_descriptor::type + >::type& operator[](Descriptor x) - { return m_g[x]; } + { return detail::get_underlying_descriptor_from_reverse_descriptor::convert(m_g[x]); } template - typename graph::detail::bundled_result::type const& + typename graph::detail::bundled_result< + BidirectionalGraph, + typename detail::get_underlying_descriptor_from_reverse_descriptor::type + >::type const& operator[](Descriptor x) const - { return m_g[x]; } + { return detail::get_underlying_descriptor_from_reverse_descriptor::convert(m_g[x]); } #endif // BOOST_GRAPH_NO_BUNDLED_PROPERTIES static vertex_descriptor null_vertex() From 79573b5dbd444fd8aa741365d694f443147c25f7 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Sun, 11 Dec 2011 21:09:33 +0000 Subject: [PATCH 095/333] Added another copy_graph hack for transpose_graph [SVN r75906] --- include/boost/graph/copy.hpp | 29 ++++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/include/boost/graph/copy.hpp b/include/boost/graph/copy.hpp index 668068681..964ba2aa4 100644 --- a/include/boost/graph/copy.hpp +++ b/include/boost/graph/copy.hpp @@ -69,6 +69,33 @@ namespace boost { } }; + // Add a reverse_graph_edge_descriptor wrapper if the Graph is a + // reverse_graph but the edge descriptor is from the original graph (this + // case comes from the fact that transpose_graph uses reverse_graph + // internally but doesn't expose the different edge descriptor type to the + // user). + template + struct add_reverse_edge_descriptor { + typedef Desc type; + static Desc convert(const Desc& d) {return d;} + }; + + template + struct add_reverse_edge_descriptor > { + typedef reverse_graph_edge_descriptor type; + static reverse_graph_edge_descriptor convert(const Desc& d) { + return reverse_graph_edge_descriptor(d); + } + }; + + template + struct add_reverse_edge_descriptor, boost::reverse_graph > { + typedef reverse_graph_edge_descriptor type; + static reverse_graph_edge_descriptor convert(const reverse_graph_edge_descriptor& d) { + return d; + } + }; + // Default edge and vertex property copiers template @@ -79,7 +106,7 @@ namespace boost { template void operator()(const Edge1& e1, Edge2& e2) const { - put(edge_all_map2, e2, get(edge_all_map1, e1)); + put(edge_all_map2, e2, get(edge_all_map1, add_reverse_edge_descriptor::convert(e1))); } typename property_map::const_type edge_all_map1; mutable typename property_map::type edge_all_map2; From 8f3dd3a4f99949835bce7913720dae90330c3b97 Mon Sep 17 00:00:00 2001 From: Steven Watanabe Date: Thu, 15 Dec 2011 22:07:53 +0000 Subject: [PATCH 096/333] Fix search for SDB and LEDA. [SVN r75970] --- test/Jamfile.v2 | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index e0cb54ac6..32c73f3de 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -8,6 +8,7 @@ # LEDA (also top level directory) at the command line of jam using -s import modules ; +import path ; path-constant TEST_DIR : . ; @@ -124,23 +125,25 @@ test-suite graph_test : ; # Run SDB tests only when -sSDB= is set. -if [ modules.peek : SDB ] != "" +local SDB = [ modules.peek : SDB ] ; +if $(SDB) { - local SDB_DEPENDENCIES = - $(SGB) $(SGB)/libgb.a ; + local sdb-root = [ path.root [ path.make $(SDB) ] [ path.pwd ] ] ; + local sdb-lib = [ path.join $(sdb-root) libgb.a ] ; - compile stanford_graph_cc.cpp - $(SDB_DEPENDENCIES) ; + compile stanford_graph_cc.cpp : + $(sdb-root) $(sdb-lib) ; } # Run LEDA tests only when -sLEDA= is set. -if [ modules.peek : LEDA ] != "" +local LEDA = [ modules.peek : LEDA ] ; +if $(LEDA) { - local LEDA_DEPENDENCIES = - $(LEDA)/incl - $(LEDA)/libG.a - ; + local leda-root = [ path.root [ path.make $(LEDA) ] [ path.pwd ] ] ; + local leda-include = [ path.join $(leda-root) incl ] ; + local leda-lib = [ path.join $(leda-root) libG.a ] ; - compile leda_graph_cc.cpp - $(LEDA_DEPENDENCIES) ; + compile leda_graph_cc.cpp : + $(leda-include) + $(leda-lib) ; } From 52d7bc8d5e5566359bb8a95535230cf716f516c1 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Thu, 15 Dec 2011 22:36:20 +0000 Subject: [PATCH 097/333] Applied patch from Jens Muller [SVN r75973] --- include/boost/graph/leda_graph.hpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/include/boost/graph/leda_graph.hpp b/include/boost/graph/leda_graph.hpp index 687a10dde..af95692a8 100644 --- a/include/boost/graph/leda_graph.hpp +++ b/include/boost/graph/leda_graph.hpp @@ -17,9 +17,9 @@ #include #include -#include -#include -#include +#include +#include +#include // The functions and classes in this file allows the user to // treat a LEDA GRAPH object as a boost graph "as is". No @@ -884,7 +884,7 @@ namespace boost { inline typename boost::property_traits< typename boost::property_map,PropertyTag>::const_type -::value_type + >::value_type get(PropertyTag p, const leda::GRAPH& g, const Key& key) { return get(get(p, g), key); } From 456f4006cbb543b4c45ed2d9d129c6e895b872c6 Mon Sep 17 00:00:00 2001 From: Steven Watanabe Date: Thu, 15 Dec 2011 22:59:03 +0000 Subject: [PATCH 098/333] Remove unused library. [SVN r75974] --- test/Jamfile.v2 | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 32c73f3de..8d26b17c4 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -129,10 +129,9 @@ local SDB = [ modules.peek : SDB ] ; if $(SDB) { local sdb-root = [ path.root [ path.make $(SDB) ] [ path.pwd ] ] ; - local sdb-lib = [ path.join $(sdb-root) libgb.a ] ; compile stanford_graph_cc.cpp : - $(sdb-root) $(sdb-lib) ; + $(sdb-root) ; } # Run LEDA tests only when -sLEDA= is set. @@ -141,9 +140,7 @@ if $(LEDA) { local leda-root = [ path.root [ path.make $(LEDA) ] [ path.pwd ] ] ; local leda-include = [ path.join $(leda-root) incl ] ; - local leda-lib = [ path.join $(leda-root) libG.a ] ; compile leda_graph_cc.cpp : - $(leda-include) - $(leda-lib) ; + $(leda-include) ; } From 231bb5dbfb6a85fe9e361a9a8477eb19559a29c4 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Sun, 18 Dec 2011 20:53:26 +0000 Subject: [PATCH 099/333] Added documented way to get underlying edge descriptor from a reverse_graph; changed name of member to prevent future use [SVN r76049] --- doc/reverse_graph.html | 29 ++++++++- include/boost/graph/copy.hpp | 24 ++++---- include/boost/graph/properties.hpp | 2 + include/boost/graph/reverse_graph.hpp | 88 ++++++++++++++++++++++----- test/reverse_graph_cc.cpp | 2 + 5 files changed, 117 insertions(+), 28 deletions(-) diff --git a/doc/reverse_graph.html b/doc/reverse_graph.html index 96d03537c..bb4a10f19 100644 --- a/doc/reverse_graph.html +++ b/doc/reverse_graph.html @@ -27,7 +27,7 @@

        a BidirectionalGraph, effectively transposing the graph. The construction of the reverse_graph is constant time, providing a highly efficient -way to obtain a transposed-view of a graph. +way to obtain a transposed view of a graph.

        Example

        @@ -215,6 +215,16 @@

        Associated Types


        +property_map<reverse_graph, edge_underlying_t>::type
        +and
        +property_map<reverse_graph, edge_underlying_t>::const_type +

        +An edge property type mapping from edge descriptors in the reverse_graph to +edge descriptors in the underlying BidirectionalGraph object. + +
        + +

        Member Functions


        @@ -358,6 +368,16 @@

        Non-Member Functions


        +
        +property_map<reverse_graph, edge_underlying_t>::const_type
        +get(PropertyTag, const reverse_graph& g)
        +
        +Returns a property map object that converts from edge descriptors in the +reverse_graph to edge descriptors in the underlying +BidirectionalGraph object. + +
        +
         template <class PropertyTag, class X>
         typename property_traits<property_map<reverse_graph, PropertyTag>::const_type>::value_type
        @@ -367,6 +387,13 @@ 

        Non-Member Functions

        a vertex or edge descriptor.
        +
        +typename graph_traits<BidirectionalGraph>::edge_descriptor
        +get(edge_underlying_t, const reverse_graph& g, edge_descriptor e)
        +
        +This returns the underlying edge descriptor for the edge e in the reverse_graph. +
        +
         template <class PropertyTag, class X, class Value>
         void
        diff --git a/include/boost/graph/copy.hpp b/include/boost/graph/copy.hpp
        index 964ba2aa4..0dc6c664a 100644
        --- a/include/boost/graph/copy.hpp
        +++ b/include/boost/graph/copy.hpp
        @@ -55,17 +55,17 @@ namespace boost {
           namespace detail {
         
             // Hack to make transpose_graph work with the same interface as before
        -    template 
        +    template 
             struct remove_reverse_edge_descriptor {
               typedef Desc type;
        -      static Desc convert(const Desc& d) {return d;}
        +      static Desc convert(const Desc& d, const Graph&) {return d;}
             };
         
        -    template 
        -    struct remove_reverse_edge_descriptor > {
        +    template 
        +    struct remove_reverse_edge_descriptor > {
               typedef Desc type;
        -      static Desc convert(const reverse_graph_edge_descriptor& d) {
        -        return d.underlying_desc;
        +      static Desc convert(const reverse_graph_edge_descriptor& d, const Graph& g) {
        +        return get(edge_underlying, g, d);
               }
             };
         
        @@ -155,7 +155,7 @@ namespace boost {
                                 CopyVertex copy_vertex, CopyEdge copy_edge,
                                 Orig2CopyVertexIndexMap orig2copy, IndexMap)
               {
        -        typedef remove_reverse_edge_descriptor::edge_descriptor> cvt;
        +        typedef remove_reverse_edge_descriptor::edge_descriptor> cvt;
                 typename graph_traits::vertex_iterator vi, vi_end;
                 for (boost::tie(vi, vi_end) = vertices(g_in); vi != vi_end; ++vi) {
                   typename graph_traits::vertex_descriptor
        @@ -170,7 +170,7 @@ namespace boost {
                   boost::tie(new_e, inserted) = add_edge(get(orig2copy, source(*ei, g_in)), 
                                                          get(orig2copy, target(*ei, g_in)),
                                                          g_out);
        -          copy_edge(cvt::convert(*ei), new_e);
        +          copy_edge(cvt::convert(*ei, g_in), new_e);
                 }
               }
             };
        @@ -185,7 +185,7 @@ namespace boost {
                                 CopyVertex copy_vertex, CopyEdge copy_edge,
                                 Orig2CopyVertexIndexMap orig2copy, IndexMap)
               {
        -        typedef remove_reverse_edge_descriptor::edge_descriptor> cvt;
        +        typedef remove_reverse_edge_descriptor::edge_descriptor> cvt;
                 typename graph_traits::vertex_iterator vi, vi_end;
                 for (boost::tie(vi, vi_end) = vertices(g_in); vi != vi_end; ++vi) {
                   typename graph_traits::vertex_descriptor
        @@ -201,7 +201,7 @@ namespace boost {
                     boost::tie(new_e, inserted) = add_edge(get(orig2copy, source(*ei, g_in)), 
                                                            get(orig2copy, target(*ei, g_in)),
                                                            g_out);
        -            copy_edge(cvt::convert(*ei), new_e);
        +            copy_edge(cvt::convert(*ei, g_in), new_e);
                   }
                 }
               }
        @@ -218,7 +218,7 @@ namespace boost {
                                 Orig2CopyVertexIndexMap orig2copy,
                                 IndexMap index_map)
               {
        -        typedef remove_reverse_edge_descriptor::edge_descriptor> cvt;
        +        typedef remove_reverse_edge_descriptor::edge_descriptor> cvt;
                 typedef color_traits Color;
                 std::vector 
                   color(num_vertices(g_in), Color::white());
        @@ -238,7 +238,7 @@ namespace boost {
                       boost::tie(new_e, inserted) = add_edge(get(orig2copy, source(*ei,g_in)),
                                                              get(orig2copy, target(*ei,g_in)),
                                                              g_out);
        -              copy_edge(cvt::convert(*ei), new_e);
        +              copy_edge(cvt::convert(*ei, g_in), new_e);
                     }
                   }
                   color[get(index_map, *vi)] = Color::black();
        diff --git a/include/boost/graph/properties.hpp b/include/boost/graph/properties.hpp
        index dd7a73576..bc498bbf9 100644
        --- a/include/boost/graph/properties.hpp
        +++ b/include/boost/graph/properties.hpp
        @@ -115,6 +115,7 @@ namespace boost {
           BOOST_DEF_PROPERTY(vertex, lowpoint);
           BOOST_DEF_PROPERTY(vertex, potential);
           BOOST_DEF_PROPERTY(vertex, update);
        +  BOOST_DEF_PROPERTY(vertex, underlying);
           BOOST_DEF_PROPERTY(edge, reverse);
           BOOST_DEF_PROPERTY(edge, capacity);
           BOOST_DEF_PROPERTY(edge, flow);
        @@ -123,6 +124,7 @@ namespace boost {
           BOOST_DEF_PROPERTY(edge, discover_time);
           BOOST_DEF_PROPERTY(edge, update);
           BOOST_DEF_PROPERTY(edge, finished);
        +  BOOST_DEF_PROPERTY(edge, underlying);
           BOOST_DEF_PROPERTY(graph, visitor);
         
           // These tags are used for property bundles
        diff --git a/include/boost/graph/reverse_graph.hpp b/include/boost/graph/reverse_graph.hpp
        index 393750a09..b1dbc4247 100644
        --- a/include/boost/graph/reverse_graph.hpp
        +++ b/include/boost/graph/reverse_graph.hpp
        @@ -27,30 +27,32 @@ struct reverse_graph_tag { };
             template 
             class reverse_graph_edge_descriptor {
               public:
        -      EdgeDesc underlying_desc;
        +      EdgeDesc underlying_descx; // Odd name is because this needs to be public but shouldn't be exposed to users anymore
        +
        +      private:
               typedef EdgeDesc base_descriptor_type;
         
               public:
        -      explicit reverse_graph_edge_descriptor(const EdgeDesc& underlying_desc = EdgeDesc())
        -        : underlying_desc(underlying_desc) {}
        +      explicit reverse_graph_edge_descriptor(const EdgeDesc& underlying_descx = EdgeDesc())
        +        : underlying_descx(underlying_descx) {}
         
               friend bool operator==(const reverse_graph_edge_descriptor& a, const reverse_graph_edge_descriptor& b) {
        -        return a.underlying_desc == b.underlying_desc;
        +        return a.underlying_descx == b.underlying_descx;
               }
               friend bool operator!=(const reverse_graph_edge_descriptor& a, const reverse_graph_edge_descriptor& b) {
        -        return a.underlying_desc != b.underlying_desc;
        +        return a.underlying_descx != b.underlying_descx;
               }
               friend bool operator<(const reverse_graph_edge_descriptor& a, const reverse_graph_edge_descriptor& b) {
        -        return a.underlying_desc < b.underlying_desc;
        +        return a.underlying_descx < b.underlying_descx;
               }
               friend bool operator>(const reverse_graph_edge_descriptor& a, const reverse_graph_edge_descriptor& b) {
        -        return a.underlying_desc > b.underlying_desc;
        +        return a.underlying_descx > b.underlying_descx;
               }
               friend bool operator<=(const reverse_graph_edge_descriptor& a, const reverse_graph_edge_descriptor& b) {
        -        return a.underlying_desc <= b.underlying_desc;
        +        return a.underlying_descx <= b.underlying_descx;
               }
               friend bool operator>=(const reverse_graph_edge_descriptor& a, const reverse_graph_edge_descriptor& b) {
        -        return a.underlying_desc >= b.underlying_desc;
        +        return a.underlying_descx >= b.underlying_descx;
               }
             };
         
        @@ -80,7 +82,7 @@ struct reverse_graph_tag { };
             template 
             struct get_underlying_descriptor_from_reverse_descriptor > {
               typedef Desc type;
        -      static Desc convert(const reverse_graph_edge_descriptor& d) {return d.underlying_desc;}
        +      static Desc convert(const reverse_graph_edge_descriptor& d) {return d.underlying_descx;}
             };
         
             template  struct choose_rev_edge_iter { };
        @@ -311,14 +313,14 @@ template 
         inline typename graph_traits::vertex_descriptor
         source(const detail::reverse_graph_edge_descriptor& e, const reverse_graph& g)
         {
        -    return target(e.underlying_desc, g.m_g);
        +    return target(e.underlying_descx, g.m_g);
         }
         
         template 
         inline typename graph_traits::vertex_descriptor
         target(const detail::reverse_graph_edge_descriptor& e, const reverse_graph& g)
         {
        -    return source(e.underlying_desc, g.m_g);
        +    return source(e.underlying_descx, g.m_g);
         }
         
         
        @@ -340,18 +342,18 @@ namespace detail {
             friend reference
             get(const reverse_graph_edge_property_map& m,
                 const key_type& e) {
        -      return get(m.underlying_pm, e.underlying_desc);
        +      return get(m.underlying_pm, e.underlying_descx);
             }
         
             friend void
             put(const reverse_graph_edge_property_map& m,
                 const key_type& e,
                 const value_type& v) {
        -      put(m.underlying_pm, e.underlying_desc, v);
        +      put(m.underlying_pm, e.underlying_descx, v);
             }
         
             reference operator[](const key_type& k) {
        -      return (this->underlying_pm)[k.underlying_desc];
        +      return (this->underlying_pm)[k.underlying_descx];
             }
           };
         
        @@ -419,6 +421,62 @@ put(Property p, reverse_graph& g, const Key& k,
           put(get(p, g), k, val);
         }
         
        +// Get the underlying descriptor from a reverse_graph's wrapped edge descriptor
        +
        +namespace detail {
        +  template 
        +  struct underlying_edge_desc_map_type {
        +    E operator[](const reverse_graph_edge_descriptor& k) const {
        +      return k.underlying_descx;
        +    }
        +  };
        +
        +  template 
        +  E
        +  get(underlying_edge_desc_map_type m,
        +      const reverse_graph_edge_descriptor& k)
        +  {
        +    return m[k];
        +  }
        +};
        +
        +template 
        +struct property_traits > {
        +  typedef detail::reverse_graph_edge_descriptor key_type;
        +  typedef E value_type;
        +  typedef const E& reference;
        +  typedef readable_property_map_tag category;
        +};
        +
        +template 
        +struct property_map, edge_underlying_t> {
        +  private:
        +  typedef typename graph_traits::edge_descriptor ed;
        +
        +  public:
        +  typedef detail::underlying_edge_desc_map_type type;
        +  typedef detail::underlying_edge_desc_map_type const_type;
        +};
        +
        +template 
        +detail::underlying_edge_desc_map_type::edge_descriptor>
        +get(edge_underlying_t,
        +    const reverse_graph& g)
        +{
        +  return detail::underlying_edge_desc_map_type::edge_descriptor>();
        +}
        +
        +template 
        +typename graph_traits::edge_descriptor
        +get(edge_underlying_t,
        +    const reverse_graph& g,
        +    const typename graph_traits >::edge_descriptor& k)
        +{
        +  return k.underlying_descx;
        +}
        +
        +// Access to wrapped graph's graph properties
        +
         template
         inline void
        diff --git a/test/reverse_graph_cc.cpp b/test/reverse_graph_cc.cpp
        index 00a362e93..3032be5f6 100644
        --- a/test/reverse_graph_cc.cpp
        +++ b/test/reverse_graph_cc.cpp
        @@ -28,6 +28,7 @@ int main(int,char*[])
             typedef graph_traits::edge_descriptor Edge;
             function_requires< ReadablePropertyGraphConcept >();
             function_requires< ReadablePropertyGraphConcept >();
        +    function_requires< ReadablePropertyGraphConcept >();
             AdjList g;
             Graph gr(g);
             get_property(gr, graph_name_t());
        @@ -45,6 +46,7 @@ int main(int,char*[])
             typedef graph_traits::edge_descriptor Edge;
             function_requires< PropertyGraphConcept >();
             function_requires< PropertyGraphConcept >();
        +    function_requires< ReadablePropertyGraphConcept >();
             AdjList g;
             Graph gr(g);
             get_property(gr, graph_name_t());
        
        From cd1fee5f7d4b8711cc81b32c88ca2ccc0a85b41d Mon Sep 17 00:00:00 2001
        From: Jeremiah Willcock 
        Date: Sun, 18 Dec 2011 21:09:34 +0000
        Subject: [PATCH 100/333] Applied fixed version of patch from #6293; fixes
         #6293
        
        [SVN r76050]
        ---
         doc/AStarHeuristic.html                       |   2 +-
         doc/AdjacencyGraph.html                       |   4 +-
         doc/BidirectionalGraph.html                   |   4 +-
         doc/EdgeListGraph.html                        |   4 +-
         doc/Graph.html                                |  12 +-
         doc/IncidenceGraph.html                       |   4 +-
         doc/KeyedUpdatableQueue.html                  |   4 +-
         doc/MutableGraph.html                         |   6 +-
         doc/MutablePropertyGraph.html                 |   2 +-
         doc/PropertyGraph.html                        |   6 +-
         doc/UpdatableQueue.html                       |   2 +-
         doc/VertexAndEdgeListGraph.html               |   4 +-
         doc/VertexListGraph.html                      |   6 +-
         doc/biconnected_components.w                  |  11 +-
         doc/constructing_algorithms.html              |  10 +-
         doc/isomorphism-impl-v2.w                     |  22 +-
         doc/isomorphism-impl-v3.w                     |  22 +-
         doc/isomorphism-impl.w                        |  14 +-
         doc/leda_conversion.html                      |   6 +-
         doc/transitive_closure.w                      |  19 +-
         example/implicit_graph.cpp                    |  20 +-
         example/leda-concept-check.cpp                |  11 +-
         example/loops_dfs.cpp                         |   5 +-
         example/put-get-helper-eg.cpp                 |   3 +-
         include/boost/graph/astar_search.hpp          |   6 +-
         .../graph/bellman_ford_shortest_paths.hpp     |  11 +-
         .../boost/graph/biconnected_components.hpp    |  17 +-
         .../graph/boykov_kolmogorov_max_flow.hpp      |  21 +-
         include/boost/graph/breadth_first_search.hpp  |   9 +-
         .../boost/graph/bron_kerbosch_all_cliques.hpp |  18 +-
         include/boost/graph/closeness_centrality.hpp  |  33 +-
         .../boost/graph/clustering_coefficient.hpp    |  21 +-
         include/boost/graph/connected_components.hpp  |   5 +-
         include/boost/graph/core_numbers.hpp          |   3 +-
         include/boost/graph/degree_centrality.hpp     |  11 +-
         include/boost/graph/depth_first_search.hpp    |  21 +-
         include/boost/graph/detail/geodesic.hpp       |   9 +-
         .../boost/graph/dijkstra_shortest_paths.hpp   |   3 +-
         include/boost/graph/dominator_tree.hpp        |   7 +-
         include/boost/graph/eccentricity.hpp          |  19 +-
         .../boost/graph/floyd_warshall_shortest.hpp   |   9 +-
         include/boost/graph/geodesic_distance.hpp     |  35 ++-
         include/boost/graph/graph_concepts.hpp        |   5 +-
         include/boost/graph/howard_cycle_ratio.hpp    |  11 +-
         include/boost/graph/isomorphism.hpp           |  23 +-
         .../graph/johnson_all_pairs_shortest.hpp      |   5 +-
         .../boost/graph/kruskal_min_spanning_tree.hpp |  19 +-
         include/boost/graph/neighbor_bfs.hpp          |  11 +-
         include/boost/graph/strong_components.hpp     |  11 +-
         include/boost/graph/tiernan_all_cycles.hpp    |  17 +-
         include/boost/graph/transitive_closure.hpp    |  21 +-
         include/boost/graph/undirected_dfs.hpp        |  29 +-
         test/adj_list_cc.cpp                          | 297 +++++++++---------
         test/adj_matrix_cc.cpp                        |  69 ++--
         test/edge_list_cc.cpp                         |   7 +-
         test/filtered_graph_cc.cpp                    |  15 +-
         test/graph_concepts.cpp                       |  11 +-
         test/grid_graph_cc.cpp                        |  17 +-
         test/leda_graph_cc.cpp                        |  32 +-
         test/read_propmap.cpp                         |   5 +-
         test/reverse_graph_cc.cpp                     |  17 +-
         test/stanford_graph_cc.cpp                    |  35 ++-
         test/test_construction.hpp                    |   1 +
         test/test_destruction.hpp                     |   3 +-
         test/test_direction.hpp                       |   1 +
         test/test_graph.hpp                           |   1 +
         test/test_iteration.hpp                       |   1 +
         test/test_properties.hpp                      |   2 +
         test/vector_graph_cc.cpp                      |   7 +-
         69 files changed, 592 insertions(+), 542 deletions(-)
        
        diff --git a/doc/AStarHeuristic.html b/doc/AStarHeuristic.html
        index 5d0c1aeb3..62257be8b 100644
        --- a/doc/AStarHeuristic.html
        +++ b/doc/AStarHeuristic.html
        @@ -116,7 +116,7 @@ 

        Concept Checking Class

        struct AStarHeuristicConcept { void constraints() { - function_requires< CopyConstructibleConcept<Heuristic> >(); + BOOST_CONCEPT_ASSERT(( CopyConstructibleConcept<Heuristic> )); h(u); } Heuristic h; diff --git a/doc/AdjacencyGraph.html b/doc/AdjacencyGraph.html index 0764b29bf..b72031b13 100644 --- a/doc/AdjacencyGraph.html +++ b/doc/AdjacencyGraph.html @@ -112,8 +112,8 @@

        Concept Checking Class

        typedef typename boost::graph_traits<G>::adjacency_iterator adjacency_iterator; void constraints() { - function_requires< IncidenceGraphConcept<G> >(); - function_requires< MultiPassInputIteratorConcept<adjacency_iterator> >(); + BOOST_CONCEPT_ASSERT(( IncidenceGraphConcept<G> )); + BOOST_CONCEPT_ASSERT(( MultiPassInputIteratorConcept<adjacency_iterator> )); p = adjacent_vertices(v, g); v = *p.first; diff --git a/doc/BidirectionalGraph.html b/doc/BidirectionalGraph.html index f67a92a48..e5a922158 100644 --- a/doc/BidirectionalGraph.html +++ b/doc/BidirectionalGraph.html @@ -145,8 +145,8 @@

        Concept Checking Class

        typedef typename boost::graph_traits<G>::in_edge_iterator in_edge_iterator; void constraints() { - function_requires< IncidenceGraphConcept<G> >(); - function_requires< MultiPassInputIteratorConcept<in_edge_iterator> >(); + BOOST_CONCEPT_ASSERT(( IncidenceGraphConcept<G> )); + BOOST_CONCEPT_ASSERT(( MultiPassInputIteratorConcept<in_edge_iterator> )); p = in_edges(v, g); e = *p.first; diff --git a/doc/EdgeListGraph.html b/doc/EdgeListGraph.html index cb87cdb06..fc62539c0 100644 --- a/doc/EdgeListGraph.html +++ b/doc/EdgeListGraph.html @@ -146,8 +146,8 @@

        Concept Checking Class

        typedef typename boost::graph_traits<G>::edge_iterator edge_iterator; void constraints() { - function_requires< GraphConcept<G> >(); - function_requires< MultiPassInputIteratorConcept<edge_iterator> >(); + BOOST_CONCEPT_ASSERT(( GraphConcept<G> )); + BOOST_CONCEPT_ASSERT(( MultiPassInputIteratorConcept<edge_iterator> )); p = edges(g); E = num_edges(g); diff --git a/doc/Graph.html b/doc/Graph.html index 08423b10c..fabae1a49 100644 --- a/doc/Graph.html +++ b/doc/Graph.html @@ -121,12 +121,12 @@

        Concept Checking Class

        typedef typename boost::graph_traits<G>::traversal_category traversal_category; void constraints() { - function_requires< DefaultConstructibleConcept<vertex_descriptor> >(); - function_requires< EqualityComparableConcept<vertex_descriptor> >(); - function_requires< AssignableConcept<vertex_descriptor> >(); - function_requires< DefaultConstructibleConcept<edge_descriptor> >(); - function_requires< EqualityComparableConcept<edge_descriptor> >(); - function_requires< AssignableConcept<edge_descriptor> >(); + BOOST_CONCEPT_ASSERT(( DefaultConstructibleConcept<vertex_descriptor> )); + BOOST_CONCEPT_ASSERT(( EqualityComparableConcept<vertex_descriptor> )); + BOOST_CONCEPT_ASSERT(( AssignableConcept<vertex_descriptor> )); + BOOST_CONCEPT_ASSERT(( DefaultConstructibleConcept<edge_descriptor> )); + BOOST_CONCEPT_ASSERT(( EqualityComparableConcept<edge_descriptor> )); + BOOST_CONCEPT_ASSERT(( AssignableConcept<edge_descriptor> )); } G g; }; diff --git a/doc/IncidenceGraph.html b/doc/IncidenceGraph.html index 29db19460..228cbfc81 100644 --- a/doc/IncidenceGraph.html +++ b/doc/IncidenceGraph.html @@ -162,8 +162,8 @@

        Concept Checking Class

        { typedef typename boost::graph_traits<G>::out_edge_iterator out_edge_iterator; void constraints() { - function_requires< GraphConcept<G> >(); - function_requires< MultiPassInputIteratorConcept<out_edge_iterator> >(); + BOOST_CONCEPT_ASSERT(( GraphConcept<G> )); + BOOST_CONCEPT_ASSERT(( MultiPassInputIteratorConcept<out_edge_iterator> )); p = out_edges(u, g); e = *p.first; diff --git a/doc/KeyedUpdatableQueue.html b/doc/KeyedUpdatableQueue.html index 6d5ecaf0b..81141a728 100644 --- a/doc/KeyedUpdatableQueue.html +++ b/doc/KeyedUpdatableQueue.html @@ -63,8 +63,8 @@

        Concept Checking Class

        typedef typename Q::key_map key_map; void constraints() { - function_requires< UpdatableQueue<Q> >(); - function_requires< ReadWritePropertyMap< key_map, typename Buffer<Q>::value_type > >(); + BOOST_CONCEPT_ASSERT(( UpdatableQueue<Q> )); + BOOST_CONCEPT_ASSERT(( ReadWritePropertyMap< key_map, typename Buffer<Q>::value_type > )); } void const_constraints(const Q& cq) { diff --git a/doc/MutableGraph.html b/doc/MutableGraph.html index edc4e64a0..323ba2e0e 100644 --- a/doc/MutableGraph.html +++ b/doc/MutableGraph.html @@ -250,7 +250,7 @@

        Concept Checking Class

        struct MutableIncidenceGraphConcept { void constraints() { - function_requires< MutableGraph<G> >(); + BOOST_CONCEPT_ASSERT(( MutableGraph<G> )); remove_edge(iter, g); remove_out_edge_if(u, p, g); } @@ -265,7 +265,7 @@

        Concept Checking Class

        struct MutableBidirectionalGraphConcept { void constraints() { - function_requires< MutableIncidenceGraph<G> >(); + BOOST_CONCEPT_ASSERT(( MutableIncidenceGraph<G> )); remove_in_edge_if(u, p, g); } G g; @@ -278,7 +278,7 @@

        Concept Checking Class

        struct MutableEdgeListGraphConcept { void constraints() { - function_requires< MutableGraph<G> >(); + BOOST_CONCEPT_ASSERT(( MutableGraph<G> )); remove_edge_if(p, g); } G g; diff --git a/doc/MutablePropertyGraph.html b/doc/MutablePropertyGraph.html index 8275bbbcd..0a10fff60 100644 --- a/doc/MutablePropertyGraph.html +++ b/doc/MutablePropertyGraph.html @@ -125,7 +125,7 @@

        Concept Checking Class

        { typedef typename boost::graph_traits<G>::edge_descriptor edge_descriptor; void constraints() { - function_requires< MutableGraphConcept<G> >(); + BOOST_CONCEPT_ASSERT(( MutableGraphConcept<G> )); v = add_vertex(vp, g); p = add_edge(u, v, ep, g); } diff --git a/doc/PropertyGraph.html b/doc/PropertyGraph.html index 9d30dc2ed..48c4ad80e 100644 --- a/doc/PropertyGraph.html +++ b/doc/PropertyGraph.html @@ -173,9 +173,9 @@

        Concept Checking Class

        typedef typename property_map<G, PropertyTag>::type Map; typedef typename property_map<G, PropertyTag>::const_type const_Map; void constraints() { - function_requires< GraphConcept<G> >(); - function_requires< ReadWritePropertyMapConcept<Map, X> >(); - function_requires< ReadablePropertyMapConcept<const_Map, X> >(); + BOOST_CONCEPT_ASSERT(( GraphConcept<G> )); + BOOST_CONCEPT_ASSERT(( ReadWritePropertyMapConcept<Map, X> )); + BOOST_CONCEPT_ASSERT(( ReadablePropertyMapConcept<const_Map, X> )); Map pmap = get(PropertyTag(), g); pval = get(PropertyTag(), g, x); diff --git a/doc/UpdatableQueue.html b/doc/UpdatableQueue.html index a91c69cf1..eb65bf756 100644 --- a/doc/UpdatableQueue.html +++ b/doc/UpdatableQueue.html @@ -58,7 +58,7 @@

        Concept Checking Class

        struct UpdatableQueueConcept { void constraints() { - function_requires< Buffer<Q> >(); + BOOST_CONCEPT_ASSERT(( Buffer<Q> )); q.update(g_ct); } diff --git a/doc/VertexAndEdgeListGraph.html b/doc/VertexAndEdgeListGraph.html index 5aabebdad..9685c8f01 100644 --- a/doc/VertexAndEdgeListGraph.html +++ b/doc/VertexAndEdgeListGraph.html @@ -51,8 +51,8 @@

        Concept Checking Class

        struct VertexAndEdgeListGraphConcept { void constraints() { - function_requires< VertexListGraphConcept<G> >(); - function_requires< EdgeListGraphConcept<G> >(); + BOOST_CONCEPT_ASSERT(( VertexListGraphConcept<G> )); + BOOST_CONCEPT_ASSERT(( EdgeListGraphConcept<G> )); } };
        diff --git a/doc/VertexListGraph.html b/doc/VertexListGraph.html index ee546feaf..b108353aa 100644 --- a/doc/VertexListGraph.html +++ b/doc/VertexListGraph.html @@ -121,9 +121,9 @@

        Concept Checking Class

        typedef typename boost::graph_traits<G>::vertex_iterator vertex_iterator; void constraints() { - function_requires< IncidenceGraphConcept<G> >(); - function_requires< AdjacencyGraphConcept<G> >(); - function_requires< MultiPassInputIteratorConcept<vertex_iterator> >(); + BOOST_CONCEPT_ASSERT(( IncidenceGraphConcept<G> )); + BOOST_CONCEPT_ASSERT(( AdjacencyGraphConcept<G> )); + BOOST_CONCEPT_ASSERT(( MultiPassInputIteratorConcept<vertex_iterator> )); p = vertices(g); V = num_vertices(g); diff --git a/doc/biconnected_components.w b/doc/biconnected_components.w index 97ba5dc85..d2eb21ffd 100644 --- a/doc/biconnected_components.w +++ b/doc/biconnected_components.w @@ -156,11 +156,11 @@ template. @d Concept checking of type parameters @{ -function_requires< VertexListGraphConcept >(); -function_requires< IncidenceGraphConcept >(); -function_requires< WritablePropertyMapConcept >(); -function_requires< ReadWritePropertyMapConcept >(); -function_requires< ReadWritePropertyMapConcept >(); +BOOST_CONCEPT_ASSERT(( VertexListGraphConcept )); +BOOST_CONCEPT_ASSERT(( IncidenceGraphConcept )); +BOOST_CONCEPT_ASSERT(( WritablePropertyMapConcept )); +BOOST_CONCEPT_ASSERT(( ReadWritePropertyMapConcept )); +BOOST_CONCEPT_ASSERT(( ReadWritePropertyMapConcept )); @} The first step of the algorithm is to initialize the discover times of @@ -286,6 +286,7 @@ S.pop(); #include #include #include +#include namespace boost { @ diff --git a/doc/constructing_algorithms.html b/doc/constructing_algorithms.html index cbea2963d..cc4047b05 100644 --- a/doc/constructing_algorithms.html +++ b/doc/constructing_algorithms.html @@ -79,7 +79,7 @@

        Constructing graph algorithms with BGL

        href="./VertexListGraph.html">VertexListGraph. This is enforced by the use of those graph operations in the algorithm, and furthermore by our explicit requirement added as a concept check with -function_requires() (see Section BOOST_CONCEPT_ASSERT() (see Section Concept Checking for more details about concept checking). @@ -122,10 +122,10 @@

        Constructing graph algorithms with BGL

        typedef typename property_traits<Color>::value_type ColorType; typedef typename property_traits<Order>::value_type OrderType; - function_requires< VertexListGraphConcept<VertexListGraph> >(); - function_requires< ReadWritePropertyMapConcept<Color, vertex_descriptor> >(); - function_requires< IntegerConcept<ColorType> >(); - function_requires< ReadablePropertyMapConcept<Order, size_type> >(); + BOOST_CONCEPT_ASSERT(( VertexListGraphConcept<VertexListGraph> )); + BOOST_CONCEPT_ASSERT(( ReadWritePropertyMapConcept<Color, vertex_descriptor> )); + BOOST_CONCEPT_ASSERT(( IntegerConcept<ColorType> )); + BOOST_CONCEPT_ASSERT(( ReadablePropertyMapConcept<Order, size_type> )); BOOST_STATIC_ASSERT((is_same<OrderType, vertex_descriptor>::value)); size_type max_color = 0; diff --git a/doc/isomorphism-impl-v2.w b/doc/isomorphism-impl-v2.w index 75f88b2bd..602db7ee2 100644 --- a/doc/isomorphism-impl-v2.w +++ b/doc/isomorphism-impl-v2.w @@ -388,31 +388,31 @@ unsigned integers. @d Concept checking @{ // Graph requirements -function_requires< VertexListGraphConcept >(); -function_requires< EdgeListGraphConcept >(); -function_requires< VertexListGraphConcept >(); -function_requires< BidirectionalGraphConcept >(); +BOOST_CONCEPT_ASSERT(( VertexListGraphConcept )); +BOOST_CONCEPT_ASSERT(( EdgeListGraphConcept )); +BOOST_CONCEPT_ASSERT(( VertexListGraphConcept )); +BOOST_CONCEPT_ASSERT(( BidirectionalGraphConcept )); typedef typename graph_traits::vertex_descriptor vertex1_t; typedef typename graph_traits::vertex_descriptor vertex2_t; typedef typename graph_traits::vertices_size_type size_type; // Vertex invariant requirement -function_requires< AdaptableUnaryFunctionConcept >(); -function_requires< AdaptableUnaryFunctionConcept >(); +BOOST_CONCEPT_ASSERT(( AdaptableUnaryFunctionConcept )); +BOOST_CONCEPT_ASSERT(( AdaptableUnaryFunctionConcept )); // Property map requirements -function_requires< ReadWritePropertyMapConcept >(); +BOOST_CONCEPT_ASSERT(( ReadWritePropertyMapConcept )); typedef typename property_traits::value_type IsoMappingValue; BOOST_STATIC_ASSERT((is_same::value)); -function_requires< ReadablePropertyMapConcept >(); +BOOST_CONCEPT_ASSERT(( ReadablePropertyMapConcept )); typedef typename property_traits::value_type IndexMap1Value; BOOST_STATIC_ASSERT((is_convertible::value)); -function_requires< ReadablePropertyMapConcept >(); +BOOST_CONCEPT_ASSERT(( ReadablePropertyMapConcept )); typedef typename property_traits::value_type IndexMap2Value; BOOST_STATIC_ASSERT((is_convertible::value)); @} diff --git a/doc/isomorphism-impl-v3.w b/doc/isomorphism-impl-v3.w index 4ce875176..6e35e8e7e 100644 --- a/doc/isomorphism-impl-v3.w +++ b/doc/isomorphism-impl-v3.w @@ -507,31 +507,31 @@ unsigned integers. @d Concept checking @{ // Graph requirements -function_requires< VertexListGraphConcept >(); -function_requires< EdgeListGraphConcept >(); -function_requires< VertexListGraphConcept >(); -function_requires< BidirectionalGraphConcept >(); +BOOST_CONCEPT_ASSERT(( VertexListGraphConcept )); +BOOST_CONCEPT_ASSERT(( EdgeListGraphConcept )); +BOOST_CONCEPT_ASSERT(( VertexListGraphConcept )); +BOOST_CONCEPT_ASSERT(( BidirectionalGraphConcept )); typedef typename graph_traits::vertex_descriptor vertex1_t; typedef typename graph_traits::vertex_descriptor vertex2_t; typedef typename graph_traits::vertices_size_type size_type; // Vertex invariant requirement -function_requires< AdaptableUnaryFunctionConcept >(); -function_requires< AdaptableUnaryFunctionConcept >(); +BOOST_CONCEPT_ASSERT(( AdaptableUnaryFunctionConcept )); +BOOST_CONCEPT_ASSERT(( AdaptableUnaryFunctionConcept )); // Property map requirements -function_requires< ReadWritePropertyMapConcept >(); +BOOST_CONCEPT_ASSERT(( ReadWritePropertyMapConcept )); typedef typename property_traits::value_type IsoMappingValue; BOOST_STATIC_ASSERT((is_same::value)); -function_requires< ReadablePropertyMapConcept >(); +BOOST_CONCEPT_ASSERT(( ReadablePropertyMapConcept )); typedef typename property_traits::value_type IndexMap1Value; BOOST_STATIC_ASSERT((is_convertible::value)); -function_requires< ReadablePropertyMapConcept >(); +BOOST_CONCEPT_ASSERT(( ReadablePropertyMapConcept )); typedef typename property_traits::value_type IndexMap2Value; BOOST_STATIC_ASSERT((is_convertible::value)); @} diff --git a/doc/isomorphism-impl.w b/doc/isomorphism-impl.w index e50337d1c..e881a9461 100644 --- a/doc/isomorphism-impl.w +++ b/doc/isomorphism-impl.w @@ -301,21 +301,21 @@ unsigned integers. @d Concept checking @{ // Graph requirements -function_requires< VertexListGraphConcept >(); -function_requires< EdgeListGraphConcept >(); -function_requires< VertexListGraphConcept >(); -function_requires< BidirectionalGraphConcept >(); +BOOST_CONCEPT_ASSERT(( VertexListGraphConcept )); +BOOST_CONCEPT_ASSERT(( EdgeListGraphConcept )); +BOOST_CONCEPT_ASSERT(( VertexListGraphConcept )); +BOOST_CONCEPT_ASSERT(( BidirectionalGraphConcept )); // Property map requirements -function_requires< ReadWritePropertyMapConcept >(); +BOOST_CONCEPT_ASSERT(( ReadWritePropertyMapConcept )); typedef typename property_traits::value_type IndexMappingValue; BOOST_STATIC_ASSERT((is_same::value)); -function_requires< ReadablePropertyMapConcept >(); +BOOST_CONCEPT_ASSERT(( ReadablePropertyMapConcept )); typedef typename property_traits::value_type IndexMap1Value; BOOST_STATIC_ASSERT((is_convertible::value)); -function_requires< ReadablePropertyMapConcept >(); +BOOST_CONCEPT_ASSERT(( ReadablePropertyMapConcept )); typedef typename property_traits::value_type IndexMap2Value; BOOST_STATIC_ASSERT((is_convertible::value)); @} diff --git a/doc/leda_conversion.html b/doc/leda_conversion.html index a8ba39f3d..6c24c6abf 100644 --- a/doc/leda_conversion.html +++ b/doc/leda_conversion.html @@ -236,9 +236,9 @@

        How to Convert Existing Graphs to BGL

        main(int,char*[]) { typedef GRAPH<int,int> Graph; - function_requires< VertexListGraphConcept<Graph> >(); - function_requires< BidirectionalGraphConcept<Graph> >(); - function_requires< MutableGraphConcept<Graph> >(); + BOOST_CONCEPT_ASSERT(( VertexListGraphConcept<Graph> )); + BOOST_CONCEPT_ASSERT(( BidirectionalGraphConcept<Graph> )); + BOOST_CONCEPT_ASSERT(( MutableGraphConcept<Graph> )); return 0; }
        diff --git a/doc/transitive_closure.w b/doc/transitive_closure.w index c8db56dc9..136eab681 100644 --- a/doc/transitive_closure.w +++ b/doc/transitive_closure.w @@ -160,11 +160,11 @@ algorithm. @d Concept checking @{ -function_requires< VertexListGraphConcept >(); -function_requires< AdjacencyGraphConcept >(); -function_requires< VertexMutableGraphConcept >(); -function_requires< EdgeMutableGraphConcept >(); -function_requires< ReadablePropertyMapConcept >(); +BOOST_CONCEPT_ASSERT(( VertexListGraphConcept )); +BOOST_CONCEPT_ASSERT(( AdjacencyGraphConcept )); +BOOST_CONCEPT_ASSERT(( VertexMutableGraphConcept )); +BOOST_CONCEPT_ASSERT(( EdgeMutableGraphConcept )); +BOOST_CONCEPT_ASSERT(( ReadablePropertyMapConcept )); @} \noindent To simplify the code in the rest of the function we make the @@ -566,8 +566,8 @@ void warshall_transitive_closure(G& g) typedef typename graph_traits::vertex_descriptor vertex; typedef typename graph_traits::vertex_iterator vertex_iterator; - function_requires< AdjacencyMatrixConcept >(); - function_requires< EdgeMutableGraphConcept >(); + BOOST_CONCEPT_ASSERT(( AdjacencyMatrixConcept )); + BOOST_CONCEPT_ASSERT(( EdgeMutableGraphConcept )); // Matrix form: // for k @@ -597,8 +597,8 @@ void warren_transitive_closure(G& g) typedef typename graph_traits::vertex_descriptor vertex; typedef typename graph_traits::vertex_iterator vertex_iterator; - function_requires< AdjacencyMatrixConcept >(); - function_requires< EdgeMutableGraphConcept >(); + BOOST_CONCEPT_ASSERT(( AdjacencyMatrixConcept )); + BOOST_CONCEPT_ASSERT(( EdgeMutableGraphConcept )); // Make sure second loop will work if (num_vertices(g) == 0) @@ -671,6 +671,7 @@ indent -nut -npcs -i2 -br -cdw -ce transitive_closure.hpp #include #include #include +#include namespace boost { diff --git a/example/implicit_graph.cpp b/example/implicit_graph.cpp index 7b0c0fc2c..b93bc8b7d 100644 --- a/example/implicit_graph.cpp +++ b/example/implicit_graph.cpp @@ -4,7 +4,7 @@ // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) - +#include #include #include #include @@ -444,15 +444,15 @@ int main (int argc, char const *argv[]) { // Check the concepts that graph models. This is included to demonstrate // how concept checking works, but is not required for a working program // since Boost algorithms do their own concept checking. - function_requires< BidirectionalGraphConcept >(); - function_requires< AdjacencyGraphConcept >(); - function_requires< VertexListGraphConcept >(); - function_requires< EdgeListGraphConcept >(); - function_requires< AdjacencyMatrixConcept >(); - function_requires< - ReadablePropertyMapConcept >(); - function_requires< - ReadablePropertyGraphConcept >(); + BOOST_CONCEPT_ASSERT(( BidirectionalGraphConcept )); + BOOST_CONCEPT_ASSERT(( AdjacencyGraphConcept )); + BOOST_CONCEPT_ASSERT(( VertexListGraphConcept )); + BOOST_CONCEPT_ASSERT(( EdgeListGraphConcept )); + BOOST_CONCEPT_ASSERT(( AdjacencyMatrixConcept )); + BOOST_CONCEPT_ASSERT(( + ReadablePropertyMapConcept )); + BOOST_CONCEPT_ASSERT(( + ReadablePropertyGraphConcept )); // Specify the size of the graph on the command line, or use a default size // of 5. diff --git a/example/leda-concept-check.cpp b/example/leda-concept-check.cpp index 21fc16060..f5720e7db 100644 --- a/example/leda-concept-check.cpp +++ b/example/leda-concept-check.cpp @@ -7,15 +7,16 @@ //======================================================================= #include #include +#include int main() { using namespace boost; - typedef leda::GRAPH < int, int >Graph; - function_requires < VertexListGraphConcept < Graph > >(); - function_requires < BidirectionalGraphConcept < Graph > >(); - function_requires < VertexMutableGraphConcept < Graph > >(); - function_requires < EdgeMutableGraphConcept < Graph > >(); + typedef leda::GRAPH Graph; + BOOST_CONCEPT_ASSERT(( VertexListGraphConcept )); + BOOST_CONCEPT_ASSERT(( BidirectionalGraphConcept< Graph> )); + BOOST_CONCEPT_ASSERT(( VertexMutableGraphConcept< Graph> )); + BOOST_CONCEPT_ASSERT(( EdgeMutableGraphConcept )); return EXIT_SUCCESS; } diff --git a/example/loops_dfs.cpp b/example/loops_dfs.cpp index c6babb1eb..9536701b9 100644 --- a/example/loops_dfs.cpp +++ b/example/loops_dfs.cpp @@ -6,6 +6,7 @@ // http://www.boost.org/LICENSE_1_0.txt) //======================================================================= #include +#include #include #include #include @@ -47,7 +48,7 @@ find_loops(typename graph_traits < Graph >::vertex_descriptor entry, const Graph & g, Loops & loops) // A container of sets of vertices { - function_requires < BidirectionalGraphConcept < Graph > >(); + BOOST_CONCEPT_ASSERT(( BidirectionalGraphConcept )); typedef typename graph_traits < Graph >::edge_descriptor Edge; typedef typename graph_traits < Graph >::vertex_descriptor Vertex; std::vector < Edge > back_edges; @@ -69,7 +70,7 @@ compute_loop_extent(typename graph_traits < Graph >::edge_descriptor back_edge, const Graph & g, Set & loop_set) { - function_requires < BidirectionalGraphConcept < Graph > >(); + BOOST_CONCEPT_ASSERT(( BidirectionalGraphConcept )); typedef typename graph_traits < Graph >::vertex_descriptor Vertex; typedef color_traits < default_color_type > Color; diff --git a/example/put-get-helper-eg.cpp b/example/put-get-helper-eg.cpp index 1134c0293..9c14e1b99 100644 --- a/example/put-get-helper-eg.cpp +++ b/example/put-get-helper-eg.cpp @@ -8,6 +8,7 @@ #include #include #include +#include #ifdef BOOST_NO_STD_ITERATOR_TRAITS #error This examples requires a compiler that provides a working std::iterator_traits @@ -53,6 +54,6 @@ main() typedef foo::iterator_property_map < vec_t::iterator, boost::identity_property_map > pmap_t; using namespace boost; - function_requires < Mutable_LvaluePropertyMapConcept < pmap_t, int > >(); + BOOST_CONCEPT_ASSERT(( Mutable_LvaluePropertyMapConcept )); return 0; } diff --git a/include/boost/graph/astar_search.hpp b/include/boost/graph/astar_search.hpp index 042ffec4a..316e70639 100644 --- a/include/boost/graph/astar_search.hpp +++ b/include/boost/graph/astar_search.hpp @@ -25,7 +25,7 @@ #include #include #include - +#include namespace boost { @@ -34,7 +34,7 @@ namespace boost { struct AStarHeuristicConcept { void constraints() { - function_requires< CopyConstructibleConcept >(); + BOOST_CONCEPT_ASSERT(( CopyConstructibleConcept )); h(u); } Heuristic h; @@ -58,7 +58,7 @@ namespace boost { struct AStarVisitorConcept { void constraints() { - function_requires< CopyConstructibleConcept >(); + BOOST_CONCEPT_ASSERT(( CopyConstructibleConcept )); vis.initialize_vertex(u, g); vis.discover_vertex(u, g); vis.examine_vertex(u, g); diff --git a/include/boost/graph/bellman_ford_shortest_paths.hpp b/include/boost/graph/bellman_ford_shortest_paths.hpp index 8fc02529a..c80ebe7c7 100644 --- a/include/boost/graph/bellman_ford_shortest_paths.hpp +++ b/include/boost/graph/bellman_ford_shortest_paths.hpp @@ -29,13 +29,14 @@ #include #include #include +#include namespace boost { template struct BellmanFordVisitorConcept { void constraints() { - function_requires< CopyConstructibleConcept >(); + BOOST_CONCEPT_ASSERT(( CopyConstructibleConcept )); vis.examine_edge(e, g); vis.edge_relaxed(e, g); vis.edge_not_relaxed(e, g); @@ -95,12 +96,12 @@ namespace boost { BinaryPredicate compare, BellmanFordVisitor v) { - function_requires >(); + BOOST_CONCEPT_ASSERT(( EdgeListGraphConcept )); typedef graph_traits GTraits; typedef typename GTraits::edge_descriptor Edge; typedef typename GTraits::vertex_descriptor Vertex; - function_requires >(); - function_requires >(); + BOOST_CONCEPT_ASSERT(( ReadWritePropertyMapConcept )); + BOOST_CONCEPT_ASSERT(( ReadablePropertyMapConcept )); typedef typename property_traits::value_type D_value; typedef typename property_traits::value_type W_value; @@ -229,7 +230,7 @@ namespace boost { (VertexAndEdgeListGraph& g, const bgl_named_params& params) { - function_requires >(); + BOOST_CONCEPT_ASSERT(( VertexListGraphConcept )); return detail::bellman_dispatch (g, num_vertices(g), choose_const_pmap(get_param(params, edge_weight), g, edge_weight), diff --git a/include/boost/graph/biconnected_components.hpp b/include/boost/graph/biconnected_components.hpp index a120c18a6..9586f9a21 100644 --- a/include/boost/graph/biconnected_components.hpp +++ b/include/boost/graph/biconnected_components.hpp @@ -20,6 +20,7 @@ #include #include #include +#include namespace boost { @@ -157,14 +158,14 @@ namespace boost { typedef typename graph_traits::vertex_descriptor vertex_t; typedef typename graph_traits::edge_descriptor edge_t; - function_requires >(); - function_requires >(); - function_requires >(); - function_requires >(); - function_requires >(); - function_requires >(); + BOOST_CONCEPT_ASSERT(( VertexListGraphConcept )); + BOOST_CONCEPT_ASSERT(( IncidenceGraphConcept )); + BOOST_CONCEPT_ASSERT(( WritablePropertyMapConcept )); + BOOST_CONCEPT_ASSERT(( ReadWritePropertyMapConcept )); + BOOST_CONCEPT_ASSERT(( ReadWritePropertyMapConcept )); + BOOST_CONCEPT_ASSERT(( ReadWritePropertyMapConcept )); std::size_t num_components = 0; std::size_t dfs_time = 0; diff --git a/include/boost/graph/boykov_kolmogorov_max_flow.hpp b/include/boost/graph/boykov_kolmogorov_max_flow.hpp index 89bcfff2a..0834c6316 100644 --- a/include/boost/graph/boykov_kolmogorov_max_flow.hpp +++ b/include/boost/graph/boykov_kolmogorov_max_flow.hpp @@ -47,6 +47,7 @@ #include #include #include +#include // The algorithm impelemented here is described in: // @@ -743,16 +744,16 @@ boykov_kolmogorov_max_flow(Graph& g, typedef typename graph_traits::edge_descriptor edge_descriptor; //as this method is the last one before we instantiate the solver, we do the concept checks here - function_requires >(); //to have vertices(), num_vertices(), - function_requires >(); //to have edges() - function_requires >(); //to have source(), target() and out_edges() - function_requires >(); //read flow-values from edges - function_requires >(); //write flow-values to residuals - function_requires >(); //read out reverse edges - function_requires >(); //store predecessor there - function_requires >(); //write corresponding tree - function_requires >(); //write distance to source/sink - function_requires >(); //get index 0...|V|-1 + BOOST_CONCEPT_ASSERT(( VertexListGraphConcept )); //to have vertices(), num_vertices(), + BOOST_CONCEPT_ASSERT(( EdgeListGraphConcept )); //to have edges() + BOOST_CONCEPT_ASSERT(( IncidenceGraphConcept )); //to have source(), target() and out_edges() + BOOST_CONCEPT_ASSERT(( ReadablePropertyMapConcept )); //read flow-values from edges + BOOST_CONCEPT_ASSERT(( ReadWritePropertyMapConcept )); //write flow-values to residuals + BOOST_CONCEPT_ASSERT(( ReadablePropertyMapConcept )); //read out reverse edges + BOOST_CONCEPT_ASSERT(( ReadWritePropertyMapConcept )); //store predecessor there + BOOST_CONCEPT_ASSERT(( ReadWritePropertyMapConcept )); //write corresponding tree + BOOST_CONCEPT_ASSERT(( ReadWritePropertyMapConcept )); //write distance to source/sink + BOOST_CONCEPT_ASSERT(( ReadablePropertyMapConcept )); //get index 0...|V|-1 BOOST_ASSERT(num_vertices(g) >= 2 && src != sink); detail::bk_max_flow< diff --git a/include/boost/graph/breadth_first_search.hpp b/include/boost/graph/breadth_first_search.hpp index 79fde8cd6..f65e47572 100644 --- a/include/boost/graph/breadth_first_search.hpp +++ b/include/boost/graph/breadth_first_search.hpp @@ -24,6 +24,7 @@ #include #include #include +#include #ifdef BOOST_GRAPH_USE_MPI #include @@ -34,7 +35,7 @@ namespace boost { template struct BFSVisitorConcept { void constraints() { - function_requires< CopyConstructibleConcept >(); + BOOST_CONCEPT_ASSERT(( CopyConstructibleConcept )); vis.initialize_vertex(u, g); vis.discover_vertex(u, g); vis.examine_vertex(u, g); @@ -59,12 +60,12 @@ namespace boost { typename graph_traits::vertex_descriptor s, Buffer& Q, BFSVisitor vis, ColorMap color) { - function_requires< IncidenceGraphConcept >(); + BOOST_CONCEPT_ASSERT(( IncidenceGraphConcept )); typedef graph_traits GTraits; typedef typename GTraits::vertex_descriptor Vertex; typedef typename GTraits::edge_descriptor Edge; - function_requires< BFSVisitorConcept >(); - function_requires< ReadWritePropertyMapConcept >(); + BOOST_CONCEPT_ASSERT(( BFSVisitorConcept )); + BOOST_CONCEPT_ASSERT(( ReadWritePropertyMapConcept )); typedef typename property_traits::value_type ColorValue; typedef color_traits Color; typename GTraits::out_edge_iterator ei, ei_end; diff --git a/include/boost/graph/bron_kerbosch_all_cliques.hpp b/include/boost/graph/bron_kerbosch_all_cliques.hpp index 35479316a..1466dfe5f 100644 --- a/include/boost/graph/bron_kerbosch_all_cliques.hpp +++ b/include/boost/graph/bron_kerbosch_all_cliques.hpp @@ -11,6 +11,8 @@ #include #include +#include + #include #include @@ -151,7 +153,7 @@ namespace detail const Container& in, Container& out) { - function_requires< GraphConcept >(); + BOOST_CONCEPT_ASSERT(( GraphConcept )); typename graph_traits::directed_category cat; typename Container::const_iterator i, end = in.end(); @@ -174,8 +176,8 @@ namespace detail Visitor vis, std::size_t min) { - function_requires< GraphConcept >(); - function_requires< CliqueVisitorConcept >(); + BOOST_CONCEPT_ASSERT(( GraphConcept )); + BOOST_CONCEPT_ASSERT(( CliqueVisitorConcept )); typedef typename graph_traits::vertex_descriptor Vertex; // Is there vertex in nots that is connected to all vertices @@ -266,15 +268,15 @@ template inline void bron_kerbosch_all_cliques(const Graph& g, Visitor vis, std::size_t min) { - function_requires< IncidenceGraphConcept >(); - function_requires< VertexListGraphConcept >(); - function_requires< VertexIndexGraphConcept >(); - function_requires< AdjacencyMatrixConcept >(); // Structural requirement only + BOOST_CONCEPT_ASSERT(( IncidenceGraphConcept )); + BOOST_CONCEPT_ASSERT(( VertexListGraphConcept )); + BOOST_CONCEPT_ASSERT(( VertexIndexGraphConcept )); + BOOST_CONCEPT_ASSERT(( AdjacencyMatrixConcept )); // Structural requirement only typedef typename graph_traits::vertex_descriptor Vertex; typedef typename graph_traits::vertex_iterator VertexIterator; typedef std::vector VertexSet; typedef std::deque Clique; - function_requires< CliqueVisitorConcept >(); + BOOST_CONCEPT_ASSERT(( CliqueVisitorConcept )); // NOTE: We're using a deque to implement the clique, because it provides // constant inserts and removals at the end and also a constant size. diff --git a/include/boost/graph/closeness_centrality.hpp b/include/boost/graph/closeness_centrality.hpp index d0dcabe15..44d478ab2 100644 --- a/include/boost/graph/closeness_centrality.hpp +++ b/include/boost/graph/closeness_centrality.hpp @@ -9,6 +9,7 @@ #include #include +#include namespace boost { @@ -25,9 +26,9 @@ struct closeness_measure result_type operator ()(distance_type d, const Graph&) { - function_requires< NumericValueConcept >(); - function_requires< NumericValueConcept >(); - function_requires< AdaptableUnaryFunctionConcept >(); + BOOST_CONCEPT_ASSERT(( NumericValueConcept )); + BOOST_CONCEPT_ASSERT(( NumericValueConcept )); + BOOST_CONCEPT_ASSERT(( AdaptableUnaryFunctionConcept )); return (d == base_type::infinite_distance()) ? base_type::zero_result() : rec(result_type(d)); @@ -75,12 +76,12 @@ closeness_centrality(const Graph& g, Measure measure, Combinator combine) { - function_requires< VertexListGraphConcept >(); + BOOST_CONCEPT_ASSERT(( VertexListGraphConcept )); typedef typename graph_traits::vertex_descriptor Vertex; - function_requires< ReadablePropertyMapConcept >(); + BOOST_CONCEPT_ASSERT(( ReadablePropertyMapConcept )); typedef typename property_traits::value_type Distance; - function_requires< NumericValueConcept >(); - function_requires< DistanceMeasureConcept >(); + BOOST_CONCEPT_ASSERT(( NumericValueConcept )); + BOOST_CONCEPT_ASSERT(( DistanceMeasureConcept )); Distance n = detail::combine_distances(g, dist, combine, Distance(0)); return measure(n, g); @@ -90,9 +91,9 @@ template inline typename Measure::result_type closeness_centrality(const Graph& g, DistanceMap dist, Measure measure) { - function_requires< GraphConcept >(); + BOOST_CONCEPT_ASSERT(( GraphConcept )); typedef typename graph_traits::vertex_descriptor Vertex; - function_requires< ReadablePropertyMapConcept >(); + BOOST_CONCEPT_ASSERT(( ReadablePropertyMapConcept )); typedef typename property_traits::value_type Distance; return closeness_centrality(g, dist, measure, std::plus()); @@ -116,12 +117,12 @@ all_closeness_centralities(const Graph& g, CentralityMap cent, Measure measure) { - function_requires< VertexListGraphConcept >(); + BOOST_CONCEPT_ASSERT(( VertexListGraphConcept )); typedef typename graph_traits::vertex_descriptor Vertex; - function_requires< ReadablePropertyMapConcept >(); + BOOST_CONCEPT_ASSERT(( ReadablePropertyMapConcept )); typedef typename property_traits::value_type DistanceMap; - function_requires< ReadablePropertyMapConcept >(); - function_requires< WritablePropertyMapConcept >(); + BOOST_CONCEPT_ASSERT(( ReadablePropertyMapConcept )); + BOOST_CONCEPT_ASSERT(( WritablePropertyMapConcept )); typedef typename property_traits::value_type Distance; typedef typename property_traits::value_type Centrality; @@ -141,11 +142,11 @@ all_closeness_centralities(const Graph& g, DistanceMatrixMap dist, CentralityMap cent) { - function_requires< GraphConcept >(); + BOOST_CONCEPT_ASSERT(( GraphConcept )); typedef typename graph_traits::vertex_descriptor Vertex; - function_requires< ReadablePropertyMapConcept >(); + BOOST_CONCEPT_ASSERT(( ReadablePropertyMapConcept )); typedef typename property_traits::value_type DistanceMap; - function_requires< ReadablePropertyMapConcept >(); + BOOST_CONCEPT_ASSERT(( ReadablePropertyMapConcept )); typedef typename property_traits::value_type Distance; typedef typename property_traits::value_type Result; diff --git a/include/boost/graph/clustering_coefficient.hpp b/include/boost/graph/clustering_coefficient.hpp index d897d94b5..dad4695a7 100644 --- a/include/boost/graph/clustering_coefficient.hpp +++ b/include/boost/graph/clustering_coefficient.hpp @@ -11,6 +11,7 @@ #include #include #include +#include namespace boost { @@ -20,7 +21,7 @@ namespace detail inline typename graph_traits::degree_size_type possible_edges(const Graph& g, std::size_t k, directed_tag) { - function_requires< GraphConcept >(); + BOOST_CONCEPT_ASSERT(( GraphConcept )); typedef typename graph_traits::degree_size_type T; return T(k) * (T(k) - 1); } @@ -42,7 +43,7 @@ namespace detail directed_tag) { - function_requires< AdjacencyMatrixConcept >(); + BOOST_CONCEPT_ASSERT(( AdjacencyMatrixConcept )); return (lookup_edge(u, v, g).second ? 1 : 0) + (lookup_edge(v, u, g).second ? 1 : 0); } @@ -55,7 +56,7 @@ namespace detail typename graph_traits::vertex_descriptor v, undirected_tag) { - function_requires< AdjacencyMatrixConcept >(); + BOOST_CONCEPT_ASSERT(( AdjacencyMatrixConcept )); return lookup_edge(u, v, g).second ? 1 : 0; } } @@ -64,7 +65,7 @@ template inline typename graph_traits::degree_size_type num_paths_through_vertex(const Graph& g, Vertex v) { - function_requires< AdjacencyGraphConcept >(); + BOOST_CONCEPT_ASSERT(( AdjacencyGraphConcept )); typedef typename graph_traits::directed_category Directed; typedef typename graph_traits::adjacency_iterator AdjacencyIterator; @@ -81,8 +82,8 @@ template inline typename graph_traits::degree_size_type num_triangles_on_vertex(const Graph& g, Vertex v) { - function_requires< IncidenceGraphConcept >(); - function_requires< AdjacencyGraphConcept >(); + BOOST_CONCEPT_ASSERT(( IncidenceGraphConcept )); + BOOST_CONCEPT_ASSERT(( AdjacencyGraphConcept )); typedef typename graph_traits::degree_size_type Degree; typedef typename graph_traits::directed_category Directed; typedef typename graph_traits::adjacency_iterator AdjacencyIterator; @@ -119,10 +120,10 @@ template inline typename property_traits::value_type all_clustering_coefficients(const Graph& g, ClusteringMap cm) { - function_requires< VertexListGraphConcept >(); + BOOST_CONCEPT_ASSERT(( VertexListGraphConcept )); typedef typename graph_traits::vertex_descriptor Vertex; typedef typename graph_traits::vertex_iterator VertexIterator; - function_requires< WritablePropertyMapConcept >(); + BOOST_CONCEPT_ASSERT(( WritablePropertyMapConcept )); typedef typename property_traits::value_type Coefficient; Coefficient sum(0); @@ -139,10 +140,10 @@ template inline typename property_traits::value_type mean_clustering_coefficient(const Graph& g, ClusteringMap cm) { - function_requires< VertexListGraphConcept >(); + BOOST_CONCEPT_ASSERT(( VertexListGraphConcept )); typedef typename graph_traits::vertex_descriptor Vertex; typedef typename graph_traits::vertex_iterator VertexIterator; - function_requires< ReadablePropertyMapConcept >(); + BOOST_CONCEPT_ASSERT(( ReadablePropertyMapConcept )); typedef typename property_traits::value_type Coefficient; Coefficient cc(0); diff --git a/include/boost/graph/connected_components.hpp b/include/boost/graph/connected_components.hpp index 90015e670..076b2a68e 100644 --- a/include/boost/graph/connected_components.hpp +++ b/include/boost/graph/connected_components.hpp @@ -17,6 +17,7 @@ #include #include #include +#include namespace boost { @@ -64,7 +65,7 @@ namespace boost { if (num_vertices(g) == 0) return 0; typedef typename graph_traits::vertex_descriptor Vertex; - function_requires< WritablePropertyMapConcept >(); + BOOST_CONCEPT_ASSERT(( WritablePropertyMapConcept )); typedef typename boost::graph_traits::directed_category directed; BOOST_STATIC_ASSERT((boost::is_same::value)); @@ -84,7 +85,7 @@ namespace boost { if (num_vertices(g) == 0) return 0; typedef typename graph_traits::vertex_descriptor Vertex; - function_requires< WritablePropertyMapConcept >(); + BOOST_CONCEPT_ASSERT(( WritablePropertyMapConcept )); typedef typename boost::graph_traits::directed_category directed; // BOOST_STATIC_ASSERT((boost::is_same::value)); diff --git a/include/boost/graph/core_numbers.hpp b/include/boost/graph/core_numbers.hpp index 7ef08261c..3db59c72b 100644 --- a/include/boost/graph/core_numbers.hpp +++ b/include/boost/graph/core_numbers.hpp @@ -15,6 +15,7 @@ #include #include #include +#include /* * core_numbers @@ -46,7 +47,7 @@ namespace boost { struct CoreNumbersVisitorConcept { void constraints() { - function_requires< CopyConstructibleConcept >(); + BOOST_CONCEPT_ASSERT(( CopyConstructibleConcept )); vis.examine_vertex(u,g); vis.finish_vertex(u,g); vis.examine_edge(e,g); diff --git a/include/boost/graph/degree_centrality.hpp b/include/boost/graph/degree_centrality.hpp index e3d7346cc..f6cc7a22f 100644 --- a/include/boost/graph/degree_centrality.hpp +++ b/include/boost/graph/degree_centrality.hpp @@ -8,6 +8,7 @@ #define BOOST_GRAPH_DEGREE_CENTRALITY_HPP #include +#include namespace boost { @@ -28,7 +29,7 @@ struct influence_measure inline degree_type operator ()(vertex_type v, const Graph& g) { - function_requires< IncidenceGraphConcept >(); + BOOST_CONCEPT_ASSERT(( IncidenceGraphConcept )); return out_degree(v, g); } }; @@ -49,7 +50,7 @@ struct prestige_measure inline degree_type operator ()(vertex_type v, const Graph& g) { - function_requires< BidirectionalGraphConcept >(); + BOOST_CONCEPT_ASSERT(( BidirectionalGraphConcept )); return in_degree(v, g); } }; @@ -64,7 +65,7 @@ template inline typename Measure::degree_type degree_centrality(const Graph& g, Vertex v, Measure measure) { - function_requires< DegreeMeasureConcept >(); + BOOST_CONCEPT_ASSERT(( DegreeMeasureConcept )); return measure(v, g); } @@ -94,10 +95,10 @@ template inline void all_degree_centralities(const Graph& g, CentralityMap cent, Measure measure) { - function_requires< VertexListGraphConcept >(); + BOOST_CONCEPT_ASSERT(( VertexListGraphConcept )); typedef typename graph_traits::vertex_descriptor Vertex; typedef typename graph_traits::vertex_iterator VertexIterator; - function_requires< WritablePropertyMapConcept >(); + BOOST_CONCEPT_ASSERT(( WritablePropertyMapConcept )); typedef typename property_traits::value_type Centrality; VertexIterator i, end; diff --git a/include/boost/graph/depth_first_search.hpp b/include/boost/graph/depth_first_search.hpp index 74fe2c029..d38ad603d 100644 --- a/include/boost/graph/depth_first_search.hpp +++ b/include/boost/graph/depth_first_search.hpp @@ -21,6 +21,7 @@ #include #include #include +#include #include #include @@ -31,7 +32,7 @@ namespace boost { class DFSVisitorConcept { public: void constraints() { - function_requires< CopyConstructibleConcept >(); + BOOST_CONCEPT_ASSERT(( CopyConstructibleConcept )); vis.initialize_vertex(u, g); vis.start_vertex(u, g); vis.discover_vertex(u, g); @@ -80,12 +81,12 @@ namespace boost { DFSVisitor& vis, ColorMap color, TerminatorFunc func = TerminatorFunc()) { - function_requires >(); - function_requires >(); + BOOST_CONCEPT_ASSERT(( IncidenceGraphConcept )); + BOOST_CONCEPT_ASSERT(( DFSVisitorConcept )); typedef typename graph_traits::vertex_descriptor Vertex; - function_requires< ReadWritePropertyMapConcept >(); + BOOST_CONCEPT_ASSERT(( ReadWritePropertyMapConcept )); typedef typename property_traits::value_type ColorValue; - function_requires< ColorValueConcept >(); + BOOST_CONCEPT_ASSERT(( ColorValueConcept )); typedef color_traits Color; typedef typename graph_traits::out_edge_iterator Iter; typedef std::pair > VertexInfo; @@ -151,12 +152,12 @@ namespace boost { DFSVisitor& vis, // pass-by-reference here, important! ColorMap color, TerminatorFunc func) { - function_requires >(); - function_requires >(); + BOOST_CONCEPT_ASSERT(( IncidenceGraphConcept )); + BOOST_CONCEPT_ASSERT(( DFSVisitorConcept )); typedef typename graph_traits::vertex_descriptor Vertex; - function_requires< ReadWritePropertyMapConcept >(); + BOOST_CONCEPT_ASSERT(( ReadWritePropertyMapConcept )); typedef typename property_traits::value_type ColorValue; - function_requires< ColorValueConcept >(); + BOOST_CONCEPT_ASSERT(( ColorValueConcept )); typedef color_traits Color; typename graph_traits::out_edge_iterator ei, ei_end; @@ -187,7 +188,7 @@ namespace boost { typename graph_traits::vertex_descriptor start_vertex) { typedef typename graph_traits::vertex_descriptor Vertex; - function_requires >(); + BOOST_CONCEPT_ASSERT(( DFSVisitorConcept )); typedef typename property_traits::value_type ColorValue; typedef color_traits Color; diff --git a/include/boost/graph/detail/geodesic.hpp b/include/boost/graph/detail/geodesic.hpp index 57e2a2088..adcb17f0a 100644 --- a/include/boost/graph/detail/geodesic.hpp +++ b/include/boost/graph/detail/geodesic.hpp @@ -11,6 +11,7 @@ #include #include #include +#include // TODO: Should this really be in detail? @@ -51,13 +52,13 @@ namespace detail { Combinator combine, Distance init) { - function_requires< VertexListGraphConcept >(); + BOOST_CONCEPT_ASSERT(( VertexListGraphConcept )); typedef typename graph_traits::vertex_descriptor Vertex; typedef typename graph_traits::vertex_iterator VertexIterator; - function_requires< ReadablePropertyMapConcept >(); - function_requires< NumericValueConcept >(); + BOOST_CONCEPT_ASSERT(( ReadablePropertyMapConcept )); + BOOST_CONCEPT_ASSERT(( NumericValueConcept )); typedef numeric_values DistanceNumbers; - function_requires< AdaptableBinaryFunction >(); + BOOST_CONCEPT_ASSERT(( AdaptableBinaryFunction )); // If there's ever an infinite distance, then we simply return // infinity. Note that this /will/ include the a non-zero diff --git a/include/boost/graph/dijkstra_shortest_paths.hpp b/include/boost/graph/dijkstra_shortest_paths.hpp index e0848e502..be0f97ea7 100644 --- a/include/boost/graph/dijkstra_shortest_paths.hpp +++ b/include/boost/graph/dijkstra_shortest_paths.hpp @@ -30,6 +30,7 @@ #include #include #include +#include #ifdef BOOST_GRAPH_DIJKSTRA_TESTING # include @@ -68,7 +69,7 @@ namespace boost { template struct DijkstraVisitorConcept { void constraints() { - function_requires< CopyConstructibleConcept >(); + BOOST_CONCEPT_ASSERT(( CopyConstructibleConcept )); vis.initialize_vertex(u, g); vis.discover_vertex(u, g); vis.examine_vertex(u, g); diff --git a/include/boost/graph/dominator_tree.hpp b/include/boost/graph/dominator_tree.hpp index db40cb73f..9371eee0d 100644 --- a/include/boost/graph/dominator_tree.hpp +++ b/include/boost/graph/dominator_tree.hpp @@ -13,6 +13,7 @@ #include #include #include +#include // Dominator tree computation @@ -244,7 +245,7 @@ namespace boost { typedef typename graph_traits::vertex_descriptor Vertex; typedef typename graph_traits::vertices_size_type VerticesSizeType; - function_requires< BidirectionalGraphConcept >(); + BOOST_CONCEPT_ASSERT(( BidirectionalGraphConcept )); const VerticesSizeType numOfVertices = num_vertices(g); if (numOfVertices == 0) return; @@ -299,7 +300,7 @@ namespace boost { // Typedefs and concept check typedef typename graph_traits::vertices_size_type VerticesSizeType; - function_requires< BidirectionalGraphConcept >(); + BOOST_CONCEPT_ASSERT(( BidirectionalGraphConcept )); // 1. Depth first visit const VerticesSizeType numOfVertices = num_vertices(g); @@ -388,7 +389,7 @@ namespace boost { iterator_property_map >::iterator, IndexMap> vertexSetMap; - function_requires >(); + BOOST_CONCEPT_ASSERT(( BidirectionalGraphConcept )); // 1. Finding dominator // 1.1. Initialize diff --git a/include/boost/graph/eccentricity.hpp b/include/boost/graph/eccentricity.hpp index 99f80a452..a8b3e4854 100644 --- a/include/boost/graph/eccentricity.hpp +++ b/include/boost/graph/eccentricity.hpp @@ -10,6 +10,7 @@ #include #include #include +#include namespace boost { @@ -19,9 +20,9 @@ template ::value_type eccentricity(const Graph& g, DistanceMap dist, Combinator combine) { - function_requires< GraphConcept >(); + BOOST_CONCEPT_ASSERT(( GraphConcept )); typedef typename graph_traits::vertex_descriptor Vertex; - function_requires< ReadablePropertyMapConcept >(); + BOOST_CONCEPT_ASSERT(( ReadablePropertyMapConcept )); typedef typename property_traits::value_type Distance; return detail::combine_distances(g, dist, combine, Distance(0)); @@ -31,9 +32,9 @@ template inline typename property_traits::value_type eccentricity(const Graph& g, DistanceMap dist) { - function_requires< GraphConcept >(); + BOOST_CONCEPT_ASSERT(( GraphConcept )); typedef typename graph_traits::vertex_descriptor Vertex; - function_requires< ReadablePropertyMapConcept >(); + BOOST_CONCEPT_ASSERT(( ReadablePropertyMapConcept )); typedef typename property_traits::value_type Distance; return eccentricity(g, dist, detail::maximize()); @@ -44,12 +45,12 @@ inline std::pair::value_type, typename property_traits::value_type> all_eccentricities(const Graph& g, const DistanceMatrix& dist, EccentricityMap ecc) { - function_requires< VertexListGraphConcept >(); + BOOST_CONCEPT_ASSERT(( VertexListGraphConcept )); typedef typename graph_traits::vertex_descriptor Vertex; typedef typename graph_traits::vertex_iterator VertexIterator; - function_requires< ReadablePropertyMapConcept >(); + BOOST_CONCEPT_ASSERT(( ReadablePropertyMapConcept )); typedef typename property_traits::value_type DistanceMap; - function_requires< WritablePropertyMapConcept >(); + BOOST_CONCEPT_ASSERT(( WritablePropertyMapConcept )); typedef typename property_traits::value_type Eccentricity; BOOST_USING_STD_MIN(); BOOST_USING_STD_MAX(); @@ -76,10 +77,10 @@ inline std::pair::value_type, typename property_traits::value_type> radius_and_diameter(const Graph& g, EccentricityMap ecc) { - function_requires< VertexListGraphConcept >(); + BOOST_CONCEPT_ASSERT(( VertexListGraphConcept )); typedef typename graph_traits::vertex_descriptor Vertex; typedef typename graph_traits::vertex_iterator VertexIterator; - function_requires< ReadablePropertyMapConcept >(); + BOOST_CONCEPT_ASSERT(( ReadablePropertyMapConcept )); typedef typename property_traits::value_type Eccentricity; BOOST_USING_STD_MIN(); BOOST_USING_STD_MAX(); diff --git a/include/boost/graph/floyd_warshall_shortest.hpp b/include/boost/graph/floyd_warshall_shortest.hpp index 3e95e1b06..472995f04 100644 --- a/include/boost/graph/floyd_warshall_shortest.hpp +++ b/include/boost/graph/floyd_warshall_shortest.hpp @@ -34,6 +34,7 @@ #include #include #include +#include namespace boost { @@ -84,7 +85,7 @@ namespace boost const BinaryFunction& combine, const Infinity& inf, const Zero& zero) { - function_requires >(); + BOOST_CONCEPT_ASSERT(( VertexListGraphConcept )); return detail::floyd_warshall_dispatch(g, d, compare, combine, inf, zero); @@ -101,9 +102,9 @@ namespace boost const BinaryPredicate& compare, const BinaryFunction& combine, const Infinity& inf, const Zero& zero) { - function_requires >(); - function_requires >(); - function_requires >(); + BOOST_CONCEPT_ASSERT(( VertexListGraphConcept )); + BOOST_CONCEPT_ASSERT(( EdgeListGraphConcept )); + BOOST_CONCEPT_ASSERT(( IncidenceGraphConcept )); typename graph_traits::vertex_iterator firstv, lastv, firstv2, lastv2; diff --git a/include/boost/graph/geodesic_distance.hpp b/include/boost/graph/geodesic_distance.hpp index 121ca4fb2..d76d321e1 100644 --- a/include/boost/graph/geodesic_distance.hpp +++ b/include/boost/graph/geodesic_distance.hpp @@ -9,6 +9,7 @@ #include #include +#include namespace boost { @@ -25,10 +26,10 @@ struct mean_geodesic_measure result_type operator ()(distance_type d, const Graph& g) { - function_requires< VertexListGraphConcept >(); - function_requires< NumericValueConcept >(); - function_requires< NumericValueConcept >(); - function_requires< AdaptableBinaryFunctionConcept >(); + BOOST_CONCEPT_ASSERT(( VertexListGraphConcept )); + BOOST_CONCEPT_ASSERT(( NumericValueConcept )); + BOOST_CONCEPT_ASSERT(( NumericValueConcept )); + BOOST_CONCEPT_ASSERT(( AdaptableBinaryFunctionConcept )); return (d == base_type::infinite_distance()) ? base_type::infinite_result() @@ -69,8 +70,8 @@ struct mean_graph_distance_measure inline result_type operator ()(distance_type d, const Graph& g) { - function_requires< VertexListGraphConcept >(); - function_requires< NumericValueConcept >(); + BOOST_CONCEPT_ASSERT(( VertexListGraphConcept )); + BOOST_CONCEPT_ASSERT(( NumericValueConcept )); if(d == base_type::infinite_distance()) { return base_type::infinite_result(); @@ -99,7 +100,7 @@ mean_geodesic(const Graph& g, Measure measure, Combinator combine) { - function_requires< DistanceMeasureConcept >(); + BOOST_CONCEPT_ASSERT(( DistanceMeasureConcept )); typedef typename Measure::distance_type Distance; Distance n = detail::combine_distances(g, dist, combine, Distance(0)); @@ -112,7 +113,7 @@ template >(); + BOOST_CONCEPT_ASSERT(( DistanceMeasureConcept )); typedef typename Measure::distance_type Distance; return mean_geodesic(g, dist, measure, std::plus()); @@ -139,15 +140,15 @@ all_mean_geodesics(const Graph& g, GeodesicMap geo, Measure measure) { - function_requires< VertexListGraphConcept >(); + BOOST_CONCEPT_ASSERT(( VertexListGraphConcept )); typedef typename graph_traits::vertex_descriptor Vertex; typedef typename graph_traits::vertex_iterator VertexIterator; - function_requires< ReadablePropertyMapConcept >(); + BOOST_CONCEPT_ASSERT(( ReadablePropertyMapConcept )); typedef typename property_traits::value_type DistanceMap; - function_requires< DistanceMeasureConcept >(); + BOOST_CONCEPT_ASSERT(( DistanceMeasureConcept )); typedef typename Measure::result_type Result; - function_requires< WritablePropertyMapConcept >(); - function_requires< NumericValueConcept >(); + BOOST_CONCEPT_ASSERT(( WritablePropertyMapConcept )); + BOOST_CONCEPT_ASSERT(( NumericValueConcept )); // NOTE: We could compute the mean geodesic here by performing additional // computations (i.e., adding and dividing). However, I don't really feel @@ -178,11 +179,11 @@ template inline typename property_traits::value_type all_mean_geodesics(const Graph& g, DistanceMatrixMap dist, GeodesicMap geo) { - function_requires< GraphConcept >(); + BOOST_CONCEPT_ASSERT(( GraphConcept )); typedef typename graph_traits::vertex_descriptor Vertex; - function_requires< ReadablePropertyMapConcept >(); + BOOST_CONCEPT_ASSERT(( ReadablePropertyMapConcept )); typedef typename property_traits::value_type DistanceMap; - function_requires< WritablePropertyMapConcept >(); + BOOST_CONCEPT_ASSERT(( WritablePropertyMapConcept )); typedef typename property_traits::value_type Result; return all_mean_geodesics(g, dist, geo, measure_mean_geodesic(g, DistanceMap())); @@ -193,7 +194,7 @@ template inline typename Measure::result_type small_world_distance(const Graph& g, GeodesicMap geo, Measure measure) { - function_requires< DistanceMeasureConcept >(); + BOOST_CONCEPT_ASSERT(( DistanceMeasureConcept )); typedef typename Measure::result_type Result; Result sum = detail::combine_distances(g, geo, std::plus(), Result(0)); diff --git a/include/boost/graph/graph_concepts.hpp b/include/boost/graph/graph_concepts.hpp index f382edf7f..8cb7cbb2f 100644 --- a/include/boost/graph/graph_concepts.hpp +++ b/include/boost/graph/graph_concepts.hpp @@ -21,6 +21,7 @@ #include #include #include +#include #include namespace boost @@ -529,8 +530,8 @@ typename T::ThereReallyIsNoMemberByThisNameInT vertices(T const&); { BOOST_CONCEPT_USAGE(NumericValue) { - function_requires< DefaultConstructible >(); - function_requires< CopyConstructible >(); + BOOST_CONCEPT_ASSERT(( DefaultConstructible )); + BOOST_CONCEPT_ASSERT(( CopyConstructible )); numeric_values::zero(); numeric_values::infinity(); } diff --git a/include/boost/graph/howard_cycle_ratio.hpp b/include/boost/graph/howard_cycle_ratio.hpp index 09c6522b8..afbf26d87 100644 --- a/include/boost/graph/howard_cycle_ratio.hpp +++ b/include/boost/graph/howard_cycle_ratio.hpp @@ -20,6 +20,7 @@ #include #include #include +#include /** @file howard_cycle_ratio.hpp * @brief The implementation of the maximum/minimum cycle ratio/mean algorithm. @@ -477,13 +478,13 @@ namespace boost { { typedef typename graph_traits::directed_category DirCat; BOOST_STATIC_ASSERT((is_convertible::value == true)); - function_requires< IncidenceGraphConcept >(); - function_requires< VertexListGraphConcept >(); + BOOST_CONCEPT_ASSERT(( IncidenceGraphConcept )); + BOOST_CONCEPT_ASSERT(( VertexListGraphConcept )); typedef typename graph_traits::vertex_descriptor Vertex; - function_requires< ReadablePropertyMapConcept >(); + BOOST_CONCEPT_ASSERT(( ReadablePropertyMapConcept )); typedef typename graph_traits::edge_descriptor Edge; - function_requires< ReadablePropertyMapConcept >(); - function_requires< ReadablePropertyMapConcept >(); + BOOST_CONCEPT_ASSERT(( ReadablePropertyMapConcept )); + BOOST_CONCEPT_ASSERT(( ReadablePropertyMapConcept )); if(pcc == 0) { return detail::mcr_howard( diff --git a/include/boost/graph/isomorphism.hpp b/include/boost/graph/isomorphism.hpp index 706e403db..bbdd1f7b4 100644 --- a/include/boost/graph/isomorphism.hpp +++ b/include/boost/graph/isomorphism.hpp @@ -15,6 +15,7 @@ #include #include #include // for make_indirect_pmap +#include #ifndef BOOST_GRAPH_ITERATION_MACROS_HPP #define BOOST_ISO_INCLUDED_ITER_MACROS // local macro, see bottom of file @@ -322,31 +323,31 @@ namespace boost { { // Graph requirements - function_requires< VertexListGraphConcept >(); - function_requires< EdgeListGraphConcept >(); - function_requires< VertexListGraphConcept >(); - function_requires< BidirectionalGraphConcept >(); + BOOST_CONCEPT_ASSERT(( VertexListGraphConcept )); + BOOST_CONCEPT_ASSERT(( EdgeListGraphConcept )); + BOOST_CONCEPT_ASSERT(( VertexListGraphConcept )); + BOOST_CONCEPT_ASSERT(( BidirectionalGraphConcept )); typedef typename graph_traits::vertex_descriptor vertex1_t; typedef typename graph_traits::vertex_descriptor vertex2_t; typedef typename graph_traits::vertices_size_type size_type; // Vertex invariant requirement - function_requires< AdaptableUnaryFunctionConcept >(); - function_requires< AdaptableUnaryFunctionConcept >(); + BOOST_CONCEPT_ASSERT(( AdaptableUnaryFunctionConcept )); + BOOST_CONCEPT_ASSERT(( AdaptableUnaryFunctionConcept )); // Property map requirements - function_requires< ReadWritePropertyMapConcept >(); + BOOST_CONCEPT_ASSERT(( ReadWritePropertyMapConcept )); typedef typename property_traits::value_type IsoMappingValue; BOOST_STATIC_ASSERT((is_same::value)); - function_requires< ReadablePropertyMapConcept >(); + BOOST_CONCEPT_ASSERT(( ReadablePropertyMapConcept )); typedef typename property_traits::value_type IndexMap1Value; BOOST_STATIC_ASSERT((is_convertible::value)); - function_requires< ReadablePropertyMapConcept >(); + BOOST_CONCEPT_ASSERT(( ReadablePropertyMapConcept )); typedef typename property_traits::value_type IndexMap2Value; BOOST_STATIC_ASSERT((is_convertible::value)); diff --git a/include/boost/graph/johnson_all_pairs_shortest.hpp b/include/boost/graph/johnson_all_pairs_shortest.hpp index 8aec50059..32e2b5cdc 100644 --- a/include/boost/graph/johnson_all_pairs_shortest.hpp +++ b/include/boost/graph/johnson_all_pairs_shortest.hpp @@ -29,6 +29,7 @@ #include #include #include +#include namespace boost { @@ -44,8 +45,8 @@ namespace boost { { typedef graph_traits Traits1; typedef typename property_traits::value_type DT; - function_requires< BasicMatrixConcept >(); + BOOST_CONCEPT_ASSERT(( BasicMatrixConcept )); typedef typename Traits1::directed_category DirCat; bool is_undirected = is_same::value; diff --git a/include/boost/graph/kruskal_min_spanning_tree.hpp b/include/boost/graph/kruskal_min_spanning_tree.hpp index a847e3f15..4d0c7efcd 100644 --- a/include/boost/graph/kruskal_min_spanning_tree.hpp +++ b/include/boost/graph/kruskal_min_spanning_tree.hpp @@ -28,6 +28,7 @@ #include #include #include +#include namespace boost { @@ -51,18 +52,18 @@ namespace boost { if (num_vertices(G) == 0) return; // Nothing to do in this case typedef typename graph_traits::vertex_descriptor Vertex; typedef typename graph_traits::edge_descriptor Edge; - function_requires >(); - function_requires >(); - function_requires >(); - function_requires >(); - function_requires >(); - function_requires >(); + BOOST_CONCEPT_ASSERT(( VertexListGraphConcept )); + BOOST_CONCEPT_ASSERT(( EdgeListGraphConcept )); + BOOST_CONCEPT_ASSERT(( OutputIteratorConcept )); + BOOST_CONCEPT_ASSERT(( ReadWritePropertyMapConcept )); + BOOST_CONCEPT_ASSERT(( ReadWritePropertyMapConcept )); + BOOST_CONCEPT_ASSERT(( ReadablePropertyMapConcept )); typedef typename property_traits::value_type W_value; typedef typename property_traits::value_type R_value; typedef typename property_traits::value_type P_value; - function_requires >(); - function_requires >(); - function_requires >(); + BOOST_CONCEPT_ASSERT(( ComparableConcept )); + BOOST_CONCEPT_ASSERT(( ConvertibleConcept )); + BOOST_CONCEPT_ASSERT(( IntegerConcept )); disjoint_sets dset(rank, parent); diff --git a/include/boost/graph/neighbor_bfs.hpp b/include/boost/graph/neighbor_bfs.hpp index 3ed94fc54..4585f2e29 100644 --- a/include/boost/graph/neighbor_bfs.hpp +++ b/include/boost/graph/neighbor_bfs.hpp @@ -24,13 +24,14 @@ #include #include #include +#include namespace boost { template struct NeighborBFSVisitorConcept { void constraints() { - function_requires< CopyConstructibleConcept >(); + BOOST_CONCEPT_ASSERT(( CopyConstructibleConcept )); vis.initialize_vertex(u, g); vis.discover_vertex(u, g); vis.examine_vertex(u, g); @@ -133,13 +134,13 @@ namespace boost { Buffer& Q, BFSVisitor vis, ColorMap color) { - function_requires< BidirectionalGraphConcept >(); + BOOST_CONCEPT_ASSERT(( BidirectionalGraphConcept )); typedef graph_traits GTraits; typedef typename GTraits::vertex_descriptor Vertex; typedef typename GTraits::edge_descriptor Edge; - function_requires< - NeighborBFSVisitorConcept >(); - function_requires< ReadWritePropertyMapConcept >(); + BOOST_CONCEPT_ASSERT(( + NeighborBFSVisitorConcept )); + BOOST_CONCEPT_ASSERT(( ReadWritePropertyMapConcept )); typedef typename property_traits::value_type ColorValue; typedef color_traits Color; diff --git a/include/boost/graph/strong_components.hpp b/include/boost/graph/strong_components.hpp index 6494283e5..ba5d45907 100644 --- a/include/boost/graph/strong_components.hpp +++ b/include/boost/graph/strong_components.hpp @@ -18,6 +18,7 @@ #include #include #include +#include namespace boost { @@ -93,11 +94,11 @@ namespace boost { const bgl_named_params& params) { typedef typename graph_traits::vertex_descriptor Vertex; - function_requires< ReadWritePropertyMapConcept >(); - function_requires< ReadWritePropertyMapConcept >(); + BOOST_CONCEPT_ASSERT(( ReadWritePropertyMapConcept )); + BOOST_CONCEPT_ASSERT(( ReadWritePropertyMapConcept )); typedef typename property_traits::value_type RootV; - function_requires< ConvertibleConcept >(); - function_requires< ReadWritePropertyMapConcept >(); + BOOST_CONCEPT_ASSERT(( ConvertibleConcept )); + BOOST_CONCEPT_ASSERT(( ReadWritePropertyMapConcept )); typename property_traits::value_type total = 0; @@ -282,7 +283,7 @@ namespace boost { kosaraju_strong_components(Graph& G, ComponentsMap c, FinishTime finish_time, ColorMap color) { - function_requires< MutableGraphConcept >(); + BOOST_CONCEPT_ASSERT(( MutableGraphConcept )); // ... typedef typename graph_traits::vertex_descriptor Vertex; diff --git a/include/boost/graph/tiernan_all_cycles.hpp b/include/boost/graph/tiernan_all_cycles.hpp index d45567962..2e7ebc97c 100644 --- a/include/boost/graph/tiernan_all_cycles.hpp +++ b/include/boost/graph/tiernan_all_cycles.hpp @@ -13,6 +13,7 @@ #include #include #include +#include #include namespace boost { @@ -156,8 +157,8 @@ namespace detail const Path& p, const ClosedMatrix& m) { - function_requires< IncidenceGraphConcept >(); - function_requires< VertexIndexGraphConcept >(); + BOOST_CONCEPT_ASSERT(( IncidenceGraphConcept )); + BOOST_CONCEPT_ASSERT(( VertexIndexGraphConcept )); typedef typename graph_traits::vertex_descriptor Vertex; // get the vertices in question @@ -181,7 +182,7 @@ namespace detail inline bool can_wrap_path(const Graph& g, const Path& p) { - function_requires< IncidenceGraphConcept >(); + BOOST_CONCEPT_ASSERT(( IncidenceGraphConcept )); typedef typename graph_traits::vertex_descriptor Vertex; typedef typename graph_traits::out_edge_iterator OutIterator; @@ -209,7 +210,7 @@ namespace detail Path& p, ClosedMatrix& closed) { - function_requires< IncidenceGraphConcept >(); + BOOST_CONCEPT_ASSERT(( IncidenceGraphConcept )); typedef typename graph_traits::vertex_descriptor Vertex; typedef typename graph_traits::edge_descriptor Edge; typedef typename graph_traits::out_edge_iterator OutIterator; @@ -238,7 +239,7 @@ namespace detail inline bool exhaust_paths(const Graph& g, Path& p, ClosedMatrix& closed) { - function_requires< GraphConcept >(); + BOOST_CONCEPT_ASSERT(( GraphConcept )); typedef typename graph_traits::vertex_descriptor Vertex; // if there's more than one vertex in the path, this closes @@ -272,10 +273,10 @@ namespace detail std::size_t minlen, std::size_t maxlen) { - function_requires< VertexListGraphConcept >(); + BOOST_CONCEPT_ASSERT(( VertexListGraphConcept )); typedef typename graph_traits::vertex_descriptor Vertex; typedef std::vector Path; - function_requires< CycleVisitorConcept >(); + BOOST_CONCEPT_ASSERT(( CycleVisitorConcept )); typedef std::vector VertexList; typedef std::vector ClosedMatrix; @@ -320,7 +321,7 @@ tiernan_all_cycles(const Graph& g, std::size_t minlen, std::size_t maxlen) { - function_requires< VertexListGraphConcept >(); + BOOST_CONCEPT_ASSERT(( VertexListGraphConcept )); typedef typename graph_traits::vertex_iterator VertexIterator; VertexIterator i, end; diff --git a/include/boost/graph/transitive_closure.hpp b/include/boost/graph/transitive_closure.hpp index 01bfb3d30..5ba0cab7f 100644 --- a/include/boost/graph/transitive_closure.hpp +++ b/include/boost/graph/transitive_closure.hpp @@ -19,6 +19,7 @@ #include #include #include +#include namespace boost { @@ -76,12 +77,12 @@ namespace boost typedef typename graph_traits < Graph >::adjacency_iterator adjacency_iterator; - function_requires < VertexListGraphConcept < Graph > >(); - function_requires < AdjacencyGraphConcept < Graph > >(); - function_requires < VertexMutableGraphConcept < GraphTC > >(); - function_requires < EdgeMutableGraphConcept < GraphTC > >(); - function_requires < ReadablePropertyMapConcept < VertexIndexMap, - vertex > >(); + BOOST_CONCEPT_ASSERT(( VertexListGraphConcept < Graph > )); + BOOST_CONCEPT_ASSERT(( AdjacencyGraphConcept < Graph > )); + BOOST_CONCEPT_ASSERT(( VertexMutableGraphConcept < GraphTC > )); + BOOST_CONCEPT_ASSERT(( EdgeMutableGraphConcept < GraphTC > )); + BOOST_CONCEPT_ASSERT(( ReadablePropertyMapConcept < VertexIndexMap, + vertex > )); typedef size_type cg_vertex; std::vector < cg_vertex > component_number_vec(num_vertices(g)); @@ -302,8 +303,8 @@ namespace boost typedef typename graph_traits < G >::vertex_descriptor vertex; typedef typename graph_traits < G >::vertex_iterator vertex_iterator; - function_requires < AdjacencyMatrixConcept < G > >(); - function_requires < EdgeMutableGraphConcept < G > >(); + BOOST_CONCEPT_ASSERT(( AdjacencyMatrixConcept < G > )); + BOOST_CONCEPT_ASSERT(( EdgeMutableGraphConcept < G > )); // Matrix form: // for k @@ -328,8 +329,8 @@ namespace boost typedef typename graph_traits < G >::vertex_descriptor vertex; typedef typename graph_traits < G >::vertex_iterator vertex_iterator; - function_requires < AdjacencyMatrixConcept < G > >(); - function_requires < EdgeMutableGraphConcept < G > >(); + BOOST_CONCEPT_ASSERT(( AdjacencyMatrixConcept < G > )); + BOOST_CONCEPT_ASSERT(( EdgeMutableGraphConcept < G > )); // Make sure second loop will work if (num_vertices(g) == 0) diff --git a/include/boost/graph/undirected_dfs.hpp b/include/boost/graph/undirected_dfs.hpp index 9cad25ad7..df31d22b2 100644 --- a/include/boost/graph/undirected_dfs.hpp +++ b/include/boost/graph/undirected_dfs.hpp @@ -13,6 +13,7 @@ #include #include +#include namespace boost { @@ -32,16 +33,16 @@ namespace boost { VertexColorMap vertex_color, EdgeColorMap edge_color) { - function_requires >(); - function_requires >(); + BOOST_CONCEPT_ASSERT(( IncidenceGraphConcept )); + BOOST_CONCEPT_ASSERT(( DFSVisitorConcept )); typedef typename graph_traits::vertex_descriptor Vertex; typedef typename graph_traits::edge_descriptor Edge; - function_requires >(); - function_requires >(); + BOOST_CONCEPT_ASSERT(( ReadWritePropertyMapConcept )); + BOOST_CONCEPT_ASSERT(( ReadWritePropertyMapConcept )); typedef typename property_traits::value_type ColorValue; typedef typename property_traits::value_type EColorValue; - function_requires< ColorValueConcept >(); - function_requires< ColorValueConcept >(); + BOOST_CONCEPT_ASSERT(( ColorValueConcept )); + BOOST_CONCEPT_ASSERT(( ColorValueConcept )); typedef color_traits Color; typedef color_traits EColor; typedef typename graph_traits::out_edge_iterator Iter; @@ -94,16 +95,16 @@ namespace boost { VertexColorMap vertex_color, EdgeColorMap edge_color) { - function_requires >(); - function_requires >(); + BOOST_CONCEPT_ASSERT(( IncidenceGraphConcept )); + BOOST_CONCEPT_ASSERT(( DFSVisitorConcept )); typedef typename graph_traits::vertex_descriptor Vertex; typedef typename graph_traits::edge_descriptor Edge; - function_requires >(); - function_requires >(); + BOOST_CONCEPT_ASSERT(( ReadWritePropertyMapConcept )); + BOOST_CONCEPT_ASSERT(( ReadWritePropertyMapConcept )); typedef typename property_traits::value_type ColorValue; typedef typename property_traits::value_type EColorValue; - function_requires< ColorValueConcept >(); - function_requires< ColorValueConcept >(); + BOOST_CONCEPT_ASSERT(( ColorValueConcept )); + BOOST_CONCEPT_ASSERT(( ColorValueConcept )); typedef color_traits Color; typedef color_traits EColor; typename graph_traits::out_edge_iterator ei, ei_end; @@ -134,8 +135,8 @@ namespace boost { VertexColorMap vertex_color, EdgeColorMap edge_color, Vertex start_vertex) { - function_requires >(); - function_requires >(); + BOOST_CONCEPT_ASSERT(( DFSVisitorConcept )); + BOOST_CONCEPT_ASSERT(( EdgeListGraphConcept )); typedef typename property_traits::value_type ColorValue; typedef color_traits Color; diff --git a/test/adj_list_cc.cpp b/test/adj_list_cc.cpp index 8f22d5735..fad293883 100644 --- a/test/adj_list_cc.cpp +++ b/test/adj_list_cc.cpp @@ -9,6 +9,7 @@ #include #include #include +#include int main(int,char*[]) { @@ -21,20 +22,20 @@ int main(int,char*[]) > Graph; typedef graph_traits::vertex_descriptor Vertex; typedef graph_traits::edge_descriptor Edge; - function_requires< VertexListGraphConcept >(); - function_requires< EdgeListGraphConcept >(); - function_requires< IncidenceGraphConcept >(); - function_requires< AdjacencyGraphConcept >(); - function_requires< MutableIncidenceGraphConcept >(); - function_requires< MutableEdgeListGraphConcept >(); - function_requires< VertexMutablePropertyGraphConcept >(); - function_requires< EdgeMutablePropertyGraphConcept >(); - function_requires< - ReadablePropertyGraphConcept >(); - function_requires< - LvaluePropertyGraphConcept >(); - function_requires< - LvaluePropertyGraphConcept >(); + BOOST_CONCEPT_ASSERT(( VertexListGraphConcept )); + BOOST_CONCEPT_ASSERT(( EdgeListGraphConcept )); + BOOST_CONCEPT_ASSERT(( IncidenceGraphConcept )); + BOOST_CONCEPT_ASSERT(( AdjacencyGraphConcept )); + BOOST_CONCEPT_ASSERT(( MutableIncidenceGraphConcept )); + BOOST_CONCEPT_ASSERT(( MutableEdgeListGraphConcept )); + BOOST_CONCEPT_ASSERT(( VertexMutablePropertyGraphConcept )); + BOOST_CONCEPT_ASSERT(( EdgeMutablePropertyGraphConcept )); + BOOST_CONCEPT_ASSERT(( + ReadablePropertyGraphConcept )); + BOOST_CONCEPT_ASSERT(( + LvaluePropertyGraphConcept )); + BOOST_CONCEPT_ASSERT(( + LvaluePropertyGraphConcept )); } { typedef adjacency_list Graph; typedef graph_traits::vertex_descriptor Vertex; typedef graph_traits::edge_descriptor Edge; - function_requires< VertexListGraphConcept >(); - function_requires< EdgeListGraphConcept >(); - function_requires< IncidenceGraphConcept >(); - function_requires< AdjacencyGraphConcept >(); - function_requires< BidirectionalGraphConcept >(); - function_requires< MutableBidirectionalGraphConcept >(); - function_requires< MutableEdgeListGraphConcept >(); - function_requires< VertexMutablePropertyGraphConcept >(); - function_requires< EdgeMutablePropertyGraphConcept >(); - function_requires< - ReadablePropertyGraphConcept >(); - function_requires< - LvaluePropertyGraphConcept >(); - function_requires< - LvaluePropertyGraphConcept >(); + BOOST_CONCEPT_ASSERT(( VertexListGraphConcept )); + BOOST_CONCEPT_ASSERT(( EdgeListGraphConcept )); + BOOST_CONCEPT_ASSERT(( IncidenceGraphConcept )); + BOOST_CONCEPT_ASSERT(( AdjacencyGraphConcept )); + BOOST_CONCEPT_ASSERT(( BidirectionalGraphConcept )); + BOOST_CONCEPT_ASSERT(( MutableBidirectionalGraphConcept )); + BOOST_CONCEPT_ASSERT(( MutableEdgeListGraphConcept )); + BOOST_CONCEPT_ASSERT(( VertexMutablePropertyGraphConcept )); + BOOST_CONCEPT_ASSERT(( EdgeMutablePropertyGraphConcept )); + BOOST_CONCEPT_ASSERT(( + ReadablePropertyGraphConcept )); + BOOST_CONCEPT_ASSERT(( + LvaluePropertyGraphConcept )); + BOOST_CONCEPT_ASSERT(( + LvaluePropertyGraphConcept )); } { typedef adjacency_list< listS, listS, directedS, @@ -66,20 +67,20 @@ int main(int,char*[]) > Graph; typedef graph_traits::vertex_descriptor Vertex; typedef graph_traits::edge_descriptor Edge; - function_requires< VertexListGraphConcept >(); - function_requires< EdgeListGraphConcept >(); - function_requires< IncidenceGraphConcept >(); - function_requires< AdjacencyGraphConcept >(); - function_requires< MutableIncidenceGraphConcept >(); - function_requires< MutableEdgeListGraphConcept >(); - function_requires< VertexMutablePropertyGraphConcept >(); - function_requires< EdgeMutablePropertyGraphConcept >(); - function_requires< - ReadablePropertyGraphConcept >(); - function_requires< - LvaluePropertyGraphConcept >(); - function_requires< - LvaluePropertyGraphConcept >(); + BOOST_CONCEPT_ASSERT(( VertexListGraphConcept )); + BOOST_CONCEPT_ASSERT(( EdgeListGraphConcept )); + BOOST_CONCEPT_ASSERT(( IncidenceGraphConcept )); + BOOST_CONCEPT_ASSERT(( AdjacencyGraphConcept )); + BOOST_CONCEPT_ASSERT(( MutableIncidenceGraphConcept )); + BOOST_CONCEPT_ASSERT(( MutableEdgeListGraphConcept )); + BOOST_CONCEPT_ASSERT(( VertexMutablePropertyGraphConcept )); + BOOST_CONCEPT_ASSERT(( EdgeMutablePropertyGraphConcept )); + BOOST_CONCEPT_ASSERT(( + ReadablePropertyGraphConcept )); + BOOST_CONCEPT_ASSERT(( + LvaluePropertyGraphConcept )); + BOOST_CONCEPT_ASSERT(( + LvaluePropertyGraphConcept )); } { typedef adjacency_list< listS, listS, undirectedS, @@ -88,20 +89,20 @@ int main(int,char*[]) > Graph; typedef graph_traits::vertex_descriptor Vertex; typedef graph_traits::edge_descriptor Edge; - function_requires< VertexListGraphConcept >(); - function_requires< EdgeListGraphConcept >(); - function_requires< IncidenceGraphConcept >(); - function_requires< AdjacencyGraphConcept >(); - function_requires< MutableBidirectionalGraphConcept >(); - function_requires< MutableEdgeListGraphConcept >(); - function_requires< VertexMutablePropertyGraphConcept >(); - function_requires< EdgeMutablePropertyGraphConcept >(); - function_requires< - ReadablePropertyGraphConcept >(); - function_requires< - LvaluePropertyGraphConcept >(); - function_requires< - LvaluePropertyGraphConcept >(); + BOOST_CONCEPT_ASSERT(( VertexListGraphConcept )); + BOOST_CONCEPT_ASSERT(( EdgeListGraphConcept )); + BOOST_CONCEPT_ASSERT(( IncidenceGraphConcept )); + BOOST_CONCEPT_ASSERT(( AdjacencyGraphConcept )); + BOOST_CONCEPT_ASSERT(( MutableBidirectionalGraphConcept )); + BOOST_CONCEPT_ASSERT(( MutableEdgeListGraphConcept )); + BOOST_CONCEPT_ASSERT(( VertexMutablePropertyGraphConcept )); + BOOST_CONCEPT_ASSERT(( EdgeMutablePropertyGraphConcept )); + BOOST_CONCEPT_ASSERT(( + ReadablePropertyGraphConcept )); + BOOST_CONCEPT_ASSERT(( + LvaluePropertyGraphConcept )); + BOOST_CONCEPT_ASSERT(( + LvaluePropertyGraphConcept )); } // Checking adjacency_list with EdgeList=setS { @@ -111,21 +112,21 @@ int main(int,char*[]) > Graph; typedef graph_traits::vertex_descriptor Vertex; typedef graph_traits::edge_descriptor Edge; - function_requires< VertexListGraphConcept >(); - function_requires< EdgeListGraphConcept >(); - function_requires< IncidenceGraphConcept >(); - function_requires< AdjacencyGraphConcept >(); - function_requires< BidirectionalGraphConcept >(); - function_requires< MutableBidirectionalGraphConcept >(); - function_requires< MutableEdgeListGraphConcept >(); - function_requires< VertexMutablePropertyGraphConcept >(); - function_requires< EdgeMutablePropertyGraphConcept >(); - function_requires< - ReadablePropertyGraphConcept >(); - function_requires< - LvaluePropertyGraphConcept >(); - function_requires< - LvaluePropertyGraphConcept >(); + BOOST_CONCEPT_ASSERT(( VertexListGraphConcept )); + BOOST_CONCEPT_ASSERT(( EdgeListGraphConcept )); + BOOST_CONCEPT_ASSERT(( IncidenceGraphConcept )); + BOOST_CONCEPT_ASSERT(( AdjacencyGraphConcept )); + BOOST_CONCEPT_ASSERT(( BidirectionalGraphConcept )); + BOOST_CONCEPT_ASSERT(( MutableBidirectionalGraphConcept )); + BOOST_CONCEPT_ASSERT(( MutableEdgeListGraphConcept )); + BOOST_CONCEPT_ASSERT(( VertexMutablePropertyGraphConcept )); + BOOST_CONCEPT_ASSERT(( EdgeMutablePropertyGraphConcept )); + BOOST_CONCEPT_ASSERT(( + ReadablePropertyGraphConcept )); + BOOST_CONCEPT_ASSERT(( + LvaluePropertyGraphConcept )); + BOOST_CONCEPT_ASSERT(( + LvaluePropertyGraphConcept )); } { typedef adjacency_list< setS, listS, directedS, @@ -134,20 +135,20 @@ int main(int,char*[]) > Graph; typedef graph_traits::vertex_descriptor Vertex; typedef graph_traits::edge_descriptor Edge; - function_requires< VertexListGraphConcept >(); - function_requires< EdgeListGraphConcept >(); - function_requires< IncidenceGraphConcept >(); - function_requires< AdjacencyGraphConcept >(); - function_requires< MutableIncidenceGraphConcept >(); - function_requires< MutableEdgeListGraphConcept >(); - function_requires< VertexMutablePropertyGraphConcept >(); - function_requires< EdgeMutablePropertyGraphConcept >(); - function_requires< - ReadablePropertyGraphConcept >(); - function_requires< - LvaluePropertyGraphConcept >(); - function_requires< - LvaluePropertyGraphConcept >(); + BOOST_CONCEPT_ASSERT(( VertexListGraphConcept )); + BOOST_CONCEPT_ASSERT(( EdgeListGraphConcept )); + BOOST_CONCEPT_ASSERT(( IncidenceGraphConcept )); + BOOST_CONCEPT_ASSERT(( AdjacencyGraphConcept )); + BOOST_CONCEPT_ASSERT(( MutableIncidenceGraphConcept )); + BOOST_CONCEPT_ASSERT(( MutableEdgeListGraphConcept )); + BOOST_CONCEPT_ASSERT(( VertexMutablePropertyGraphConcept )); + BOOST_CONCEPT_ASSERT(( EdgeMutablePropertyGraphConcept )); + BOOST_CONCEPT_ASSERT(( + ReadablePropertyGraphConcept )); + BOOST_CONCEPT_ASSERT(( + LvaluePropertyGraphConcept )); + BOOST_CONCEPT_ASSERT(( + LvaluePropertyGraphConcept )); } { typedef adjacency_list< setS, listS, undirectedS, @@ -156,105 +157,105 @@ int main(int,char*[]) > Graph; typedef graph_traits::vertex_descriptor Vertex; typedef graph_traits::edge_descriptor Edge; - function_requires< VertexListGraphConcept >(); - function_requires< EdgeListGraphConcept >(); - function_requires< IncidenceGraphConcept >(); - function_requires< AdjacencyGraphConcept >(); - function_requires< MutableBidirectionalGraphConcept >(); - function_requires< MutableEdgeListGraphConcept >(); - function_requires< VertexMutablePropertyGraphConcept >(); - function_requires< EdgeMutablePropertyGraphConcept >(); - function_requires< - ReadablePropertyGraphConcept >(); - function_requires< - LvaluePropertyGraphConcept >(); - function_requires< - LvaluePropertyGraphConcept >(); + BOOST_CONCEPT_ASSERT(( VertexListGraphConcept )); + BOOST_CONCEPT_ASSERT(( EdgeListGraphConcept )); + BOOST_CONCEPT_ASSERT(( IncidenceGraphConcept )); + BOOST_CONCEPT_ASSERT(( AdjacencyGraphConcept )); + BOOST_CONCEPT_ASSERT(( MutableBidirectionalGraphConcept )); + BOOST_CONCEPT_ASSERT(( MutableEdgeListGraphConcept )); + BOOST_CONCEPT_ASSERT(( VertexMutablePropertyGraphConcept )); + BOOST_CONCEPT_ASSERT(( EdgeMutablePropertyGraphConcept )); + BOOST_CONCEPT_ASSERT(( + ReadablePropertyGraphConcept )); + BOOST_CONCEPT_ASSERT(( + LvaluePropertyGraphConcept )); + BOOST_CONCEPT_ASSERT(( + LvaluePropertyGraphConcept )); } // Check adjacency_list without any properties { typedef adjacency_list Graph; typedef graph_traits::vertex_descriptor Vertex; typedef graph_traits::edge_descriptor Edge; - function_requires< VertexListGraphConcept >(); - function_requires< EdgeListGraphConcept >(); - function_requires< IncidenceGraphConcept >(); - function_requires< AdjacencyGraphConcept >(); - function_requires< MutableIncidenceGraphConcept >(); - function_requires< MutableEdgeListGraphConcept >(); - function_requires< VertexMutablePropertyGraphConcept >(); - function_requires< EdgeMutablePropertyGraphConcept >(); - function_requires< - ReadablePropertyGraphConcept >(); + BOOST_CONCEPT_ASSERT(( VertexListGraphConcept )); + BOOST_CONCEPT_ASSERT(( EdgeListGraphConcept )); + BOOST_CONCEPT_ASSERT(( IncidenceGraphConcept )); + BOOST_CONCEPT_ASSERT(( AdjacencyGraphConcept )); + BOOST_CONCEPT_ASSERT(( MutableIncidenceGraphConcept )); + BOOST_CONCEPT_ASSERT(( MutableEdgeListGraphConcept )); + BOOST_CONCEPT_ASSERT(( VertexMutablePropertyGraphConcept )); + BOOST_CONCEPT_ASSERT(( EdgeMutablePropertyGraphConcept )); + BOOST_CONCEPT_ASSERT(( + ReadablePropertyGraphConcept )); } { typedef adjacency_list Graph; typedef graph_traits::vertex_descriptor Vertex; typedef graph_traits::edge_descriptor Edge; - function_requires< VertexListGraphConcept >(); - function_requires< EdgeListGraphConcept >(); - function_requires< IncidenceGraphConcept >(); - function_requires< AdjacencyGraphConcept >(); - function_requires< BidirectionalGraphConcept >(); - function_requires< MutableBidirectionalGraphConcept >(); - function_requires< MutableEdgeListGraphConcept >(); - function_requires< - ReadablePropertyGraphConcept >(); + BOOST_CONCEPT_ASSERT(( VertexListGraphConcept )); + BOOST_CONCEPT_ASSERT(( EdgeListGraphConcept )); + BOOST_CONCEPT_ASSERT(( IncidenceGraphConcept )); + BOOST_CONCEPT_ASSERT(( AdjacencyGraphConcept )); + BOOST_CONCEPT_ASSERT(( BidirectionalGraphConcept )); + BOOST_CONCEPT_ASSERT(( MutableBidirectionalGraphConcept )); + BOOST_CONCEPT_ASSERT(( MutableEdgeListGraphConcept )); + BOOST_CONCEPT_ASSERT(( + ReadablePropertyGraphConcept )); } { typedef adjacency_list< listS, listS, directedS> Graph; typedef graph_traits::vertex_descriptor Vertex; typedef graph_traits::edge_descriptor Edge; - function_requires< VertexListGraphConcept >(); - function_requires< EdgeListGraphConcept >(); - function_requires< IncidenceGraphConcept >(); - function_requires< AdjacencyGraphConcept >(); - function_requires< MutableIncidenceGraphConcept >(); - function_requires< MutableEdgeListGraphConcept >(); + BOOST_CONCEPT_ASSERT(( VertexListGraphConcept )); + BOOST_CONCEPT_ASSERT(( EdgeListGraphConcept )); + BOOST_CONCEPT_ASSERT(( IncidenceGraphConcept )); + BOOST_CONCEPT_ASSERT(( AdjacencyGraphConcept )); + BOOST_CONCEPT_ASSERT(( MutableIncidenceGraphConcept )); + BOOST_CONCEPT_ASSERT(( MutableEdgeListGraphConcept )); } { typedef adjacency_list< listS, listS, undirectedS> Graph; typedef graph_traits::vertex_descriptor Vertex; typedef graph_traits::edge_descriptor Edge; - function_requires< VertexListGraphConcept >(); - function_requires< EdgeListGraphConcept >(); - function_requires< IncidenceGraphConcept >(); - function_requires< AdjacencyGraphConcept >(); - function_requires< MutableBidirectionalGraphConcept >(); - function_requires< MutableEdgeListGraphConcept >(); + BOOST_CONCEPT_ASSERT(( VertexListGraphConcept )); + BOOST_CONCEPT_ASSERT(( EdgeListGraphConcept )); + BOOST_CONCEPT_ASSERT(( IncidenceGraphConcept )); + BOOST_CONCEPT_ASSERT(( AdjacencyGraphConcept )); + BOOST_CONCEPT_ASSERT(( MutableBidirectionalGraphConcept )); + BOOST_CONCEPT_ASSERT(( MutableEdgeListGraphConcept )); } // Checking EdgeList=setS with no properties { typedef adjacency_list Graph; typedef graph_traits::vertex_descriptor Vertex; typedef graph_traits::edge_descriptor Edge; - function_requires< VertexListGraphConcept >(); - function_requires< EdgeListGraphConcept >(); - function_requires< IncidenceGraphConcept >(); - function_requires< AdjacencyGraphConcept >(); - function_requires< BidirectionalGraphConcept >(); - function_requires< MutableBidirectionalGraphConcept >(); - function_requires< MutableEdgeListGraphConcept >(); - function_requires< ReadablePropertyGraphConcept >(); + BOOST_CONCEPT_ASSERT(( VertexListGraphConcept )); + BOOST_CONCEPT_ASSERT(( EdgeListGraphConcept )); + BOOST_CONCEPT_ASSERT(( IncidenceGraphConcept )); + BOOST_CONCEPT_ASSERT(( AdjacencyGraphConcept )); + BOOST_CONCEPT_ASSERT(( BidirectionalGraphConcept )); + BOOST_CONCEPT_ASSERT(( MutableBidirectionalGraphConcept )); + BOOST_CONCEPT_ASSERT(( MutableEdgeListGraphConcept )); + BOOST_CONCEPT_ASSERT(( ReadablePropertyGraphConcept )); } { typedef adjacency_list< setS, listS, directedS> Graph; typedef graph_traits::vertex_descriptor Vertex; typedef graph_traits::edge_descriptor Edge; - function_requires< MutableIncidenceGraphConcept >(); - function_requires< MutableEdgeListGraphConcept >(); + BOOST_CONCEPT_ASSERT(( MutableIncidenceGraphConcept )); + BOOST_CONCEPT_ASSERT(( MutableEdgeListGraphConcept )); } { typedef adjacency_list< setS, listS, undirectedS> Graph; typedef graph_traits::vertex_descriptor Vertex; typedef graph_traits::edge_descriptor Edge; - function_requires< VertexListGraphConcept >(); - function_requires< EdgeListGraphConcept >(); - function_requires< IncidenceGraphConcept >(); - function_requires< AdjacencyGraphConcept >(); - function_requires< MutableBidirectionalGraphConcept >(); - function_requires< MutableEdgeListGraphConcept >(); + BOOST_CONCEPT_ASSERT(( VertexListGraphConcept )); + BOOST_CONCEPT_ASSERT(( EdgeListGraphConcept )); + BOOST_CONCEPT_ASSERT(( IncidenceGraphConcept )); + BOOST_CONCEPT_ASSERT(( AdjacencyGraphConcept )); + BOOST_CONCEPT_ASSERT(( MutableBidirectionalGraphConcept )); + BOOST_CONCEPT_ASSERT(( MutableEdgeListGraphConcept )); } return 0; } diff --git a/test/adj_matrix_cc.cpp b/test/adj_matrix_cc.cpp index 317a22f4a..ae8060145 100644 --- a/test/adj_matrix_cc.cpp +++ b/test/adj_matrix_cc.cpp @@ -9,6 +9,7 @@ #include #include #include +#include int main(int,char*[]) { @@ -16,21 +17,21 @@ int main(int,char*[]) // Check adjacency_matrix without properties { typedef adjacency_matrix Graph; - function_requires< VertexListGraphConcept >(); - function_requires< EdgeListGraphConcept >(); - function_requires< IncidenceGraphConcept >(); - function_requires< AdjacencyGraphConcept >(); - function_requires< MutableGraphConcept >(); - function_requires< AdjacencyMatrixConcept >(); + BOOST_CONCEPT_ASSERT(( VertexListGraphConcept )); + BOOST_CONCEPT_ASSERT(( EdgeListGraphConcept )); + BOOST_CONCEPT_ASSERT(( IncidenceGraphConcept )); + BOOST_CONCEPT_ASSERT(( AdjacencyGraphConcept )); + BOOST_CONCEPT_ASSERT(( MutableGraphConcept )); + BOOST_CONCEPT_ASSERT(( AdjacencyMatrixConcept )); } { typedef adjacency_matrix Graph; - function_requires< VertexListGraphConcept >(); - function_requires< EdgeListGraphConcept >(); - function_requires< IncidenceGraphConcept >(); - function_requires< AdjacencyGraphConcept >(); - function_requires< MutableGraphConcept >(); - function_requires< AdjacencyMatrixConcept >(); + BOOST_CONCEPT_ASSERT(( VertexListGraphConcept )); + BOOST_CONCEPT_ASSERT(( EdgeListGraphConcept )); + BOOST_CONCEPT_ASSERT(( IncidenceGraphConcept )); + BOOST_CONCEPT_ASSERT(( AdjacencyGraphConcept )); + BOOST_CONCEPT_ASSERT(( MutableGraphConcept )); + BOOST_CONCEPT_ASSERT(( AdjacencyMatrixConcept )); } // Check adjacency_matrix with properties { @@ -39,17 +40,17 @@ int main(int,char*[]) property > Graph; typedef graph_traits::vertex_descriptor Vertex; typedef graph_traits::edge_descriptor Edge; - function_requires< VertexListGraphConcept >(); - function_requires< EdgeListGraphConcept >(); - function_requires< IncidenceGraphConcept >(); - function_requires< AdjacencyGraphConcept >(); - function_requires< AdjacencyMatrixConcept >(); - function_requires< VertexMutablePropertyGraphConcept >(); - function_requires< EdgeMutablePropertyGraphConcept >(); - function_requires< ReadablePropertyGraphConcept >(); - function_requires< PropertyGraphConcept >(); - function_requires< PropertyGraphConcept >(); + BOOST_CONCEPT_ASSERT(( VertexListGraphConcept )); + BOOST_CONCEPT_ASSERT(( EdgeListGraphConcept )); + BOOST_CONCEPT_ASSERT(( IncidenceGraphConcept )); + BOOST_CONCEPT_ASSERT(( AdjacencyGraphConcept )); + BOOST_CONCEPT_ASSERT(( AdjacencyMatrixConcept )); + BOOST_CONCEPT_ASSERT(( VertexMutablePropertyGraphConcept )); + BOOST_CONCEPT_ASSERT(( EdgeMutablePropertyGraphConcept )); + BOOST_CONCEPT_ASSERT(( ReadablePropertyGraphConcept )); + BOOST_CONCEPT_ASSERT(( PropertyGraphConcept )); + BOOST_CONCEPT_ASSERT(( PropertyGraphConcept )); } { typedef adjacency_matrix > Graph; typedef graph_traits::vertex_descriptor Vertex; typedef graph_traits::edge_descriptor Edge; - function_requires< VertexListGraphConcept >(); - function_requires< EdgeListGraphConcept >(); - function_requires< IncidenceGraphConcept >(); - function_requires< AdjacencyGraphConcept >(); - function_requires< AdjacencyMatrixConcept >(); - function_requires< VertexMutablePropertyGraphConcept >(); - function_requires< EdgeMutablePropertyGraphConcept >(); - function_requires< ReadablePropertyGraphConcept >(); - function_requires< PropertyGraphConcept >(); - function_requires< PropertyGraphConcept >(); + BOOST_CONCEPT_ASSERT(( VertexListGraphConcept )); + BOOST_CONCEPT_ASSERT(( EdgeListGraphConcept )); + BOOST_CONCEPT_ASSERT(( IncidenceGraphConcept )); + BOOST_CONCEPT_ASSERT(( AdjacencyGraphConcept )); + BOOST_CONCEPT_ASSERT(( AdjacencyMatrixConcept )); + BOOST_CONCEPT_ASSERT(( VertexMutablePropertyGraphConcept )); + BOOST_CONCEPT_ASSERT(( EdgeMutablePropertyGraphConcept )); + BOOST_CONCEPT_ASSERT(( ReadablePropertyGraphConcept )); + BOOST_CONCEPT_ASSERT(( PropertyGraphConcept )); + BOOST_CONCEPT_ASSERT(( PropertyGraphConcept )); } return 0; } diff --git a/test/edge_list_cc.cpp b/test/edge_list_cc.cpp index 0741cceac..18d34e050 100644 --- a/test/edge_list_cc.cpp +++ b/test/edge_list_cc.cpp @@ -9,6 +9,7 @@ #include #include #include +#include #include #include @@ -24,10 +25,10 @@ int main(int,char*[]) typedef graph_traits::edge_descriptor Edge; - function_requires< EdgeListGraphConcept >(); + BOOST_CONCEPT_ASSERT(( EdgeListGraphConcept )); - function_requires< ReadablePropertyGraphConcept >(); + BOOST_CONCEPT_ASSERT(( ReadablePropertyGraphConcept )); } return 0; } diff --git a/test/filtered_graph_cc.cpp b/test/filtered_graph_cc.cpp index 09feb4b00..52221b1ef 100644 --- a/test/filtered_graph_cc.cpp +++ b/test/filtered_graph_cc.cpp @@ -10,6 +10,7 @@ #include #include #include +#include int main(int,char*[]) { @@ -22,12 +23,12 @@ int main(int,char*[]) typedef filtered_graph > ResGraph; typedef graph_traits::edge_descriptor Edge; - function_requires< VertexListGraphConcept >(); - function_requires< EdgeListGraphConcept >(); - function_requires< IncidenceGraphConcept >(); - function_requires< AdjacencyGraphConcept >(); - function_requires< PropertyGraphConcept >(); + BOOST_CONCEPT_ASSERT(( VertexListGraphConcept )); + BOOST_CONCEPT_ASSERT(( EdgeListGraphConcept )); + BOOST_CONCEPT_ASSERT(( IncidenceGraphConcept )); + BOOST_CONCEPT_ASSERT(( AdjacencyGraphConcept )); + BOOST_CONCEPT_ASSERT(( PropertyGraphConcept )); } // Check filtered_graph with bidirectional adjacency_list { @@ -35,7 +36,7 @@ int main(int,char*[]) no_property, property > Graph; typedef property_map::type ResCapMap; typedef filtered_graph > ResGraph; - function_requires< BidirectionalGraphConcept >(); + BOOST_CONCEPT_ASSERT(( BidirectionalGraphConcept )); } return 0; } diff --git a/test/graph_concepts.cpp b/test/graph_concepts.cpp index cfab6b4dd..c2edc342e 100644 --- a/test/graph_concepts.cpp +++ b/test/graph_concepts.cpp @@ -8,6 +8,7 @@ //======================================================================= #include #include +#include int main(int,char*[]) { @@ -19,22 +20,22 @@ int main(int,char*[]) typedef incidence_graph_archetype Graph1; - function_requires< IncidenceGraphConcept >(); + BOOST_CONCEPT_ASSERT(( IncidenceGraphConcept )); typedef adjacency_graph_archetype Graph2; - function_requires< AdjacencyGraphConcept >(); + BOOST_CONCEPT_ASSERT(( AdjacencyGraphConcept )); typedef vertex_list_graph_archetype Graph3; - function_requires< VertexListGraphConcept >(); + BOOST_CONCEPT_ASSERT(( VertexListGraphConcept )); - function_requires< ColorValueConcept >(); + BOOST_CONCEPT_ASSERT(( ColorValueConcept )); typedef incidence_graph_archetype G; typedef property_graph_archetype Graph4; - function_requires< PropertyGraphConcept >(); + BOOST_CONCEPT_ASSERT(( PropertyGraphConcept )); return 0; } diff --git a/test/grid_graph_cc.cpp b/test/grid_graph_cc.cpp index 6c7d76a33..a9e1c808f 100644 --- a/test/grid_graph_cc.cpp +++ b/test/grid_graph_cc.cpp @@ -10,6 +10,7 @@ #include #include #include +#include #define DIMENSIONS 3 using namespace boost; @@ -20,14 +21,14 @@ int main (int, char*[]) { typedef graph_traits::vertex_descriptor Vertex; typedef graph_traits::edge_descriptor Edge; - function_requires >(); - function_requires >(); - function_requires >(); - function_requires >(); - function_requires >(); - function_requires >(); - function_requires >(); - function_requires >(); + BOOST_CONCEPT_ASSERT((BidirectionalGraphConcept )); + BOOST_CONCEPT_ASSERT((VertexListGraphConcept )); + BOOST_CONCEPT_ASSERT((EdgeListGraphConcept )); + BOOST_CONCEPT_ASSERT((IncidenceGraphConcept )); + BOOST_CONCEPT_ASSERT((AdjacencyGraphConcept )); + BOOST_CONCEPT_ASSERT((AdjacencyMatrixConcept )); + BOOST_CONCEPT_ASSERT((ReadablePropertyGraphConcept )); + BOOST_CONCEPT_ASSERT((ReadablePropertyGraphConcept )); return (0); } diff --git a/test/leda_graph_cc.cpp b/test/leda_graph_cc.cpp index 40fafcf5c..389985162 100644 --- a/test/leda_graph_cc.cpp +++ b/test/leda_graph_cc.cpp @@ -8,7 +8,7 @@ //======================================================================= #include #include - +#include int main(int,char*[]) @@ -18,21 +18,21 @@ main(int,char*[]) typedef leda::GRAPH Graph; typedef graph_traits::vertex_descriptor Vertex; typedef graph_traits::edge_descriptor Edge; - function_requires< VertexListGraphConcept >(); - function_requires< BidirectionalGraphConcept >(); - function_requires< AdjacencyGraphConcept >(); - function_requires< VertexMutableGraphConcept >(); - function_requires< EdgeMutableGraphConcept >(); - function_requires< VertexMutablePropertyGraphConcept >(); - function_requires< EdgeMutablePropertyGraphConcept >(); - function_requires< - ReadablePropertyGraphConcept >(); - function_requires< - ReadablePropertyGraphConcept >(); - function_requires< - LvaluePropertyGraphConcept >(); - function_requires< - LvaluePropertyGraphConcept >(); + BOOST_CONCEPT_ASSERT(( VertexListGraphConcept )); + BOOST_CONCEPT_ASSERT(( BidirectionalGraphConcept )); + BOOST_CONCEPT_ASSERT(( AdjacencyGraphConcept )); + BOOST_CONCEPT_ASSERT(( VertexMutableGraphConcept )); + BOOST_CONCEPT_ASSERT(( EdgeMutableGraphConcept )); + BOOST_CONCEPT_ASSERT(( VertexMutablePropertyGraphConcept )); + BOOST_CONCEPT_ASSERT(( EdgeMutablePropertyGraphConcept )); + BOOST_CONCEPT_ASSERT(( + ReadablePropertyGraphConcept )); + BOOST_CONCEPT_ASSERT(( + ReadablePropertyGraphConcept )); + BOOST_CONCEPT_ASSERT(( + LvaluePropertyGraphConcept )); + BOOST_CONCEPT_ASSERT(( + LvaluePropertyGraphConcept )); } return 0; } diff --git a/test/read_propmap.cpp b/test/read_propmap.cpp index 3c0aa69a6..5e22fd443 100644 --- a/test/read_propmap.cpp +++ b/test/read_propmap.cpp @@ -6,6 +6,7 @@ #include #include +#include // Test contributed by Dmitry that validates a read-only property map bug // for bundled properties. @@ -24,7 +25,7 @@ int main() typedef property_map::type WeightMap; typedef property_map::const_type cWeightMap; typedef graph_traits::edge_descriptor Edge; - function_requires >(); - function_requires >(); + BOOST_CONCEPT_ASSERT((ReadablePropertyMapConcept )); + BOOST_CONCEPT_ASSERT((ReadablePropertyMapConcept )); return 0; } diff --git a/test/reverse_graph_cc.cpp b/test/reverse_graph_cc.cpp index 3032be5f6..eef53bf97 100644 --- a/test/reverse_graph_cc.cpp +++ b/test/reverse_graph_cc.cpp @@ -10,6 +10,7 @@ #include #include #include +#include #include int main(int,char*[]) @@ -23,12 +24,12 @@ int main(int,char*[]) property > AdjList; typedef reverse_graph Graph; - function_requires< VertexListGraphConcept >(); + BOOST_CONCEPT_ASSERT(( VertexListGraphConcept )); typedef graph_traits::vertex_descriptor Vertex; typedef graph_traits::edge_descriptor Edge; - function_requires< ReadablePropertyGraphConcept >(); - function_requires< ReadablePropertyGraphConcept >(); - function_requires< ReadablePropertyGraphConcept >(); + BOOST_CONCEPT_ASSERT(( ReadablePropertyGraphConcept )); + BOOST_CONCEPT_ASSERT(( ReadablePropertyGraphConcept )); + BOOST_CONCEPT_ASSERT(( ReadablePropertyGraphConcept )); AdjList g; Graph gr(g); get_property(gr, graph_name_t()); @@ -41,12 +42,12 @@ int main(int,char*[]) property > AdjList; typedef reverse_graph Graph; - function_requires< VertexListGraphConcept >(); + BOOST_CONCEPT_ASSERT(( VertexListGraphConcept )); typedef graph_traits::vertex_descriptor Vertex; typedef graph_traits::edge_descriptor Edge; - function_requires< PropertyGraphConcept >(); - function_requires< PropertyGraphConcept >(); - function_requires< ReadablePropertyGraphConcept >(); + BOOST_CONCEPT_ASSERT(( PropertyGraphConcept )); + BOOST_CONCEPT_ASSERT(( PropertyGraphConcept )); + BOOST_CONCEPT_ASSERT(( ReadablePropertyGraphConcept )); AdjList g; Graph gr(g); get_property(gr, graph_name_t()); diff --git a/test/stanford_graph_cc.cpp b/test/stanford_graph_cc.cpp index 1da24d646..c237fdb3e 100644 --- a/test/stanford_graph_cc.cpp +++ b/test/stanford_graph_cc.cpp @@ -9,6 +9,7 @@ #include #include #include +#include int main(int,char*[]) { @@ -18,28 +19,28 @@ int main(int,char*[]) typedef Graph* Graph; typedef graph_traits::vertex_descriptor Vertex; typedef graph_traits::edge_descriptor Edge; - function_requires< VertexListGraphConcept >(); - function_requires< IncidenceGraphConcept >(); - function_requires< AdjacencyGraphConcept >(); - function_requires< PropertyGraphConcept >(); - function_requires< - PropertyGraphConcept > >(); - function_requires< - PropertyGraphConcept > >(); + BOOST_CONCEPT_ASSERT(( VertexListGraphConcept )); + BOOST_CONCEPT_ASSERT(( IncidenceGraphConcept )); + BOOST_CONCEPT_ASSERT(( AdjacencyGraphConcept )); + BOOST_CONCEPT_ASSERT(( PropertyGraphConcept )); + BOOST_CONCEPT_ASSERT(( + PropertyGraphConcept > )); + BOOST_CONCEPT_ASSERT(( + PropertyGraphConcept > )); } { typedef const Graph* Graph; typedef graph_traits::vertex_descriptor Vertex; typedef graph_traits::edge_descriptor Edge; - function_requires< VertexListGraphConcept >(); - function_requires< IncidenceGraphConcept >(); - function_requires< AdjacencyGraphConcept >(); - function_requires< - ReadablePropertyGraphConcept >(); - function_requires< - ReadablePropertyGraphConcept > >(); - function_requires< - ReadablePropertyGraphConcept > >(); + BOOST_CONCEPT_ASSERT(( VertexListGraphConcept )); + BOOST_CONCEPT_ASSERT(( IncidenceGraphConcept )); + BOOST_CONCEPT_ASSERT(( AdjacencyGraphConcept )); + BOOST_CONCEPT_ASSERT(( + ReadablePropertyGraphConcept )); + BOOST_CONCEPT_ASSERT(( + ReadablePropertyGraphConcept > )); + BOOST_CONCEPT_ASSERT(( + ReadablePropertyGraphConcept > )); } return 0; } diff --git a/test/test_construction.hpp b/test/test_construction.hpp index 2f0939055..0243f6d2b 100644 --- a/test/test_construction.hpp +++ b/test/test_construction.hpp @@ -7,6 +7,7 @@ #ifndef TEST_CONSTRUCTION_HPP #define TEST_CONSTRUCTION_HPP +#include #include /** @name Build Graph diff --git a/test/test_destruction.hpp b/test/test_destruction.hpp index f6d8b14c7..8cdfa1b67 100644 --- a/test/test_destruction.hpp +++ b/test/test_destruction.hpp @@ -7,6 +7,7 @@ #ifndef TEST_DESTRUCTION_HPP #define TEST_DESTRUCTION_HPP +#include #include /** @name Destroy Graph @@ -36,7 +37,7 @@ template void destroy_graph(Graph& g, VertexSet const&, boost::mpl::false_, boost::mpl::true_) { using namespace boost; BOOST_CONCEPT_ASSERT((VertexListGraphConcept)); - // function_requires< VeretexMutableGraphConcept >(); + // BOOST_CONCEPT_ASSERT(( VeretexMutableGraphConcept )); std::cout << "...destroy_labeled\n"; // Remove the roof vertex diff --git a/test/test_direction.hpp b/test/test_direction.hpp index b2774b1af..1084c06b9 100644 --- a/test/test_direction.hpp +++ b/test/test_direction.hpp @@ -9,6 +9,7 @@ #include #include +#include /** @name Test Out-Directed Graph * Test all graphs that have directed out edges. diff --git a/test/test_graph.hpp b/test/test_graph.hpp index 481008b1a..f12230426 100644 --- a/test/test_graph.hpp +++ b/test/test_graph.hpp @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include diff --git a/test/test_iteration.hpp b/test/test_iteration.hpp index ce48e0d73..7842dd39c 100644 --- a/test/test_iteration.hpp +++ b/test/test_iteration.hpp @@ -7,6 +7,7 @@ #ifndef TEST_ITERATION_HPP #define TEST_ITERATION_HPP +#include #include /** @name Test Vertex List diff --git a/test/test_properties.hpp b/test/test_properties.hpp index 9c3d49796..adeb9ae10 100644 --- a/test/test_properties.hpp +++ b/test/test_properties.hpp @@ -7,6 +7,8 @@ #ifndef TEST_PROPERTIES_HPP #define TEST_PROPERTIES_HPP +#include + template T const& as_const(T& x) { return x; } template void ignore(T const&) { } diff --git a/test/vector_graph_cc.cpp b/test/vector_graph_cc.cpp index 7f7c5ebdb..f9b1cfac5 100644 --- a/test/vector_graph_cc.cpp +++ b/test/vector_graph_cc.cpp @@ -7,6 +7,7 @@ // http://www.boost.org/LICENSE_1_0.txt) //======================================================================= #include +#include #include #include @@ -24,9 +25,9 @@ int main(int,char*[]) // Check "vector as graph" { typedef std::vector< std::list > Graph; - function_requires< VertexListGraphConcept >(); - function_requires< IncidenceGraphConcept >(); - function_requires< AdjacencyGraphConcept >(); + BOOST_CONCEPT_ASSERT(( VertexListGraphConcept )); + BOOST_CONCEPT_ASSERT(( IncidenceGraphConcept )); + BOOST_CONCEPT_ASSERT(( AdjacencyGraphConcept )); } return 0; } From 99f7ed91aff0b9eb83f5da77454eaa50ca40f26b Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Tue, 20 Dec 2011 18:49:09 +0000 Subject: [PATCH 101/333] Applied patch from bug #6306; fixes #6306 [SVN r76083] --- include/boost/graph/reverse_graph.hpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/include/boost/graph/reverse_graph.hpp b/include/boost/graph/reverse_graph.hpp index b1dbc4247..6207a9539 100644 --- a/include/boost/graph/reverse_graph.hpp +++ b/include/boost/graph/reverse_graph.hpp @@ -269,13 +269,15 @@ vertex(const typename graph_traits::vertices_size_type v, } template -inline std::pair::edge_descriptor, - bool> +inline std::pair< typename graph_traits >::edge_descriptor, + bool> edge(const typename graph_traits::vertex_descriptor u, const typename graph_traits::vertex_descriptor v, const reverse_graph& g) { - return edge(v, u, g.m_g); + typedef typename graph_traits::edge_descriptor underlying_edge_descriptor; + std::pair e = edge(v, u, g.m_g); + return std::make_pair(detail::reverse_graph_edge_descriptor(e.first), e.second); } template From a439c4842572a0f0f2feb396ed243de3f3af743e Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Tue, 10 Jan 2012 01:29:38 +0000 Subject: [PATCH 102/333] Applied patch from #6371; fixes #6371 [SVN r76394] --- include/boost/graph/directed_graph.hpp | 2 +- include/boost/graph/undirected_graph.hpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/include/boost/graph/directed_graph.hpp b/include/boost/graph/directed_graph.hpp index 992546d46..0bf025190 100644 --- a/include/boost/graph/directed_graph.hpp +++ b/include/boost/graph/directed_graph.hpp @@ -410,7 +410,7 @@ template typename DIRECTED_GRAPH::vertex_descriptor vertex(typename DIRECTED_GRAPH::vertices_size_type n, DIRECTED_GRAPH const& g) -{ return vertex(g.impl()); } +{ return vertex(n, g.impl()); } template std::pair diff --git a/include/boost/graph/undirected_graph.hpp b/include/boost/graph/undirected_graph.hpp index d5374101e..3178b42af 100644 --- a/include/boost/graph/undirected_graph.hpp +++ b/include/boost/graph/undirected_graph.hpp @@ -413,7 +413,7 @@ template typename UNDIRECTED_GRAPH::vertex_descriptor vertex(typename UNDIRECTED_GRAPH::vertices_size_type n, UNDIRECTED_GRAPH const& g) -{ return vertex(g.impl()); } +{ return vertex(n, g.impl()); } template std::pair From f761059ecd05c87a9c321b6e9c400654d9a1a7db Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Thu, 12 Jan 2012 20:27:31 +0000 Subject: [PATCH 103/333] Applied some fixes from #6313; fixes #6313 [SVN r76439] --- include/boost/graph/reverse_graph.hpp | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/include/boost/graph/reverse_graph.hpp b/include/boost/graph/reverse_graph.hpp index 6207a9539..48c4e0576 100644 --- a/include/boost/graph/reverse_graph.hpp +++ b/include/boost/graph/reverse_graph.hpp @@ -124,8 +124,7 @@ class reverse_graph { typedef transform_iterator, typename Traits::out_edge_iterator> in_edge_iterator; // AdjacencyGraph requirements - typedef typename adjacency_iterator_generator::type adjacency_iterator; + typedef typename adjacency_iterator_generator::type adjacency_iterator; // VertexListGraph requirements typedef typename Traits::vertex_iterator vertex_iterator; @@ -149,7 +148,7 @@ class reverse_graph { typename detail::get_underlying_descriptor_from_reverse_descriptor::type >::type& operator[](Descriptor x) - { return detail::get_underlying_descriptor_from_reverse_descriptor::convert(m_g[x]); } + { return m_g[detail::get_underlying_descriptor_from_reverse_descriptor::convert(x)]; } template typename graph::detail::bundled_result< @@ -157,7 +156,7 @@ class reverse_graph { typename detail::get_underlying_descriptor_from_reverse_descriptor::type >::type const& operator[](Descriptor x) const - { return detail::get_underlying_descriptor_from_reverse_descriptor::convert(m_g[x]); } + { return m_g[detail::get_underlying_descriptor_from_reverse_descriptor::convert(x)]; } #endif // BOOST_GRAPH_NO_BUNDLED_PROPERTIES static vertex_descriptor null_vertex() @@ -354,7 +353,7 @@ namespace detail { put(m.underlying_pm, e.underlying_descx, v); } - reference operator[](const key_type& k) { + reference operator[](const key_type& k) const { return (this->underlying_pm)[k.underlying_descx]; } }; From 3af4b053be1c3279126058c57d0df9485955435e Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Thu, 19 Jan 2012 16:35:28 +0000 Subject: [PATCH 104/333] Fixed issue with printing const graphs [SVN r76588] --- include/boost/graph/adjacency_list_io.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/boost/graph/adjacency_list_io.hpp b/include/boost/graph/adjacency_list_io.hpp index 91b0b465d..30d87b107 100644 --- a/include/boost/graph/adjacency_list_io.hpp +++ b/include/boost/graph/adjacency_list_io.hpp @@ -248,7 +248,7 @@ struct PropertyPrinter > template PropertyPrinter& operator () ( std::ostream& out, const Val& v ) { - typename property_map::type ps = get(Tag(), *graph); + typename property_map::const_type ps = get(Tag(), *graph); out << ps[ v ] <<" "; PropertyPrinter print(*graph); print(out, v); From cddab52a7bfbd5324593e5d0916db89c534fd248 Mon Sep 17 00:00:00 2001 From: "K. Noel Belcourt" Date: Mon, 23 Jan 2012 02:52:23 +0000 Subject: [PATCH 105/333] Fix astar_search graph test. [SVN r76648] --- include/boost/graph/astar_search.hpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/include/boost/graph/astar_search.hpp b/include/boost/graph/astar_search.hpp index 316e70639..132dca021 100644 --- a/include/boost/graph/astar_search.hpp +++ b/include/boost/graph/astar_search.hpp @@ -158,6 +158,7 @@ namespace boost { template void tree_edge(Edge e, const Graph& g) { + using boost::get; m_decreased = relax(e, g, m_weight, m_predecessor, m_distance, m_combine, m_compare); @@ -173,6 +174,7 @@ namespace boost { template void gray_target(Edge e, const Graph& g) { + using boost::get; m_decreased = relax(e, g, m_weight, m_predecessor, m_distance, m_combine, m_compare); @@ -189,6 +191,7 @@ namespace boost { template void black_target(Edge e, const Graph& g) { + using boost::get; m_decreased = relax(e, g, m_weight, m_predecessor, m_distance, m_combine, m_compare); From e761a6b4d032e38245554303a29a83b7b9aa8de4 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Mon, 23 Jan 2012 16:07:05 +0000 Subject: [PATCH 106/333] Fixed typo from #6435 plus others; fixes #6435 [SVN r76651] --- doc/topology.html | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/doc/topology.html b/doc/topology.html index 24271c0c7..57f53e57c 100644 --- a/doc/topology.html +++ b/doc/topology.html @@ -124,8 +124,8 @@

        Summary

        struct point { point() { } - double& operator[](std::size_t i) {return values[i];} - const double& operator[](std::size_t i) const {return values[i];} + double& operator[](std::size_t i) {return values[i];} + const double& operator[](std::size_t i) const {return values[i];} private: double values[Dims]; @@ -157,7 +157,7 @@

        Summary

        { public: explicit hypercube_topology(double scaling = 1.0); - hypercube_topology(RandomNumberGenerator& gen, double scaling = 1.0); + hypercube_topology(RandomNumberGenerator& gen, double scaling = 1.0); point_type random_point() const; };
    3. @@ -173,13 +173,13 @@

      Summary

      { public: explicit square_topology(double scaling = 1.0); - square_topology(RandomNumberGenerator& gen, double scaling = 1.0); + square_topology(RandomNumberGenerator& gen, double scaling = 1.0); };

      Class template cube_topology

      -

      Class template cube_topology is a two-dimensional +

      Class template cube_topology is a three-dimensional hypercube topology.

      @@ -188,7 +188,7 @@ 

      Summary

      { public: explicit cube_topology(double scaling = 1.0); - cube_topology(RandomNumberGenerator& gen, double scaling = 1.0); + cube_topology(RandomNumberGenerator& gen, double scaling = 1.0); };
      @@ -209,7 +209,7 @@

      Summary

      { public: explicit ball_topology(double radius = 1.0); - ball_topology(RandomNumberGenerator& gen, double radius = 1.0); + ball_topology(RandomNumberGenerator& gen, double radius = 1.0); point_type random_point() const; }; @@ -225,13 +225,13 @@

      Summary

      { public: explicit circle_topology(double radius = 1.0); - circle_topology(RandomNumberGenerator& gen, double radius = 1.0); + circle_topology(RandomNumberGenerator& gen, double radius = 1.0); };

      Class template sphere_topology

      -

      Class template sphere_topology is a two-dimensional +

      Class template sphere_topology is a three-dimensional ball topology.

      @@ -240,7 +240,7 @@ 

      Summary

      { public: explicit sphere_topology(double radius = 1.0); - sphere_topology(RandomNumberGenerator& gen, double radius = 1.0); + sphere_topology(RandomNumberGenerator& gen, double radius = 1.0); };
      @@ -258,7 +258,7 @@

      Summary

      typedef unspecified point_type; heart_topology(); - heart_topology(RandomNumberGenerator& gen); + heart_topology(RandomNumberGenerator& gen); point_type random_point() const; double distance(point_type a, point_type b) const; point_type move_position_toward(point_type a, double fraction, point_type b) const; From 1c7c456e18488e769b2631a8a7333bc4a1ec4910 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Mon, 23 Jan 2012 19:57:42 +0000 Subject: [PATCH 107/333] Changed another property map type to const_type [SVN r76654] --- include/boost/graph/adjacency_list_io.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/boost/graph/adjacency_list_io.hpp b/include/boost/graph/adjacency_list_io.hpp index 30d87b107..547c02902 100644 --- a/include/boost/graph/adjacency_list_io.hpp +++ b/include/boost/graph/adjacency_list_io.hpp @@ -215,7 +215,7 @@ struct PropertyPrinter template PropertyPrinter& operator () ( std::ostream& out, const Val& v ) { - typename property_map::type ps = get(Tag(), *graph); + typename property_map::const_type ps = get(Tag(), *graph); out << ps[ v ] <<" "; PropertyPrinter print(*graph); print(out, v); From f63ebe9a8b77e8870d337edbdfcec21e038a7853 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Fri, 27 Jan 2012 22:06:21 +0000 Subject: [PATCH 108/333] Added example from David Doria [SVN r76726] --- doc/grid_graph.html | 2 +- example/Jamfile.v2 | 2 ++ example/grid_graph_properties.cpp | 40 +++++++++++++++++++++++++++++++ 3 files changed, 43 insertions(+), 1 deletion(-) create mode 100644 example/grid_graph_properties.cpp diff --git a/doc/grid_graph.html b/doc/grid_graph.html index bebbd1c27..100c97ecc 100644 --- a/doc/grid_graph.html +++ b/doc/grid_graph.html @@ -69,7 +69,7 @@

      Overview

      Defined in boost/graph/grid_graph.hpp - with all functions in the boost namespace. All examples are available in a single program file in libs/graph/example/grid_graph_example.cpp + with all functions in the boost namespace. A simple examples of creating and iterating over a grid_graph is available here libs/graph/example/grid_graph_example.cpp. An example of adding properties to a grid_graph is also available libs/graph/example/grid_graph_properties.cpp

      Template Parameters

      diff --git a/example/Jamfile.v2 b/example/Jamfile.v2 index fa7ebf9d6..5037ff68c 100644 --- a/example/Jamfile.v2 +++ b/example/Jamfile.v2 @@ -20,6 +20,7 @@ exe bron_kerbosch_print_cliques : bron_kerbosch_print_cliques.cpp ; exe bron_kerbosch_clique_number : bron_kerbosch_clique_number.cpp ; exe mcgregor_subgraphs_example : mcgregor_subgraphs_example.cpp ; exe grid_graph_example : grid_graph_example.cpp ; +exe grid_graph_properties : grid_graph_properties.cpp ; exe bipartite_example : bipartite_example.cpp ; exe fr_layout : fr_layout.cpp ; exe canonical_ordering : canonical_ordering.cpp ; @@ -33,3 +34,4 @@ exe stoer_wagner : stoer_wagner.cpp ; exe bfs-example : bfs-example.cpp ; exe bfs-example2 : bfs-example2.cpp ; exe dfs-example : dfs-example.cpp ; +exe adjacency_list_io : adjacency_list_io.cpp ; diff --git a/example/grid_graph_properties.cpp b/example/grid_graph_properties.cpp new file mode 100644 index 000000000..37d252a85 --- /dev/null +++ b/example/grid_graph_properties.cpp @@ -0,0 +1,40 @@ +//======================================================================= +// Copyright 2012 David Doria +// Authors: David Doria +// +// 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) +//======================================================================= + +#include +#include +#include + +int main(int argc, char* argv[]) +{ + // A 2D grid graph + typedef boost::grid_graph<2> GraphType; + + // Create a 5x5 graph + const unsigned int dimension = 5; + boost::array lengths = { { dimension, dimension } }; + GraphType graph(lengths); + + // Get the index map of the grid graph + typedef boost::property_map::const_type indexMapType; + indexMapType indexMap(get(boost::vertex_index, graph)); + + // Create a float for every node in the graph + boost::vector_property_map dataMap(num_vertices(graph), indexMap); + + // Associate the value 2.0 with the node at position (0,1) in the grid + boost::graph_traits::vertex_descriptor v = { { 0, 1 } }; + put(dataMap, v, 2.0f); + + // Get the data at the node at position (0,1) in the grid + float retrieved = get(dataMap, v); + std::cout << "Retrieved value: " << retrieved << std::endl; + + return 0; +} From a1fc58cc93c525455e191e832102de4a5e4f182a Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Sun, 29 Jan 2012 19:04:46 +0000 Subject: [PATCH 109/333] Added directed_graph stub documentation from David Doria [SVN r76778] --- doc/directed_graph.html | 95 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 95 insertions(+) create mode 100644 doc/directed_graph.html diff --git a/doc/directed_graph.html b/doc/directed_graph.html new file mode 100644 index 000000000..63c475610 --- /dev/null +++ b/doc/directed_graph.html @@ -0,0 +1,95 @@ + + + +Boost Graph Library: Directed Graph + +C++ Boost + +
      + +

      +
      +directed_graph<VertexProp, EdgeProp, GraphProp>
      +
      +

      + + +

      +The directed_graph class template is is a simplified version +of the BGL adjacency list. This class is provided for ease of use, but +may not perform as well as custom-defined adjacency list classes. Instances +of this template model the BidirectionalGraph, VertexIndexGraph, and +EdgeIndexGraph concepts. + +

      Example

      + +

      + + +

      +  typedef boost::directed_graph<> Graph;
      +  Graph g;
      +  Graph::vertex_descriptor v0 = g.add_vertex();
      +  Graph::vertex_descriptor v1 = g.add_vertex();
      +
      +  g.add_edge(v0, v1);
      +
      + +

      Template Parameters

      + +

      + + + + + + + + + + + + + + + + + + + + + +
      ParameterDescriptionDefault
      VertexPropA property map for the graph vertices. 
      EdgePropA property map for the graph edges. 
      GraphPropA property map for the graph itself.
      +

      + +

      Where Defined

      + +

      +boost/graph/directed_graph.hpp + +

      + +
      +


      + + +
      Copyright © 2000-2001 +Jeremy Siek, +Indiana University (jsiek@osl.iu.edu)
      +Lie-Quan Lee, Indiana University (llee@cs.indiana.edu)
      +Andrew Lumsdaine, +Indiana University (lums@osl.iu.edu) +
      + + + From 9d353c53e2831e4afd04d38a38f2436b4c18e2bd Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Sun, 29 Jan 2012 21:08:40 +0000 Subject: [PATCH 110/333] Added documentation and examples from David Doria [SVN r76779] --- doc/directed_graph.html | 96 +++++++++++++++++++ doc/undirected_graph.html | 96 +++++++++++++++++++ example/Jamfile.v2 | 3 + example/directed_graph.cpp | 26 +++++ ...cted.cpp => undirected_adjacency_list.cpp} | 0 ...ted => undirected_adjacency_list.expected} | 0 example/undirected_graph.cpp | 30 ++++++ 7 files changed, 251 insertions(+) create mode 100644 doc/undirected_graph.html create mode 100644 example/directed_graph.cpp rename example/{undirected.cpp => undirected_adjacency_list.cpp} (100%) rename example/{undirected.expected => undirected_adjacency_list.expected} (100%) create mode 100644 example/undirected_graph.cpp diff --git a/doc/directed_graph.html b/doc/directed_graph.html index 63c475610..d17038c40 100644 --- a/doc/directed_graph.html +++ b/doc/directed_graph.html @@ -1,4 +1,100 @@ + + +Boost Graph Library: Directed Graph + +C++ Boost + +
      + +

      +
      +directed_graph<VertexProp, EdgeProp, GraphProp>
      +
      +

      + + +

      +The directed_graph class template is is a simplified version +of the BGL adjacency list. This class is provided for ease of use, but +may not perform as well as custom-defined adjacency list classes. Instances +of this template model the BidirectionalGraph, VertexIndexGraph, and +EdgeIndexGraph concepts. + +

      Example

      + +A simple examples of creating a directed_graph is available here libs/graph/example/directed_graph.cpp. +

      + + +

      +  typedef boost::directed_graph<> Graph;
      +  Graph g;
      +  boost::graph_traits::vertex_descriptor v0 = g.add_vertex();
      +  boost::graph_traits::vertex_descriptor v1 = g.add_vertex();
      +
      +  g.add_edge(v0, v1);
      +
      + +

      Template Parameters

      + +

      + + + + + + + + + + + + + + + + + + + + + +
      ParameterDescriptionDefault
      VertexPropA property map for the graph vertices. 
      EdgePropA property map for the graph edges. 
      GraphPropA property map for the graph itself.
      +

      + +

      Where Defined

      + +

      +boost/graph/directed_graph.hpp + +

      + +
      +


      + + +
      Copyright © 2000-2001 +Jeremy Siek, +Indiana University (jsiek@osl.iu.edu)
      +Lie-Quan Lee, Indiana University (llee@cs.indiana.edu)
      +Andrew Lumsdaine, +Indiana University (lums@osl.iu.edu) +
      + + + + + +Boost Graph Library: Undirected Graph + +C++ Boost + +
      + +

      +
      +undirected_graph<VertexProp, EdgeProp, GraphProp>
      +
      +

      + + +

      +The undirected_graph class template is is a simplified version +of the BGL adjacency list. This class is provided for ease of use, but +may not perform as well as custom-defined adjacency list classes. Instances +of this template model the BidirectionalGraph, VertexIndexGraph, and +EdgeIndexGraph concepts. + +

      Example

      + +A simple example of creating an undirected_graph is available here libs/graph/example/undirected_graph.cpp +

      + + +

      +  typedef boost::undirected_graph<> Graph;
      +  Graph g;
      +  boost::graph_traits::vertex_descriptor v0 = g.add_vertex();
      +  boost::graph_traits::vertex_descriptor v1 = g.add_vertex();
      +
      +  g.add_edge(v0, v1);
      +
      + +

      Template Parameters

      + +

      + + + + + + + + + + + + + + + + + + + + + +
      ParameterDescriptionDefault
      VertexPropA property map for the graph vertices. 
      EdgePropA property map for the graph edges. 
      GraphPropA property map for the graph itself.
      +

      + +

      Where Defined

      + +

      +boost/graph/undirected_graph.hpp + +

      + +
      +


      + + +
      Copyright © 2000-2001 +Jeremy Siek, +Indiana University (jsiek@osl.iu.edu)
      +Lie-Quan Lee, Indiana University (llee@cs.indiana.edu)
      +Andrew Lumsdaine, +Indiana University (lums@osl.iu.edu) +
      + + + diff --git a/example/Jamfile.v2 b/example/Jamfile.v2 index 5037ff68c..ca46194a4 100644 --- a/example/Jamfile.v2 +++ b/example/Jamfile.v2 @@ -35,3 +35,6 @@ exe bfs-example : bfs-example.cpp ; exe bfs-example2 : bfs-example2.cpp ; exe dfs-example : dfs-example.cpp ; exe adjacency_list_io : adjacency_list_io.cpp ; +exe undirected_adjacency_list : undirected_adjacency_list.cpp ; +exe directed_graph : directed_graph.cpp ; +exe undirected_graph : undirected_graph.cpp ; diff --git a/example/directed_graph.cpp b/example/directed_graph.cpp new file mode 100644 index 000000000..bb308aa59 --- /dev/null +++ b/example/directed_graph.cpp @@ -0,0 +1,26 @@ +//======================================================================= +// Copyright 2012 +// Authors: David Doria +// +// 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) +//======================================================================= + +#include // A subclass to provide reasonable arguments to adjacency_list for a typical directed graph + +int main(int,char*[]) +{ + // directed_graph is a subclass of adjacency_list which gives you object oriented access to functions + // like add_vertex and add_edge, which makes the code easier to understand. However, it hard codes many + // of the template parameters, so it is much less flexible. + + typedef boost::directed_graph<> Graph; + Graph g; + boost::graph_traits::vertex_descriptor v0 = g.add_vertex(); + boost::graph_traits::vertex_descriptor v1 = g.add_vertex(); + + g.add_edge(v0, v1); + + return 0; +} diff --git a/example/undirected.cpp b/example/undirected_adjacency_list.cpp similarity index 100% rename from example/undirected.cpp rename to example/undirected_adjacency_list.cpp diff --git a/example/undirected.expected b/example/undirected_adjacency_list.expected similarity index 100% rename from example/undirected.expected rename to example/undirected_adjacency_list.expected diff --git a/example/undirected_graph.cpp b/example/undirected_graph.cpp new file mode 100644 index 000000000..d926c7b51 --- /dev/null +++ b/example/undirected_graph.cpp @@ -0,0 +1,30 @@ +//======================================================================= +// Copyright 2012 +// Authors: David Doria +// +// 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) +//======================================================================= + +#include +#include + +typedef boost::undirected_graph Graph; + +int main(int,char*[]) +{ + // Create a graph object + Graph g; + + // Add vertices + boost::graph_traits::vertex_descriptor v0 = g.add_vertex(); + boost::graph_traits::vertex_descriptor v1 = g.add_vertex(); + boost::graph_traits::vertex_descriptor v2 = g.add_vertex(); + + // Add edges + g.add_edge(v0, v1); + g.add_edge(v1, v2); + + return 0; +} From cd1186205d5cd140c29069d15f9f410b2f652895 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Sun, 29 Jan 2012 21:36:23 +0000 Subject: [PATCH 111/333] Added links sent by David Doria to his new documentation files [SVN r76783] --- doc/table_of_contents.html | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/doc/table_of_contents.html b/doc/table_of_contents.html index 6032e9ccf..090053bb5 100644 --- a/doc/table_of_contents.html +++ b/doc/table_of_contents.html @@ -101,6 +101,10 @@

      Table of Contents: the Boost Graph Library
    4. Graph classes
      1. adjacency_list
      2. +
          +
        1. directed_graph
        2. +
        3. undirected_graph
        4. +
      3. adjacency_matrix
      4. compressed_sparse_row_graph
    5. From b42b71824bf7c012fa694717f24899b9d41a8c2b Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Sat, 4 Feb 2012 05:12:04 +0000 Subject: [PATCH 112/333] Removed unused parameter names [SVN r76867] --- include/boost/graph/property_maps/null_property_map.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/boost/graph/property_maps/null_property_map.hpp b/include/boost/graph/property_maps/null_property_map.hpp index f6273481b..09ff55e34 100644 --- a/include/boost/graph/property_maps/null_property_map.hpp +++ b/include/boost/graph/property_maps/null_property_map.hpp @@ -29,7 +29,7 @@ namespace boost // The null_property_map only has a put() function. template - void put(null_property_map& pm, const K& key, const V& value) + void put(null_property_map& /*pm*/, const K& /*key*/, const V& /*value*/) { } // A helper function for intantiating null property maps. From cdef2804eae4ec1c24da5e8044b5913441bf6510 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Sat, 4 Feb 2012 05:12:58 +0000 Subject: [PATCH 113/333] Fixed incorrect iterator type [SVN r76868] --- include/boost/graph/vector_as_graph.hpp | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/include/boost/graph/vector_as_graph.hpp b/include/boost/graph/vector_as_graph.hpp index ee0df4bc9..c1799993c 100644 --- a/include/boost/graph/vector_as_graph.hpp +++ b/include/boost/graph/vector_as_graph.hpp @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include @@ -71,7 +72,7 @@ namespace boost { out_edge_iterator; typedef void in_edge_iterator; typedef void edge_iterator; - typedef typename integer_range::iterator vertex_iterator; + typedef counting_iterator vertex_iterator; typedef directed_tag directed_category; typedef allow_parallel_edge_tag edge_parallel_category; typedef vector_as_graph_traversal_tag traversal_category; @@ -178,14 +179,11 @@ namespace boost { // source() and target() already provided for pairs in graph_traits.hpp template - std::pair - ::iterator, - typename boost::integer_range - ::iterator > + std::pair, + boost::counting_iterator > vertices(const std::vector& v) { - typedef typename boost::integer_range - ::iterator Iter; + typedef boost::counting_iterator Iter; return std::make_pair(Iter(0), Iter(v.size())); } From 0a31d3c76bf29e3ab7b334a937af50dd12d80f84 Mon Sep 17 00:00:00 2001 From: Aaron Windsor Date: Tue, 14 Feb 2012 02:43:44 +0000 Subject: [PATCH 114/333] Correcting a doc bug: order of vertices on the outer face of a graph should have been reversed in planar_face_traversal example [SVN r77013] --- doc/planar_face_traversal.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/planar_face_traversal.html b/doc/planar_face_traversal.html index c52fa8b89..9a93799d6 100644 --- a/doc/planar_face_traversal.html +++ b/doc/planar_face_traversal.html @@ -97,7 +97,7 @@
      A plane drawing of a graph (left), and the 8 faces defined by the planar New face: 1 2 5 4 New face: 2 3 4 5 New face: 3 0 1 4 - New face: 2 3 0 1 + New face: 1 0 3 2

      Visitor Event Points

      From ce88df48fd4e34d95ac2a9e95d6c966146483918 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Sun, 19 Feb 2012 20:06:15 +0000 Subject: [PATCH 115/333] Changed property map uses to not use operator[] [SVN r77074] --- include/boost/graph/edmonds_karp_max_flow.hpp | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/include/boost/graph/edmonds_karp_max_flow.hpp b/include/boost/graph/edmonds_karp_max_flow.hpp index 43cc592d2..6aba1d059 100644 --- a/include/boost/graph/edmonds_karp_max_flow.hpp +++ b/include/boost/graph/edmonds_karp_max_flow.hpp @@ -52,21 +52,21 @@ namespace boost { // find minimum residual capacity along the augmenting path FlowValue delta = (std::numeric_limits::max)(); - e = p[sink]; + e = get(p, sink); do { BOOST_USING_STD_MIN(); - delta = min BOOST_PREVENT_MACRO_SUBSTITUTION(delta, residual_capacity[e]); + delta = min BOOST_PREVENT_MACRO_SUBSTITUTION(delta, get(residual_capacity, e)); u = source(e, g); - e = p[u]; + e = get(p, u); } while (u != src); // push delta units of flow along the augmenting path - e = p[sink]; + e = get(p, sink); do { - residual_capacity[e] -= delta; - residual_capacity[reverse_edge[e]] += delta; + put(residual_capacity, e, get(residual_capacity, e) - delta); + put(residual_capacity, get(reverse_edge, e), get(residual_capacity, get(reverse_edge, e)) + delta); u = source(e, g); - e = p[u]; + e = get(p, u); } while (u != src); } @@ -94,22 +94,22 @@ namespace boost { typename graph_traits::out_edge_iterator ei, e_end; for (boost::tie(u_iter, u_end) = vertices(g); u_iter != u_end; ++u_iter) for (boost::tie(ei, e_end) = out_edges(*u_iter, g); ei != e_end; ++ei) - res[*ei] = cap[*ei]; + put(res, *ei, get(cap, *ei)); - color[sink] = Color::gray(); - while (color[sink] != Color::white()) { + put(color, sink, Color::gray()); + while (get(color, sink) != Color::white()) { boost::queue Q; breadth_first_search (detail::residual_graph(g, res), src, Q, make_bfs_visitor(record_edge_predecessors(pred, on_tree_edge())), color); - if (color[sink] != Color::white()) + if (get(color, sink) != Color::white()) detail::augment(g, src, sink, pred, res, rev); } // while typename property_traits::value_type flow = 0; for (boost::tie(ei, e_end) = out_edges(src, g); ei != e_end; ++ei) - flow += (cap[*ei] - res[*ei]); + flow += (get(cap, *ei) - get(res, *ei)); return flow; } // edmonds_karp_max_flow() From 2d41bea1c8d373beb81c4bdf9c79d105989d79a9 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Sat, 3 Mar 2012 18:56:40 +0000 Subject: [PATCH 116/333] Fixed typo in documentation; fixes #6583 [SVN r77182] --- doc/DijkstraVisitor.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/DijkstraVisitor.html b/doc/DijkstraVisitor.html index e8c8c6c90..1f25bc84b 100644 --- a/doc/DijkstraVisitor.html +++ b/doc/DijkstraVisitor.html @@ -80,7 +80,7 @@

      Notation

      w -An object of type DistanceMap. +An object of type WeightMap. From c1b4a409a5ca786c6c163a961e9b0d652b712e99 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Sat, 3 Mar 2012 20:02:27 +0000 Subject: [PATCH 117/333] Changed to trampolined implementation of match() to avoid stack overflows, now passes test case in #6573 with 10000 sides; fixes #6573 [SVN r77185] --- include/boost/graph/isomorphism.hpp | 135 +++++++++++++++++++--------- 1 file changed, 95 insertions(+), 40 deletions(-) diff --git a/include/boost/graph/isomorphism.hpp b/include/boost/graph/isomorphism.hpp index bbdd1f7b4..f8e448675 100644 --- a/include/boost/graph/isomorphism.hpp +++ b/include/boost/graph/isomorphism.hpp @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -195,69 +196,123 @@ namespace boost { } private: + struct match_continuation { + enum {pos_G2_vertex_loop, pos_fi_adj_loop, pos_dfs_num} position; + typedef typename graph_traits::vertex_iterator vertex_iterator; + std::pair G2_verts; + typedef typename graph_traits::adjacency_iterator adjacency_iterator; + std::pair fi_adj; + edge_iter iter; + int dfs_num_k; + }; + bool match(edge_iter iter, int dfs_num_k) { + std::vector k; + typedef typename graph_traits::vertex_iterator vertex_iterator; + std::pair G2_verts(vertices(G2)); + typedef typename graph_traits::adjacency_iterator adjacency_iterator; + std::pair fi_adj; + vertex1_t i, j; + + recur: if (iter != ordered_edges.end()) { - vertex1_t i = source(*iter, G1), j = target(*iter, G2); + i = source(*iter, G1); + j = target(*iter, G2); if (dfs_num[i] > dfs_num_k) { - vertex1_t kp1 = dfs_vertices[dfs_num_k + 1]; - BGL_FORALL_VERTICES_T(u, G2, Graph2) { - if (invariant1(kp1) == invariant2(u) && in_S[u] == false) { - f[kp1] = u; - in_S[u] = true; - num_edges_on_k = 0; - - if (match(iter, dfs_num_k + 1)) -#if 0 - // dwa 2003/7/11 -- this *HAS* to be a bug! - ; -#endif - return true; + G2_verts = vertices(G2); + while (G2_verts.first != G2_verts.second) { + { + vertex2_t u = *G2_verts.first; + vertex1_t kp1 = dfs_vertices[dfs_num_k + 1]; + if (invariant1(kp1) == invariant2(u) && in_S[u] == false) { + { + f[kp1] = u; + in_S[u] = true; + num_edges_on_k = 0; - in_S[u] = false; + match_continuation new_k; + new_k.position = match_continuation::pos_G2_vertex_loop; + new_k.G2_verts = G2_verts; + new_k.iter = iter; + new_k.dfs_num_k = dfs_num_k; + k.push_back(new_k); + ++dfs_num_k; + goto recur; + } + } } +G2_loop_k: ++G2_verts.first; } } else if (dfs_num[j] > dfs_num_k) { - vertex1_t k = dfs_vertices[dfs_num_k]; - num_edges_on_k -= - count_if(adjacent_vertices(f[k], G2), make_indirect_pmap(in_S)); - - for (int jj = 0; jj < dfs_num_k; ++jj) { - vertex1_t j = dfs_vertices[jj]; - num_edges_on_k -= count(adjacent_vertices(f[j], G2), f[k]); + { + vertex1_t vk = dfs_vertices[dfs_num_k]; + num_edges_on_k -= + count_if(adjacent_vertices(f[vk], G2), make_indirect_pmap(in_S)); + + for (int jj = 0; jj < dfs_num_k; ++jj) { + vertex1_t j = dfs_vertices[jj]; + num_edges_on_k -= count(adjacent_vertices(f[j], G2), f[vk]); + } } if (num_edges_on_k != 0) - return false; - BGL_FORALL_ADJ_T(f[i], v, G2, Graph2) - if (invariant2(v) == invariant1(j) && in_S[v] == false) { - f[j] = v; - in_S[v] = true; - num_edges_on_k = 1; - BOOST_USING_STD_MAX(); - int next_k = max BOOST_PREVENT_MACRO_SUBSTITUTION(dfs_num_k, max BOOST_PREVENT_MACRO_SUBSTITUTION(dfs_num[i], dfs_num[j])); - if (match(boost::next(iter), next_k)) - return true; - in_S[v] = false; + goto return_point_false; + fi_adj = adjacent_vertices(f[i], G2); + while (fi_adj.first != fi_adj.second) { + { + vertex2_t v = *fi_adj.first; + if (invariant2(v) == invariant1(j) && in_S[v] == false) { + f[j] = v; + in_S[v] = true; + num_edges_on_k = 1; + BOOST_USING_STD_MAX(); + int next_k = max BOOST_PREVENT_MACRO_SUBSTITUTION(dfs_num_k, max BOOST_PREVENT_MACRO_SUBSTITUTION(dfs_num[i], dfs_num[j])); + match_continuation new_k; + new_k.position = match_continuation::pos_fi_adj_loop; + new_k.fi_adj = fi_adj; + new_k.iter = iter; + new_k.dfs_num_k = dfs_num_k; + ++iter; + dfs_num_k = next_k; + k.push_back(new_k); + goto recur; + } } - - +fi_adj_loop_k:++fi_adj.first; + } } else { if (container_contains(adjacent_vertices(f[i], G2), f[j])) { ++num_edges_on_k; - if (match(boost::next(iter), dfs_num_k)) - return true; + match_continuation new_k; + new_k.position = match_continuation::pos_dfs_num; + k.push_back(new_k); + ++iter; + goto recur; } } } else - return true; - return false; - } + goto return_point_true; + goto return_point_false; + { + return_point_true: return true; + + return_point_false: + if (k.empty()) return false; + const match_continuation& this_k = k.back(); + switch (this_k.position) { + case match_continuation::pos_G2_vertex_loop: {G2_verts = this_k.G2_verts; iter = this_k.iter; dfs_num_k = this_k.dfs_num_k; k.pop_back(); in_S[*G2_verts.first] = false; i = source(*iter, G1); j = target(*iter, G2); goto G2_loop_k;} + case match_continuation::pos_fi_adj_loop: {fi_adj = this_k.fi_adj; iter = this_k.iter; dfs_num_k = this_k.dfs_num_k; k.pop_back(); in_S[*fi_adj.first] = false; i = source(*iter, G1); j = target(*iter, G2); goto fi_adj_loop_k;} + case match_continuation::pos_dfs_num: {k.pop_back(); goto return_point_false;} + default: assert (!"Bad position"); abort(); + } + } + } }; From 761f792ed4602df194e1547b3a837cc1dc28e7b8 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Sat, 3 Mar 2012 20:06:15 +0000 Subject: [PATCH 118/333] Applied new patch from #6033 from Jan Hazla; fixes #6033 [SVN r77186] --- .../boost/graph/biconnected_components.hpp | 74 ++++++++++--------- 1 file changed, 41 insertions(+), 33 deletions(-) diff --git a/include/boost/graph/biconnected_components.hpp b/include/boost/graph/biconnected_components.hpp index 9586f9a21..0fdbad0d2 100644 --- a/include/boost/graph/biconnected_components.hpp +++ b/include/boost/graph/biconnected_components.hpp @@ -28,17 +28,23 @@ namespace boost { template struct biconnected_components_visitor : public dfs_visitor<> { biconnected_components_visitor - (ComponentMap comp, std::size_t& c, DiscoverTimeMap dtm, + (ComponentMap comp, std::size_t& c, + std::size_t& children_of_root, DiscoverTimeMap dtm, std::size_t& dfs_time, LowPointMap lowpt, PredecessorMap pred, - OutputIterator out, Stack& S, DFSVisitor vis) - : comp(comp), c(c), children_of_root(0), dtm(dtm), - dfs_time(dfs_time), lowpt(lowpt), - pred(pred), out(out), S(S), vis(vis) { } + OutputIterator out, Stack& S, + ArticulationVector& is_articulation_point, IndexMap index_map, + DFSVisitor vis) + : comp(comp), c(c), children_of_root(children_of_root), + dtm(dtm), dfs_time(dfs_time), lowpt(lowpt), + pred(pred), out(out), S(S), + is_articulation_point(is_articulation_point), + index_map(index_map), vis(vis) { } template void initialize_vertex(const Vertex& u, Graph& g) @@ -89,8 +95,7 @@ namespace boost typename boost::graph_traits::vertex_descriptor src = source(e, g); typename boost::graph_traits::vertex_descriptor tgt = target(e, g); - if ( ( tgt != get(pred, src) || get(pred, src) == src ) && - get(dtm, tgt) < get(dtm, src) ) { + if ( tgt != get(pred, src) ) { S.push(e); put(lowpt, src, min BOOST_PREVENT_MACRO_SUBSTITUTION(get(lowpt, src), @@ -111,40 +116,41 @@ namespace boost BOOST_USING_STD_MIN(); Vertex parent = get(pred, u); if (parent == u) { // Root of tree is special - if (children_of_root >= 2) { - *out++ = u; - } - return; - } - put(lowpt, parent, - min BOOST_PREVENT_MACRO_SUBSTITUTION(get(lowpt, parent), + is_articulation_point[get(index_map, u)] = (children_of_root > 1); + } else { + put(lowpt, parent, + min BOOST_PREVENT_MACRO_SUBSTITUTION(get(lowpt, parent), get(lowpt, u))); - if ( get(lowpt, u) >= get(dtm, parent) ) { - if ( get(pred, parent) != parent ) { - *out++ = parent; - } - while ( get(dtm, source(S.top(), g)) >= get(dtm, u) ) { + if ( get(lowpt, u) >= get(dtm, parent) ) { + is_articulation_point[get(index_map, parent)] = true; + while ( get(dtm, source(S.top(), g)) >= get(dtm, u) ) { + put(comp, S.top(), c); + S.pop(); + } + assert (source(S.top(), g) == parent); + assert (target(S.top(), g) == u); put(comp, S.top(), c); S.pop(); + ++c; } - assert (source(S.top(), g) == parent); - assert (target(S.top(), g) == u); - put(comp, S.top(), c); - S.pop(); - ++c; + } + if ( is_articulation_point[get(index_map, u)] ) { + *out++ = u; } vis.finish_vertex(u, g); } ComponentMap comp; std::size_t& c; - std::size_t children_of_root; + std::size_t& children_of_root; DiscoverTimeMap dtm; std::size_t& dfs_time; LowPointMap lowpt; PredecessorMap pred; OutputIterator out; Stack& S; + ArticulationVector& is_articulation_point; + IndexMap index_map; DFSVisitor vis; }; @@ -168,14 +174,16 @@ namespace boost vertex_t> )); std::size_t num_components = 0; + std::size_t children_of_root; std::size_t dfs_time = 0; - std::stack S; - - biconnected_components_visitor, - DFSVisitor> - vis(comp, num_components, dtm, dfs_time, lowpt, pred, out, - S, dfs_vis); + std::stack S; + std::vector is_articulation_point(num_vertices(g)); + + biconnected_components_visitor, + std::vector, VertexIndexMap, DFSVisitor> + vis(comp, num_components, children_of_root, dtm, dfs_time, + lowpt, pred, out, S, is_articulation_point, index_map, dfs_vis); depth_first_search(g, visitor(vis).vertex_index_map(index_map)); From fdc5f76aca93712f8fc8cffe0a884f5ca9ef97cc Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Sat, 3 Mar 2012 21:18:22 +0000 Subject: [PATCH 119/333] Fixed use of non-existent member [SVN r77187] --- include/boost/graph/compressed_sparse_row_graph.hpp | 1 - 1 file changed, 1 deletion(-) diff --git a/include/boost/graph/compressed_sparse_row_graph.hpp b/include/boost/graph/compressed_sparse_row_graph.hpp index caa27a906..75e61659d 100644 --- a/include/boost/graph/compressed_sparse_row_graph.hpp +++ b/include/boost/graph/compressed_sparse_row_graph.hpp @@ -1134,7 +1134,6 @@ add_vertices(typename BOOST_DIR_CSR_GRAPH_TYPE::vertices_size_type count, BOOST_ Vertex old_num_verts_plus_one = g.m_forward.m_rowstart.size(); EdgeIndex numedges = g.m_forward.m_rowstart.back(); g.m_forward.m_rowstart.resize(old_num_verts_plus_one + count, numedges); - g.m_backward.m_rowstart.resize(old_num_verts_plus_one + count, numedges); g.vertex_properties().resize(num_vertices(g)); return old_num_verts_plus_one - 1; } From e7d2639f6efb04feefdac1241e1be87f42bad9a8 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Sat, 3 Mar 2012 21:19:03 +0000 Subject: [PATCH 120/333] Added finish call to mutate_graph [SVN r77188] --- include/boost/graph/detail/read_graphviz_spirit.hpp | 4 +++- src/read_graphviz_new.cpp | 1 + 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/include/boost/graph/detail/read_graphviz_spirit.hpp b/include/boost/graph/detail/read_graphviz_spirit.hpp index 4e8b22e5e..994646988 100644 --- a/include/boost/graph/detail/read_graphviz_spirit.hpp +++ b/include/boost/graph/detail/read_graphviz_spirit.hpp @@ -604,7 +604,9 @@ bool read_graphviz_spirit(MultiPassIterator begin, MultiPassIterator end, scanner_t scan(begin, end, policies); - return p.parse(scan); + bool ok = p.parse(scan); + m_graph.finish_building_graph(); + return ok; } } // namespace boost diff --git a/src/read_graphviz_new.cpp b/src/read_graphviz_new.cpp index 130a112c2..6c6608c7b 100644 --- a/src/read_graphviz_new.cpp +++ b/src/read_graphviz_new.cpp @@ -787,6 +787,7 @@ namespace read_graphviz_detail { for (properties::const_iterator i = root_graph_props.begin(); i != root_graph_props.end(); ++i) { mg->set_graph_property(i->first, i->second); } + mg->finish_building_graph(); } } // end namespace read_graphviz_detail From c49c05f5023b2753e20a057619197f1a66f3c904 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Sat, 3 Mar 2012 21:19:38 +0000 Subject: [PATCH 121/333] Tried to do read_graphviz for CSR; does not work but some infrastructure changed so it is being committed [SVN r77189] --- include/boost/graph/graphviz.hpp | 102 ++++++++++++++++++++++++ test/graphviz_test.cpp | 132 +++++++++++++++++++++++-------- 2 files changed, 202 insertions(+), 32 deletions(-) diff --git a/include/boost/graph/graphviz.hpp b/include/boost/graph/graphviz.hpp index 718220ffe..ac708e56f 100644 --- a/include/boost/graph/graphviz.hpp +++ b/include/boost/graph/graphviz.hpp @@ -25,10 +25,14 @@ #include #include #include +#include #include #include +#include #include #include +#include +#include namespace boost { @@ -713,6 +717,9 @@ class mutate_graph virtual void // RG: need new second parameter to support BGL subgraphs set_graph_property(const id_t& key, const id_t& value) = 0; + + virtual void + finish_building_graph() = 0; }; template @@ -781,6 +788,8 @@ class mutate_graph_impl : public mutate_graph put(key, dp_, &graph_, value); } + void finish_building_graph() {} + protected: MutableGraph& graph_; @@ -790,6 +799,99 @@ class mutate_graph_impl : public mutate_graph std::map bgl_edges; }; +template +class mutate_graph_impl > + : public mutate_graph +{ + // The first part of this is to make the code dependent on a template parameter. + BOOST_STATIC_ASSERT_MSG(sizeof(Directed) == 0, + "Graphviz loading for CSR graphs is broken"); + + typedef compressed_sparse_row_graph CSRGraph; + typedef typename graph_traits::vertices_size_type bgl_vertex_t; + typedef typename graph_traits::edges_size_type bgl_edge_t; + + public: + mutate_graph_impl(CSRGraph& graph, dynamic_properties& dp, + std::string node_id_prop) + : graph_(graph), dp_(dp), vertex_count(0), node_id_prop_(node_id_prop) { } + + ~mutate_graph_impl() {} + + void finish_building_graph() { + CSRGraph temp(edges_are_unsorted, edges.begin(), edges.end(), vertex_count); + set_property(temp, graph_all, get_property(graph_, graph_all)); + graph_ = temp; + typedef tuple ve_prop; + BOOST_FOREACH(const ve_prop& t, vertex_and_edge_props) { + put(get<0>(t), dp_, get<1>(t), get<2>(t)); + } + } + + 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 = vertex_count++; + + // 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. + vertex_and_edge_props.push_back(make_tuple(node_id_prop_, v, node)); + } + + void + do_add_edge(const edge_t& edge, const node_t& source, const node_t& target) + { + bgl_edge_t result = edges.size(); + edges.push_back(std::make_pair(bgl_nodes[source], bgl_nodes[target])); + bgl_edges.insert(std::make_pair(edge, result)); + } + + void + set_node_property(const id_t& key, const node_t& node, const id_t& value) + { + vertex_and_edge_props.push_back(make_tuple(key, bgl_nodes[node], value)); + } + + void + set_edge_property(const id_t& key, const edge_t& edge, const id_t& value) + { + vertex_and_edge_props.push_back(make_tuple(key, 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: + CSRGraph& graph_; + dynamic_properties& dp_; + bgl_vertex_t vertex_count; + std::string node_id_prop_; + std::vector > vertex_and_edge_props; + std::vector > edges; + std::map bgl_nodes; + std::map bgl_edges; +}; + } } } // end namespace boost::detail::graph #ifdef BOOST_GRAPH_USE_SPIRIT_PARSER diff --git a/test/graphviz_test.cpp b/test/graphviz_test.cpp index 765175df1..dcf2667c4 100644 --- a/test/graphviz_test.cpp +++ b/test/graphviz_test.cpp @@ -17,6 +17,7 @@ #include #include #include +#include #include #include #include @@ -41,33 +42,49 @@ typedef std::pair edge_t; typedef std::map mass_map_t; typedef std::map weight_map_t; -template +template +bool test_graph(std::istream& dotfile, std::size_t correct_num_vertices, + mass_map_t const& masses, + weight_map_t const& weights, + std::string const& node_id = "node_id", + std::string const& g_name = std::string(), + NameMapKey name_map_key = boost::vertex_name, + MassMapKey mass_map_key = boost::vertex_color, + WeightMapKey weight_map_key = boost::edge_weight); + +template bool test_graph(std::istream& dotfile, std::size_t correct_num_vertices, mass_map_t const& masses, weight_map_t const& weights, std::string const& node_id = "node_id", std::string const& g_name = std::string()) { + return test_graph(dotfile, correct_num_vertices, masses, weights, node_id); +} + +template +bool test_graph(std::istream& dotfile, std::size_t correct_num_vertices, + mass_map_t const& masses, + weight_map_t const& weights, + std::string const& node_id = "node_id", + std::string const& g_name = std::string(), + NameMapKey name_map_key = boost::vertex_name, + MassMapKey mass_map_key = boost::vertex_color, + WeightMapKey weight_map_key = boost::edge_weight) { - typedef property < vertex_name_t, std::string, - property < vertex_color_t, float > > vertex_p; - typedef property < edge_weight_t, double > edge_p; - typedef property < graph_name_t, std::string > graph_p; - typedef adjacency_list < OutEdgeList, vecS, Directedness, - vertex_p, edge_p, graph_p > graph_t; typedef typename graph_traits < graph_t >::edge_descriptor edge_t; typedef typename graph_traits < graph_t >::vertex_descriptor vertex_t; // Construct a graph and set up the dynamic_property_maps. - graph_t graph(0); + graph_t graph; dynamic_properties dp(ignore_other_properties); - typename property_map::type name = - get(vertex_name, graph); + typename property_map::type name = + get(name_map_key, graph); dp.property(node_id,name); - typename property_map::type mass = - get(vertex_color, graph); + typename property_map::type mass = + get(mass_map_key, graph); dp.property("mass",mass); - typename property_map::type weight = - get(edge_weight, graph); + typename property_map::type weight = + get(weight_map_key, graph); dp.property("weight",weight); boost::ref_property_map gname( @@ -139,19 +156,31 @@ bool test_graph(std::istream& dotfile, std::size_t correct_num_vertices, typedef istringstream gs_t; + typedef property < vertex_name_t, std::string, + property < vertex_color_t, float > > vertex_p; + typedef property < edge_weight_t, double > edge_p; + typedef property < graph_name_t, std::string > graph_p; + + struct vertex_p_bundled {std::string name; float color;}; + struct edge_p_bundled {double weight;}; + // Basic directed graph tests BOOST_AUTO_TEST_CASE (basic_directed_graph_1) { mass_map_t masses; insert ( masses ) ("a",0.0f) ("c",7.7f) ("e", 6.66f); gs_t gs("digraph { a node [mass = 7.7] c e [mass = 6.66] }"); - BOOST_CHECK((test_graph(gs,3,masses,weight_map_t()))); + typedef adjacency_list < vecS, vecS, directedS, + vertex_p, edge_p, graph_p > graph_t; + BOOST_CHECK((test_graph(gs,3,masses,weight_map_t()))); } BOOST_AUTO_TEST_CASE (basic_directed_graph_2) { mass_map_t masses; insert ( masses ) ("a",0.0f) ("e", 6.66f); gs_t gs("digraph { a node [mass = 7.7] \"a\" e [mass = 6.66] }"); - BOOST_CHECK((test_graph(gs,2,masses,weight_map_t()))); + typedef adjacency_list < vecS, vecS, directedS, + vertex_p, edge_p, graph_p > graph_t; + BOOST_CHECK((test_graph(gs,2,masses,weight_map_t()))); } BOOST_AUTO_TEST_CASE (basic_directed_graph_3) { @@ -162,7 +191,9 @@ bool test_graph(std::istream& dotfile, std::size_t correct_num_vertices, gs_t gs("digraph { a -> b eDge [weight = 7.7] " "c -> d e-> f [weight = 6.66] " "d ->e->a [weight=.5]}"); - BOOST_CHECK((test_graph(gs,6,mass_map_t(),weights))); + typedef adjacency_list < vecS, vecS, directedS, + vertex_p, edge_p, graph_p > graph_t; + BOOST_CHECK((test_graph(gs,6,mass_map_t(),weights))); } // undirected graph with alternate node_id property name @@ -170,8 +201,10 @@ bool test_graph(std::istream& dotfile, std::size_t correct_num_vertices, mass_map_t masses; insert ( masses ) ("a",0.0f) ("c",7.7f) ("e", 6.66f); gs_t gs("graph { a node [mass = 7.7] c e [mass = 6.66] }"); - BOOST_CHECK((test_graph(gs,3,masses,weight_map_t(), - "nodenames"))); + typedef adjacency_list < vecS, vecS, undirectedS, + vertex_p, edge_p, graph_p > graph_t; + BOOST_CHECK((test_graph(gs,3,masses,weight_map_t(), + "nodenames"))); } // Basic undirected graph tests @@ -179,7 +212,9 @@ bool test_graph(std::istream& dotfile, std::size_t correct_num_vertices, mass_map_t masses; insert ( masses ) ("a",0.0f) ("c",7.7f) ("e", 6.66f); gs_t gs("graph { a node [mass = 7.7] c e [mass =\\\n6.66] }"); - BOOST_CHECK((test_graph(gs,3,masses,weight_map_t()))); + typedef adjacency_list < vecS, vecS, undirectedS, + vertex_p, edge_p, graph_p > graph_t; + BOOST_CHECK((test_graph(gs,3,masses,weight_map_t()))); } BOOST_AUTO_TEST_CASE (basic_undirected_graph_2) { @@ -188,7 +223,9 @@ bool test_graph(std::istream& dotfile, std::size_t correct_num_vertices, (make_pair("c","d"),7.7)(make_pair("e","f"),6.66); gs_t gs("graph { a -- b eDge [weight = 7.7] " "c -- d e -- f [weight = 6.66] }"); - BOOST_CHECK((test_graph(gs,6,mass_map_t(),weights))); + typedef adjacency_list < vecS, vecS, undirectedS, + vertex_p, edge_p, graph_p > graph_t; + BOOST_CHECK((test_graph(gs,6,mass_map_t(),weights))); } // Mismatch directed graph test @@ -197,7 +234,9 @@ bool test_graph(std::istream& dotfile, std::size_t correct_num_vertices, insert ( masses ) ("a",0.0f) ("c",7.7f) ("e", 6.66f); gs_t gs("graph { a nodE [mass = 7.7] c e [mass = 6.66] }"); try { - test_graph(gs,3,masses,weight_map_t()); + typedef adjacency_list < vecS, vecS, directedS, + vertex_p, edge_p, graph_p > graph_t; + test_graph(gs,3,masses,weight_map_t()); BOOST_ERROR("Failed to throw boost::undirected_graph_error."); } catch (boost::undirected_graph_error&) { } catch (boost::directed_graph_error&) { @@ -211,7 +250,9 @@ bool test_graph(std::istream& dotfile, std::size_t correct_num_vertices, insert ( masses ) ("a",0.0f) ("c",7.7f) ("e", 6.66f); gs_t gs("digraph { a node [mass = 7.7] c e [mass = 6.66] }"); try { - test_graph(gs,3,masses,weight_map_t()); + typedef adjacency_list < vecS, vecS, undirectedS, + vertex_p, edge_p, graph_p > graph_t; + test_graph(gs,3,masses,weight_map_t()); BOOST_ERROR("Failed to throw boost::directed_graph_error."); } catch (boost::directed_graph_error&) {} } @@ -223,7 +264,9 @@ bool test_graph(std::istream& dotfile, std::size_t correct_num_vertices, insert( weights )(make_pair("a","b"),7.7); gs_t gs("diGraph { a -> b [weight = 7.7] a -> b [weight = 7.7] }"); try { - test_graph(gs,2,mass_map_t(),weights); + typedef adjacency_list < setS, vecS, directedS, + vertex_p, edge_p, graph_p > graph_t; + test_graph(gs,2,mass_map_t(),weights); BOOST_ERROR("Failed to throw boost::bad_parallel_edge."); } catch (boost::bad_parallel_edge&) {} } @@ -233,7 +276,9 @@ bool test_graph(std::istream& dotfile, std::size_t correct_num_vertices, weight_map_t weights; insert( weights )(make_pair("a","b"),7.7); gs_t gs("digraph { a -> b [weight = 7.7] a -> b [weight = 7.7] }"); - BOOST_CHECK((test_graph(gs,2,mass_map_t(),weights))); + typedef adjacency_list < vecS, vecS, directedS, + vertex_p, edge_p, graph_p > graph_t; + BOOST_CHECK((test_graph(gs,2,mass_map_t(),weights))); } // Graph Property Test 1 @@ -242,8 +287,10 @@ bool test_graph(std::istream& dotfile, std::size_t correct_num_vertices, insert ( masses ) ("a",0.0f) ("c",0.0f) ("e", 6.66f); gs_t gs("digraph { graph [name=\"foo \\\"escaped\\\"\"] a c e [mass = 6.66] }"); std::string graph_name("foo \"escaped\""); - BOOST_CHECK((test_graph(gs,3,masses,weight_map_t(),"", - graph_name))); + typedef adjacency_list < vecS, vecS, directedS, + vertex_p, edge_p, graph_p > graph_t; + BOOST_CHECK((test_graph(gs,3,masses,weight_map_t(),"", + graph_name))); } // Graph Property Test 2 @@ -252,8 +299,10 @@ bool test_graph(std::istream& dotfile, std::size_t correct_num_vertices, insert ( masses ) ("a",0.0f) ("c",0.0f) ("e", 6.66f); gs_t gs("digraph { name=\"fo\"+ \"\\\no\" a c e [mass = 6.66] }"); std::string graph_name("foo"); - BOOST_CHECK((test_graph(gs,3,masses,weight_map_t(),"", - graph_name))); + typedef adjacency_list < vecS, vecS, directedS, + vertex_p, edge_p, graph_p > graph_t; + BOOST_CHECK((test_graph(gs,3,masses,weight_map_t(),"", + graph_name))); } // Graph Property Test 3 (HTML) @@ -262,8 +311,10 @@ bool test_graph(std::istream& dotfile, std::size_t correct_num_vertices, insert ( masses ) ("a",0.0f) ("c",0.0f) ("e", 6.66f); std::string graph_name = "foo]]>bar\n
      \nbaz"; gs_t gs("digraph { name=" + graph_name + " a c e [mass = 6.66] }"); - BOOST_CHECK((test_graph(gs,3,masses,weight_map_t(),"", - graph_name))); + typedef adjacency_list < vecS, vecS, directedS, + vertex_p, edge_p, graph_p > graph_t; + BOOST_CHECK((test_graph(gs,3,masses,weight_map_t(),"", + graph_name))); } // Comments embedded in strings @@ -274,7 +325,24 @@ bool test_graph(std::istream& dotfile, std::size_t correct_num_vertices, "a1 [ label = \"//depot/path/to/file_29#9\" ];" "a0 -> a1 [ color=gray ];" "}"); - BOOST_CHECK((test_graph(gs,2,mass_map_t(),weight_map_t()))); + typedef adjacency_list < vecS, vecS, directedS, + vertex_p, edge_p, graph_p > graph_t; + BOOST_CHECK((test_graph(gs,2,mass_map_t(),weight_map_t()))); } + +#if 0 // Currently broken + BOOST_AUTO_TEST_CASE (basic_csr_directed_graph) { + weight_map_t weights; + insert( weights )(make_pair("a","b"),0.0) + (make_pair("c","d"),7.7)(make_pair("e","f"),6.66) + (make_pair("d","e"),0.5)(make_pair("e","a"),0.5); + gs_t gs("digraph { a -> b eDge [weight = 7.7] " + "c -> d e-> f [weight = 6.66] " + "d ->e->a [weight=.5]}"); + typedef compressed_sparse_row_graph graph_t; + BOOST_CHECK((test_graph(gs,6,mass_map_t(),weights,"node_id","",&vertex_p_bundled::name,&vertex_p_bundled::color,&edge_p_bundled::weight))); + } +#endif + // return 0; // } From 5476d8d70af382486d4a9649cb29eafefe24ae37 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Sun, 4 Mar 2012 20:21:22 +0000 Subject: [PATCH 122/333] Made Graphviz reading into CSR graphs work for external properties only; refs #5442 [SVN r77222] --- include/boost/graph/graphviz.hpp | 41 ++++++++++++++--------- test/graphviz_test.cpp | 57 ++++++++++++++++++++------------ 2 files changed, 61 insertions(+), 37 deletions(-) diff --git a/include/boost/graph/graphviz.hpp b/include/boost/graph/graphviz.hpp index ac708e56f..3fc5b1cdb 100644 --- a/include/boost/graph/graphviz.hpp +++ b/include/boost/graph/graphviz.hpp @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include @@ -808,13 +809,10 @@ template > : public mutate_graph { - // The first part of this is to make the code dependent on a template parameter. - BOOST_STATIC_ASSERT_MSG(sizeof(Directed) == 0, - "Graphviz loading for CSR graphs is broken"); - typedef compressed_sparse_row_graph CSRGraph; typedef typename graph_traits::vertices_size_type bgl_vertex_t; typedef typename graph_traits::edges_size_type bgl_edge_t; + typedef typename graph_traits::edge_descriptor edge_descriptor; public: mutate_graph_impl(CSRGraph& graph, dynamic_properties& dp, @@ -824,13 +822,25 @@ class mutate_graph_impl TempCSRGraph; + TempCSRGraph temp(edges_are_unsorted_multi_pass, + edges_to_add.begin(), edges_to_add.end(), + counting_iterator(0), + vertex_count); set_property(temp, graph_all, get_property(graph_, graph_all)); - graph_ = temp; - typedef tuple ve_prop; - BOOST_FOREACH(const ve_prop& t, vertex_and_edge_props) { + graph_.assign(temp); // Copies structure, not properties + std::vector edge_permutation_from_sorting(num_edges(temp)); + BGL_FORALL_EDGES_T(e, temp, TempCSRGraph) { + edge_permutation_from_sorting[temp[e]] = e; + } + typedef tuple v_prop; + BOOST_FOREACH(const v_prop& t, vertex_props) { put(get<0>(t), dp_, get<1>(t), get<2>(t)); } + typedef tuple e_prop; + BOOST_FOREACH(const e_prop& t, edge_props) { + put(get<0>(t), dp_, edge_permutation_from_sorting[get<1>(t)], get<2>(t)); + } } bool is_directed() const @@ -850,27 +860,27 @@ class mutate_graph_impl > vertex_and_edge_props; - std::vector > edges; + std::vector > vertex_props; + std::vector > edge_props; + std::vector > edges_to_add; std::map bgl_nodes; std::map bgl_edges; }; diff --git a/test/graphviz_test.cpp b/test/graphviz_test.cpp index dcf2667c4..adc29034a 100644 --- a/test/graphviz_test.cpp +++ b/test/graphviz_test.cpp @@ -42,15 +42,16 @@ typedef std::pair edge_t; typedef std::map mass_map_t; typedef std::map weight_map_t; -template -bool test_graph(std::istream& dotfile, std::size_t correct_num_vertices, +template +bool test_graph(std::istream& dotfile, graph_t& graph, + std::size_t correct_num_vertices, mass_map_t const& masses, weight_map_t const& weights, - std::string const& node_id = "node_id", - std::string const& g_name = std::string(), - NameMapKey name_map_key = boost::vertex_name, - MassMapKey mass_map_key = boost::vertex_color, - WeightMapKey weight_map_key = boost::edge_weight); + std::string const& node_id, + std::string const& g_name, + NameMap name, + MassMap mass, + WeightMap weight); template bool test_graph(std::istream& dotfile, std::size_t correct_num_vertices, @@ -58,33 +59,29 @@ bool test_graph(std::istream& dotfile, std::size_t correct_num_vertices, weight_map_t const& weights, std::string const& node_id = "node_id", std::string const& g_name = std::string()) { - return test_graph(dotfile, correct_num_vertices, masses, weights, node_id); + graph_t g; + return test_graph(dotfile, g, correct_num_vertices, masses, weights, node_id, g_name, + get(vertex_name, g), get(vertex_color, g), get(edge_weight, g)); } -template -bool test_graph(std::istream& dotfile, std::size_t correct_num_vertices, +template +bool test_graph(std::istream& dotfile, graph_t& graph, + std::size_t correct_num_vertices, mass_map_t const& masses, weight_map_t const& weights, - std::string const& node_id = "node_id", - std::string const& g_name = std::string(), - NameMapKey name_map_key = boost::vertex_name, - MassMapKey mass_map_key = boost::vertex_color, - WeightMapKey weight_map_key = boost::edge_weight) { + std::string const& node_id, + std::string const& g_name, + NameMap name, + MassMap mass, + WeightMap weight) { typedef typename graph_traits < graph_t >::edge_descriptor edge_t; typedef typename graph_traits < graph_t >::vertex_descriptor vertex_t; // Construct a graph and set up the dynamic_property_maps. - graph_t graph; dynamic_properties dp(ignore_other_properties); - typename property_map::type name = - get(name_map_key, graph); dp.property(node_id,name); - typename property_map::type mass = - get(mass_map_key, graph); dp.property("mass",mass); - typename property_map::type weight = - get(weight_map_key, graph); dp.property("weight",weight); boost::ref_property_map gname( @@ -344,5 +341,21 @@ bool test_graph(std::istream& dotfile, std::size_t correct_num_vertices, } #endif + BOOST_AUTO_TEST_CASE (basic_csr_directed_graph_ext_props) { + weight_map_t weights; + insert( weights )(make_pair("a","b"),0.0) + (make_pair("c","d"),7.7)(make_pair("e","f"),6.66) + (make_pair("d","e"),0.5)(make_pair("e","a"),0.5); + gs_t gs("digraph { a -> b eDge [weight = 7.7] " + "c -> d e-> f [weight = 6.66] " + "d ->e->a [weight=.5]}"); + typedef compressed_sparse_row_graph graph_t; + graph_t g; + vector_property_map::const_type> vertex_name(get(vertex_index, g)); + vector_property_map::const_type> vertex_color(get(vertex_index, g)); + vector_property_map::const_type> edge_weight(get(edge_index, g)); + BOOST_CHECK((test_graph(gs,g,6,mass_map_t(),weights,"node_id","",vertex_name,vertex_color,edge_weight))); + } + // return 0; // } From 00ae7b7e728eeb29228002b547cc70fc24b1632e Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Sun, 4 Mar 2012 20:24:30 +0000 Subject: [PATCH 123/333] Applied patch from #6564; fixes #6564 [SVN r77223] --- include/boost/graph/subgraph.hpp | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/include/boost/graph/subgraph.hpp b/include/boost/graph/subgraph.hpp index b98c39026..35815b4b8 100644 --- a/include/boost/graph/subgraph.hpp +++ b/include/boost/graph/subgraph.hpp @@ -131,15 +131,29 @@ class subgraph { // copy constructor subgraph(const subgraph& x) - : m_graph(x.m_graph), m_parent(x.m_parent), m_edge_counter(x.m_edge_counter) + : m_parent(x.m_parent), m_edge_counter(x.m_edge_counter) , m_global_vertex(x.m_global_vertex), m_global_edge(x.m_global_edge) { - // Do a deep copy (recursive). - for(typename ChildrenList::const_iterator i = x.m_children.begin(); - i != x.m_children.end(); ++i) + if(x.is_root()) { - m_children.push_back(new subgraph( **i )); + m_graph = x.m_graph; } + // Do a deep copy (recursive). + // Only the root graph is copied, the subgraphs contain + // only references to the global vertices they own. + subgraph::children_iterator i,i_end; + boost::tie(i,i_end) = x.children(); + for(; i != i_end; ++i) + { + subgraph child = this->create_subgraph(); + child = *i; + vertex_iterator vi,vi_end; + boost::tie(vi,vi_end) = vertices(*i); + for (;vi!=vi_end;++vi) + { + add_vertex(*vi,child); + } + } } From fee51b8cdccc29c23fae034b7bede7b65e55d887 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Tue, 6 Mar 2012 16:23:53 +0000 Subject: [PATCH 124/333] Added typename; fixes #6656 [SVN r77248] --- include/boost/graph/subgraph.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/boost/graph/subgraph.hpp b/include/boost/graph/subgraph.hpp index 35815b4b8..1860c8ce7 100644 --- a/include/boost/graph/subgraph.hpp +++ b/include/boost/graph/subgraph.hpp @@ -141,7 +141,7 @@ class subgraph { // Do a deep copy (recursive). // Only the root graph is copied, the subgraphs contain // only references to the global vertices they own. - subgraph::children_iterator i,i_end; + typename subgraph::children_iterator i,i_end; boost::tie(i,i_end) = x.children(); for(; i != i_end; ++i) { From 908ebf506f1bdbdf5d4c442723c5068a2a8bd1f3 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Fri, 9 Mar 2012 02:19:01 +0000 Subject: [PATCH 125/333] Added range checking in asserts [SVN r77279] --- include/boost/graph/detail/histogram_sort.hpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/include/boost/graph/detail/histogram_sort.hpp b/include/boost/graph/detail/histogram_sort.hpp index b359a73de..e8fbadb83 100644 --- a/include/boost/graph/detail/histogram_sort.hpp +++ b/include/boost/graph/detail/histogram_sort.hpp @@ -60,6 +60,7 @@ count_starts // Put the degree of each vertex v into m_rowstart[v + 1] for (KeyIterator i = begin; i != end; ++i) { if (key_filter(*i)) { + assert (key_transform(*i) < numkeys); ++starts[key_transform(*i) + 1]; } } @@ -99,6 +100,7 @@ histogram_sort(KeyIterator key_begin, KeyIterator key_end, for (KeyIterator i = key_begin; i != key_end; ++i, ++v1i) { if (key_filter(*i)) { vertices_size_type source = key_transform(*i); + assert (source < numkeys); EdgeIndex insert_pos = current_insert_positions[source]; ++current_insert_positions[source]; values1_out[insert_pos] = *v1i; @@ -137,6 +139,7 @@ histogram_sort(KeyIterator key_begin, KeyIterator key_end, for (KeyIterator i = key_begin; i != key_end; ++i, ++v1i, ++v2i) { if (key_filter(*i)) { vertices_size_type source = key_transform(*i); + assert (source < numkeys); EdgeIndex insert_pos = current_insert_positions[source]; ++current_insert_positions[source]; values1_out[insert_pos] = *v1i; @@ -163,6 +166,7 @@ histogram_sort_inplace(KeyIterator key_begin, std::vector insert_positions(rowstart, rowstart + numkeys); // 2. Swap the sources and targets into place for (size_t i = 0; i < rowstart[numkeys]; ++i) { + assert (key_transform(key_begin[i]) < numkeys); // While edge i is not in the right bucket: while (!(i >= rowstart[key_transform(key_begin[i])] && i < insert_positions[key_transform(key_begin[i])])) { // Add a slot in the right bucket @@ -197,6 +201,7 @@ histogram_sort_inplace(KeyIterator key_begin, std::vector insert_positions(rowstart, rowstart + numkeys); // 2. Swap the sources and targets into place for (size_t i = 0; i < rowstart[numkeys]; ++i) { + assert (key_transform(key_begin[i]) < numkeys); // While edge i is not in the right bucket: while (!(i >= rowstart[key_transform(key_begin[i])] && i < insert_positions[key_transform(key_begin[i])])) { // Add a slot in the right bucket From 7cddb8febf082aae3a7c2121a376084da971d6cf Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Thu, 15 Mar 2012 17:39:14 +0000 Subject: [PATCH 126/333] Changed type of graph property keys to Graph* to match Graphviz reader code and test [SVN r77341] --- include/boost/graph/graphml.hpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/include/boost/graph/graphml.hpp b/include/boost/graph/graphml.hpp index 2239d9666..028cdc26c 100644 --- a/include/boost/graph/graphml.hpp +++ b/include/boost/graph/graphml.hpp @@ -262,7 +262,7 @@ write_graphml(std::ostream& out, const Graph& g, VertexIndexMap vertex_index, for (dynamic_properties::const_iterator i = dp.begin(); i != dp.end(); ++i) { std::string key_id = "key" + lexical_cast(key_count++); - if (i->second->key() == typeid(Graph)) + if (i->second->key() == typeid(Graph*)) graph_key_ids[i->first] = key_id; else if (i->second->key() == typeid(vertex_descriptor)) vertex_key_ids[i->first] = key_id; @@ -273,7 +273,7 @@ write_graphml(std::ostream& out, const Graph& g, VertexIndexMap vertex_index, std::string type_name = "string"; mpl::for_each(get_type_name(i->second->value(), type_names, type_name)); out << " second->key() == typeid(Graph) ? "graph" : (i->second->key() == typeid(vertex_descriptor) ? "node" : "edge")) << "\"" + << (i->second->key() == typeid(Graph*) ? "graph" : (i->second->key() == typeid(vertex_descriptor) ? "node" : "edge")) << "\"" << " attr.name=\"" << i->first << "\"" << " attr.type=\"" << type_name << "\"" << " />\n"; @@ -287,10 +287,12 @@ write_graphml(std::ostream& out, const Graph& g, VertexIndexMap vertex_index, // Output graph data for (dynamic_properties::const_iterator i = dp.begin(); i != dp.end(); ++i) { - if (i->second->key() == typeid(Graph)) + if (i->second->key() == typeid(Graph*)) { + // The const_cast here is just to get typeid correct for property + // map key; the graph should not be mutated using it. out << " first] << "\">" - << encode_char_entities(i->second->get_string(g)) << "\n"; + << encode_char_entities(i->second->get_string(const_cast(&g))) << "\n"; } } From a3d25c552115862b34794c1fa50540c2dd0bdc1b Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Mon, 19 Mar 2012 20:38:20 +0000 Subject: [PATCH 127/333] Added missing #include; fixes #6707 [SVN r77414] --- include/boost/graph/is_straight_line_drawing.hpp | 1 + 1 file changed, 1 insertion(+) diff --git a/include/boost/graph/is_straight_line_drawing.hpp b/include/boost/graph/is_straight_line_drawing.hpp index 74775b44f..d46e4fdfe 100644 --- a/include/boost/graph/is_straight_line_drawing.hpp +++ b/include/boost/graph/is_straight_line_drawing.hpp @@ -19,6 +19,7 @@ #include #include #include +#include From cae4628d7eae83a94ddfcac3015e0fe8f492d3e5 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Mon, 19 Mar 2012 20:48:42 +0000 Subject: [PATCH 128/333] Added "inline" to avoid multiple definition errors; fixes #6708 [SVN r77415] --- include/boost/graph/is_straight_line_drawing.hpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/include/boost/graph/is_straight_line_drawing.hpp b/include/boost/graph/is_straight_line_drawing.hpp index d46e4fdfe..161da4d12 100644 --- a/include/boost/graph/is_straight_line_drawing.hpp +++ b/include/boost/graph/is_straight_line_drawing.hpp @@ -35,12 +35,12 @@ namespace boost // defines how far away from the endpoints of s1 and s2 we want to consider // an intersection. - bool intersects(double x1, double y1, - double x2, double y2, - double a1, double b1, - double a2, double b2, - double epsilon = 0.000001 - ) + inline bool intersects(double x1, double y1, + double x2, double y2, + double a1, double b1, + double a2, double b2, + double epsilon = 0.000001 + ) { if (x1 - x2 == 0) From b838adfa32944b61f72865fdf398d3265111f9f7 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Sat, 24 Mar 2012 23:35:23 +0000 Subject: [PATCH 129/333] Fixed warnings [SVN r77523] --- include/boost/graph/johnson_all_pairs_shortest.hpp | 2 -- test/property_iter.cpp | 2 ++ 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/include/boost/graph/johnson_all_pairs_shortest.hpp b/include/boost/graph/johnson_all_pairs_shortest.hpp index 32e2b5cdc..b8da0fe19 100644 --- a/include/boost/graph/johnson_all_pairs_shortest.hpp +++ b/include/boost/graph/johnson_all_pairs_shortest.hpp @@ -121,8 +121,6 @@ namespace boost { (g2, *u, pred, d, w_hat, id2, compare, combine, inf, zero,dvis); for (boost::tie(v, v_end) = vertices(g2); v != v_end; ++v) { if (*u != s && *v != s) { - typename Traits1::vertex_descriptor u1, v1; - u1 = verts1[get(id2, *u)]; v1 = verts1[get(id2, *v)]; D[get(id2, *u)-1][get(id2, *v)-1] = combine(get(d, *v), (get(h, *v) - get(h, *u))); } } diff --git a/test/property_iter.cpp b/test/property_iter.cpp index 150061e9f..d206d2a7a 100644 --- a/test/property_iter.cpp +++ b/test/property_iter.cpp @@ -68,8 +68,10 @@ int main(int, char* []) std::size_t current_edge_id = 0; property_map::type vertex_id_map = get(vertex_id, g); + (void)vertex_id_map; property_map::type edge_id_map = get(edge_id, g); + (void)edge_id_map; for (std::size_t k = 0; k < N; ++k) add_vertex(current_vertex_id++, g); From e315856b1b5a02b7a82beafd97d6a7f7840e3537 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Sun, 25 Mar 2012 01:38:29 +0000 Subject: [PATCH 130/333] Fixed warnings [SVN r77525] --- test/index_graph.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/index_graph.cpp b/test/index_graph.cpp index b988179f6..3e757e82e 100644 --- a/test/index_graph.cpp +++ b/test/index_graph.cpp @@ -20,7 +20,7 @@ void test() static const size_t N = 5; Graph g; - IndexMap x = get(vertex_index, g); + (void)(IndexMap)get(vertex_index, g); // build up the graph Vertex v[N]; @@ -73,7 +73,7 @@ void build() Graph g(N); BOOST_ASSERT(max_vertex_index(g) == N); - IndexMap x = get(vertex_index, g); + (void)(IndexMap)get(vertex_index, g); // Each vertex should be numbered correctly. Iterator i, end; From 3b7250f7366c7ad2b135f61c1db7e4627c4276a9 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Sun, 25 Mar 2012 04:57:48 +0000 Subject: [PATCH 131/333] Disambiguated tuple operations [SVN r77526] --- include/boost/graph/graphviz.hpp | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/include/boost/graph/graphviz.hpp b/include/boost/graph/graphviz.hpp index 3fc5b1cdb..aedce5553 100644 --- a/include/boost/graph/graphviz.hpp +++ b/include/boost/graph/graphviz.hpp @@ -32,7 +32,6 @@ #include #include #include -#include #include namespace boost { @@ -833,13 +832,13 @@ class mutate_graph_impl v_prop; + typedef boost::tuple v_prop; BOOST_FOREACH(const v_prop& t, vertex_props) { - put(get<0>(t), dp_, get<1>(t), get<2>(t)); + put(boost::get<0>(t), dp_, boost::get<1>(t), boost::get<2>(t)); } - typedef tuple e_prop; + typedef boost::tuple e_prop; BOOST_FOREACH(const e_prop& t, edge_props) { - put(get<0>(t), dp_, edge_permutation_from_sorting[get<1>(t)], get<2>(t)); + put(boost::get<0>(t), dp_, edge_permutation_from_sorting[boost::get<1>(t)], boost::get<2>(t)); } } @@ -860,7 +859,7 @@ class mutate_graph_impl > vertex_props; - std::vector > edge_props; + std::vector > vertex_props; + std::vector > edge_props; std::vector > edges_to_add; std::map bgl_nodes; std::map bgl_edges; From bbab01b9c3132e5ac1ec1e1c85e0a76ed062cc25 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Sun, 25 Mar 2012 04:58:58 +0000 Subject: [PATCH 132/333] Removed incorrect tests [SVN r77527] --- test/adj_list_cc.cpp | 8 -------- 1 file changed, 8 deletions(-) diff --git a/test/adj_list_cc.cpp b/test/adj_list_cc.cpp index fad293883..b1e2d544d 100644 --- a/test/adj_list_cc.cpp +++ b/test/adj_list_cc.cpp @@ -75,8 +75,6 @@ int main(int,char*[]) BOOST_CONCEPT_ASSERT(( MutableEdgeListGraphConcept )); BOOST_CONCEPT_ASSERT(( VertexMutablePropertyGraphConcept )); BOOST_CONCEPT_ASSERT(( EdgeMutablePropertyGraphConcept )); - BOOST_CONCEPT_ASSERT(( - ReadablePropertyGraphConcept )); BOOST_CONCEPT_ASSERT(( LvaluePropertyGraphConcept )); BOOST_CONCEPT_ASSERT(( @@ -97,8 +95,6 @@ int main(int,char*[]) BOOST_CONCEPT_ASSERT(( MutableEdgeListGraphConcept )); BOOST_CONCEPT_ASSERT(( VertexMutablePropertyGraphConcept )); BOOST_CONCEPT_ASSERT(( EdgeMutablePropertyGraphConcept )); - BOOST_CONCEPT_ASSERT(( - ReadablePropertyGraphConcept )); BOOST_CONCEPT_ASSERT(( LvaluePropertyGraphConcept )); BOOST_CONCEPT_ASSERT(( @@ -143,8 +139,6 @@ int main(int,char*[]) BOOST_CONCEPT_ASSERT(( MutableEdgeListGraphConcept )); BOOST_CONCEPT_ASSERT(( VertexMutablePropertyGraphConcept )); BOOST_CONCEPT_ASSERT(( EdgeMutablePropertyGraphConcept )); - BOOST_CONCEPT_ASSERT(( - ReadablePropertyGraphConcept )); BOOST_CONCEPT_ASSERT(( LvaluePropertyGraphConcept )); BOOST_CONCEPT_ASSERT(( @@ -165,8 +159,6 @@ int main(int,char*[]) BOOST_CONCEPT_ASSERT(( MutableEdgeListGraphConcept )); BOOST_CONCEPT_ASSERT(( VertexMutablePropertyGraphConcept )); BOOST_CONCEPT_ASSERT(( EdgeMutablePropertyGraphConcept )); - BOOST_CONCEPT_ASSERT(( - ReadablePropertyGraphConcept )); BOOST_CONCEPT_ASSERT(( LvaluePropertyGraphConcept )); BOOST_CONCEPT_ASSERT(( From 7e598645468ff4c5fe84b2d46a0cf8164ab070b7 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Sun, 25 Mar 2012 04:59:23 +0000 Subject: [PATCH 133/333] Fixed warnings [SVN r77528] --- test/csr_graph_test.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/test/csr_graph_test.cpp b/test/csr_graph_test.cpp index 757a8841f..b6a99603c 100644 --- a/test/csr_graph_test.cpp +++ b/test/csr_graph_test.cpp @@ -280,14 +280,13 @@ void graph_test(const OrigGraph& g) // Check edge_from_index (and implicitly the edge_index property map) for // each edge in g2 - std::size_t last_src = 0, last_tgt = 0; + std::size_t last_src = 0; for (boost::tie(ei, ei_end) = edges(g2); ei != ei_end; ++ei) { BOOST_CHECK(edge_from_index(get(boost::edge_index, g2, *ei), g2) == *ei); std::size_t src = get(boost::vertex_index, g2, source(*ei, g2)); - std::size_t tgt = get(boost::vertex_index, g2, target(*ei, g2)); + (void)(std::size_t)get(boost::vertex_index, g2, target(*ei, g2)); BOOST_CHECK(src >= last_src); last_src = src; - last_tgt = tgt; } // Check out edge iteration and vertex iteration for sortedness From 57121513a7df0a564261f2ca41ed55c50aee8e74 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Sun, 25 Mar 2012 05:00:05 +0000 Subject: [PATCH 134/333] Fixed property map access [SVN r77529] --- test/subgraph_bundled.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/subgraph_bundled.cpp b/test/subgraph_bundled.cpp index 81629c95b..ccfcb42b6 100644 --- a/test/subgraph_bundled.cpp +++ b/test/subgraph_bundled.cpp @@ -127,7 +127,7 @@ int test_main(int, char*[]) graph_traits::edge_iterator ei, ee; for (boost::tie(ei, ee) = edges(sub); ei != ee; ++ei) { // This used to segfault. - get(edge_weight, sub, *ei); + get(&arc::weight, sub, *ei); } } From 6f4b8bf204a15389e6fcc74e1d27a56271cd72a9 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Sun, 25 Mar 2012 05:00:21 +0000 Subject: [PATCH 135/333] Removed unused variable [SVN r77530] --- test/core_numbers_test.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/test/core_numbers_test.cpp b/test/core_numbers_test.cpp index 733bf4a6f..3af081160 100644 --- a/test/core_numbers_test.cpp +++ b/test/core_numbers_test.cpp @@ -78,7 +78,6 @@ int test_2() { int num_arcs = sizeof(edge_array) / sizeof(Edge); graph_t G(edge_array, edge_array + num_arcs, weights, num_nodes); - property_map::type weightmap = get(edge_weight, G); std::vector core_nums(num_vertices(G)); weighted_core_numbers(G, From 035fac705cf1e2b127cb2fc80a9f1275f7a2ccf2 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Sun, 25 Mar 2012 05:00:36 +0000 Subject: [PATCH 136/333] Fixed warnings [SVN r77531] --- test/dag_longest_paths.cpp | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/test/dag_longest_paths.cpp b/test/dag_longest_paths.cpp index a3793082d..4b5151b32 100644 --- a/test/dag_longest_paths.cpp +++ b/test/dag_longest_paths.cpp @@ -20,12 +20,11 @@ int test_main(int, char*[]) property > Graph; Graph graph; - Graph::vertex_descriptor v1, v2, v3, v4; - v1 = add_vertex(graph); - v2 = add_vertex(graph); - v3 = add_vertex(graph); - v4 = add_vertex(graph); + (void)add_vertex(graph); + (void)add_vertex(graph); + (void)add_vertex(graph); + (void)add_vertex(graph); Graph::edge_descriptor e; From 7a2ec7c4dcb9a59abe54e77488ceab9b0f019db7 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Sun, 25 Mar 2012 05:00:52 +0000 Subject: [PATCH 137/333] Removed unused type and variable [SVN r77532] --- test/dijkstra_no_color_map_compare.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/test/dijkstra_no_color_map_compare.cpp b/test/dijkstra_no_color_map_compare.cpp index a8c140d19..5ff18c1c9 100644 --- a/test/dijkstra_no_color_map_compare.cpp +++ b/test/dijkstra_no_color_map_compare.cpp @@ -109,8 +109,6 @@ int test_main(int argc, char* argv[]) put(index_map, current_vertex, vertex_index++); } - typedef property_map::type weight_map_t; - weight_map_t weight_map = get(edge_weight, graph); randomize_property(graph, generator); // Run comparison test with original dijkstra_shortest_paths From 5aa2be67b05dbffabc08467e1fa7bc68a580e526 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Sun, 25 Mar 2012 05:01:15 +0000 Subject: [PATCH 138/333] Changed to use documented interface [SVN r77533] --- example/bipartite_example.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/example/bipartite_example.cpp b/example/bipartite_example.cpp index 05dd9cd8d..c8e62ad26 100644 --- a/example/bipartite_example.cpp +++ b/example/bipartite_example.cpp @@ -31,7 +31,7 @@ void print_bipartite (const Graph& g) if (bipartite) { typedef std::vector partition_t; - typedef vec_adj_list_vertex_id_map index_map_t; + typedef typename property_map ::type index_map_t; typedef iterator_property_map partition_map_t; partition_t partition (num_vertices (g)); From 8f8cd154e645fbec2ef6b38f8cf14c8d971cf88d Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Sun, 25 Mar 2012 05:01:58 +0000 Subject: [PATCH 139/333] Fixed warning [SVN r77534] --- include/boost/graph/bron_kerbosch_all_cliques.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/boost/graph/bron_kerbosch_all_cliques.hpp b/include/boost/graph/bron_kerbosch_all_cliques.hpp index 1466dfe5f..91960936e 100644 --- a/include/boost/graph/bron_kerbosch_all_cliques.hpp +++ b/include/boost/graph/bron_kerbosch_all_cliques.hpp @@ -224,7 +224,7 @@ namespace detail // otherwise, iterate over candidates and and test // for maxmimal cliquiness. - typename Container::iterator i, j, end = cands.end(); + typename Container::iterator i, j; for(i = cands.begin(); i != cands.end(); ) { Vertex candidate = *i; From e0c11b31166465c4ea423bcc7fb573012623b337 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Sun, 25 Mar 2012 05:22:49 +0000 Subject: [PATCH 140/333] Fixed HTML [SVN r77536] --- doc/faq.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/faq.html b/doc/faq.html index 6f4914842..ff20e1622 100644 --- a/doc/faq.html +++ b/doc/faq.html @@ -124,8 +124,8 @@

      Frequently Asked Questions

      not being found, such as:
       ../../../boost/concept_check.hpp:209: no match for
      -`boost::detail::error_property_not_found & == 
      - boost::detail::error_property_not_found &'
      +`boost::detail::error_property_not_found & == 
      + boost::detail::error_property_not_found &'
       
      or a message such as:
      
      From e77cd87de11263b60cebf6996efc7d1b3cb4d0b5 Mon Sep 17 00:00:00 2001
      From: Jeremiah Willcock 
      Date: Sun, 25 Mar 2012 21:03:59 +0000
      Subject: [PATCH 141/333] Changed property lookup code to simplify graph
       implementations (remove most special-casing of bundled properties), made CSR
       graph work with non-bundled properties (probably), split named parameter
       algorithms to not use property map code
      
      [SVN r77549]
      ---
       include/boost/graph/adjacency_list.hpp        | 167 +------
       include/boost/graph/adjacency_list_io.hpp     |   6 +-
       include/boost/graph/adjacency_matrix.hpp      | 462 +++++++-----------
       .../graph/bellman_ford_shortest_paths.hpp     |   2 +-
       .../boost/graph/betweenness_centrality.hpp    |   6 +-
       .../boost/graph/biconnected_components.hpp    |  26 +-
       include/boost/graph/breadth_first_search.hpp  |  49 +-
       .../graph/compressed_sparse_row_graph.hpp     | 180 ++++---
       include/boost/graph/copy.hpp                  |   4 +-
       include/boost/graph/detail/adjacency_list.hpp |  83 ++--
       include/boost/graph/directed_graph.hpp        |  43 +-
       include/boost/graph/edmonds_karp_max_flow.hpp |  14 +-
       include/boost/graph/fruchterman_reingold.hpp  |   6 +-
       include/boost/graph/graph_traits.hpp          |  44 +-
       include/boost/graph/named_function_params.hpp | 236 +++++----
       include/boost/graph/named_graph.hpp           |  49 +-
       include/boost/graph/neighbor_bfs.hpp          |   6 +-
       include/boost/graph/properties.hpp            | 193 ++------
       include/boost/graph/reverse_graph.hpp         |  58 ++-
       include/boost/graph/strong_components.hpp     |   8 +-
       include/boost/graph/subgraph.hpp              | 253 ++--------
       include/boost/graph/undirected_dfs.hpp        |   6 +-
       include/boost/graph/undirected_graph.hpp      |  80 +--
       include/boost/pending/detail/property.hpp     | 139 ------
       include/boost/pending/property.hpp            | 230 ++++++---
       25 files changed, 831 insertions(+), 1519 deletions(-)
      
      diff --git a/include/boost/graph/adjacency_list.hpp b/include/boost/graph/adjacency_list.hpp
      index 5034fec5a..7b121637a 100644
      --- a/include/boost/graph/adjacency_list.hpp
      +++ b/include/boost/graph/adjacency_list.hpp
      @@ -51,11 +51,6 @@ namespace boost {
         // adjacency_list, and the container_gen traits class which is used
         // to map the selectors to the container type used to implement the
         // graph.
      -  //
      -  // The main container_gen traits class uses partial specialization,
      -  // so we also include a workaround.
      -
      -#if !defined BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
       
       #if !defined BOOST_NO_SLIST
         struct slistS {};
      @@ -130,93 +125,6 @@ namespace boost {
           typedef boost::unordered_multiset type;
         };
       
      -#else // !defined BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
      -
      -#if !defined BOOST_NO_SLIST
      -  struct slistS {
      -    template 
      -    struct bind_ { typedef BOOST_STD_EXTENSION_NAMESPACE::slist type; };
      -  };
      -#endif
      -
      -  struct vecS  {
      -    template 
      -    struct bind_ { typedef std::vector type; };
      -  };
      -
      -  struct listS {
      -    template 
      -    struct bind_ { typedef std::list type; };
      -  };
      -
      -  struct setS  {
      -    template 
      -    struct bind_ { typedef std::set > type; };
      -  };
      -
      -
      -  struct mapS  {
      -    template 
      -    struct bind_ { typedef std::set > type; };
      -  };
      -
      -  struct multisetS  {
      -    template 
      -    struct bind_ { typedef std::multiset > type; };
      -  };
      -
      -  struct multimapS  {
      -    template 
      -    struct bind_ { typedef std::multiset > type; };
      -  };
      -
      -  struct hash_setS {
      -    template 
      -    struct bind_ { typedef boost::unordered_set type; };
      -  };
      -
      -  struct hash_mapS {
      -    template 
      -    struct bind_ { typedef boost::unordered_set type; };
      -  };
      -
      -  struct hash_multisetS {
      -    template 
      -    struct bind_ { typedef boost::unordered_multiset type; };
      -  };
      -
      -  struct hash_multimapS {
      -    template 
      -    struct bind_ { typedef boost::unordered_multiset type; };
      -  };
      -
      -  template  struct container_selector {
      -    typedef vecS type;
      -  };
      -
      -#define BOOST_CONTAINER_SELECTOR(NAME) \
      -  template <> struct container_selector  { \
      -    typedef NAME type; \
      -  }
      -
      -  BOOST_CONTAINER_SELECTOR(vecS);
      -  BOOST_CONTAINER_SELECTOR(listS);
      -  BOOST_CONTAINER_SELECTOR(mapS);
      -  BOOST_CONTAINER_SELECTOR(setS);
      -  BOOST_CONTAINER_SELECTOR(multisetS);
      -  BOOST_CONTAINER_SELECTOR(hash_mapS);
      -#if !defined BOOST_NO_SLIST
      -  BOOST_CONTAINER_SELECTOR(slistS);
      -#endif
      -
      -  template 
      -  struct container_gen {
      -    typedef typename container_selector::type Select;
      -    typedef typename Select:: template bind_::type type;
      -  };
      -
      -#endif // !defined BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
      -
         template 
         struct parallel_edge_traits { };
       
      @@ -354,13 +262,7 @@ namespace boost {
             adjacency_list,
             VertexListS, OutEdgeListS, DirectedS,
      -#if !defined(BOOST_GRAPH_NO_BUNDLED_PROPERTIES)
      -      typename detail::retag_property_list::type,
      -      typename detail::retag_property_list::type,
      -#else
             VertexProperty, EdgeProperty,
      -#endif
             GraphProperty, EdgeListS>::type,
             // Support for named vertices
             public graph::maybe_named_graph<
      @@ -371,25 +273,14 @@ namespace boost {
               VertexProperty>
         {
             public:
      -#if !defined(BOOST_GRAPH_NO_BUNDLED_PROPERTIES)
      -    typedef typename graph_detail::graph_prop::property graph_property_type;
      -    typedef typename graph_detail::graph_prop::bundle graph_bundled;
      -
      -    typedef typename graph_detail::vertex_prop::property vertex_property_type;
      -    typedef typename graph_detail::vertex_prop::bundle vertex_bundled;
      -
      -    typedef typename graph_detail::edge_prop::property edge_property_type;
      -    typedef typename graph_detail::edge_prop::bundle edge_bundled;
      -#else
           typedef GraphProperty graph_property_type;
      -    typedef no_graph_bundle graph_bundled;
      +    typedef typename lookup_one_property::type graph_bundled;
       
           typedef VertexProperty vertex_property_type;
      -    typedef no_vertex_bundle vertex_bundled;
      +    typedef typename lookup_one_property::type vertex_bundled;
       
           typedef EdgeProperty edge_property_type;
      -    typedef no_edge_bundle edge_bundled;
      -#endif
      +    typedef typename lookup_one_property::type edge_bundled;
       
         private:
           typedef adjacency_list self;
      @@ -545,58 +436,6 @@ namespace boost {
           return e.m_target;
         }
       
      -  // Support for bundled properties
      -#ifndef BOOST_GRAPH_NO_BUNDLED_PROPERTIES
      -  template
      -  inline
      -  typename property_map, T Bundle::*>::type
      -  get(T Bundle::* p, adjacency_list& g)
      -  {
      -    typedef typename property_map, T Bundle::*>::type
      -      result_type;
      -    return result_type(&g, p);
      -  }
      -
      -  template
      -  inline
      -  typename property_map, T Bundle::*>::const_type
      -  get(T Bundle::* p, adjacency_list const & g)
      -  {
      -    typedef typename property_map, T Bundle::*>::const_type
      -      result_type;
      -    return result_type(&g, p);
      -  }
      -
      -  template
      -  inline T
      -  get(T Bundle::* p, adjacency_list const & g, const Key& key)
      -  {
      -    return get(get(p, g), key);
      -  }
      -
      -  template
      -  inline void
      -  put(T Bundle::* p, adjacency_list& g, const Key& key, const T& value)
      -  {
      -    put(get(p, g), key, value);
      -  }
      -
      -#endif
      -
       // Mutability Traits
       template 
       struct graph_mutability_traits {
      diff --git a/include/boost/graph/adjacency_list_io.hpp b/include/boost/graph/adjacency_list_io.hpp
      index 547c02902..aaba8a43c 100644
      --- a/include/boost/graph/adjacency_list_io.hpp
      +++ b/include/boost/graph/adjacency_list_io.hpp
      @@ -40,7 +40,7 @@ namespace boost {
       template
       std::istream& operator >> ( std::istream& in, property& p )
       {
      -        in >> p.m_value >> *(static_cast(&p)); // houpla !!
      +        in >> p.m_value >> p.m_base; // houpla !!
               return in;
       }
       
      @@ -65,7 +65,7 @@ template
       void get
       ( property& p, const V& v, Stag s )
       {
      -        get( *(static_cast(&p)),v,s );
      +        get( p.m_base,v,s );
       }
       
       template
      @@ -82,7 +82,7 @@ void getSubset
       ( property& p, const property& s )
       {
               get( p, s.m_value, Stag() );
      -        getSubset( p, Snext(s) );
      +        getSubset( p, s.m_base );
       }
       
       template
       #include 
       #include 
      +#include 
       #include 
       #include 
       #include 
      @@ -29,7 +30,10 @@
       #include 
       #include 
       #include 
      -#include 
      +#include 
      +#include 
      +#include 
      +#include 
       
       namespace boost {
       
      @@ -484,25 +488,14 @@ namespace boost {
           BOOST_STATIC_ASSERT(!(is_same::value));
       #endif
       
      -#if !defined(BOOST_GRAPH_NO_BUNDLED_PROPERTIES)
      -    typedef typename graph_detail::graph_prop::property graph_property_type;
      -    typedef typename graph_detail::graph_prop::bundle graph_bundled;
      -
      -    typedef typename graph_detail::vertex_prop::property vertex_property_type;
      -    typedef typename graph_detail::vertex_prop::bundle vertex_bundled;
      -
      -    typedef typename graph_detail::edge_prop::property edge_property_type;
      -    typedef typename graph_detail::edge_prop::bundle edge_bundled;
      -#else
           typedef GraphProperty graph_property_type;
      -    typedef no_graph_bundle graph_bundled;
      +    typedef typename lookup_one_property::type graph_bundled;
       
           typedef VertexProperty vertex_property_type;
      -    typedef no_vertex_bundle vertex_bundled;
      +    typedef typename lookup_one_property::type vertex_bundled;
       
           typedef EdgeProperty edge_property_type;
      -    typedef no_edge_bundle edge_bundled;
      -#endif
      +    typedef typename lookup_one_property::type edge_bundled;
       
         public: // should be private
           typedef typename mpl::if_::type,
      @@ -640,16 +633,16 @@ namespace boost {
       #ifndef BOOST_GRAPH_NO_BUNDLED_PROPERTIES
           // Directly access a vertex or edge bundle
           vertex_bundled& operator[](vertex_descriptor v)
      -    { return get(vertex_bundle, *this)[v]; }
      +    { return get(vertex_bundle, *this, v); }
       
           const vertex_bundled& operator[](vertex_descriptor v) const
      -    { return get(vertex_bundle, *this)[v]; }
      +    { return get(vertex_bundle, *this, v); }
       
           edge_bundled& operator[](edge_descriptor e)
      -    { return get(edge_bundle, *this)[e]; }
      +    { return get(edge_bundle, *this, e); }
       
           const edge_bundled& operator[](edge_descriptor e) const
      -    { return get(edge_bundle, *this)[e]; }
      +    { return get(edge_bundle, *this, e); }
       
           graph_bundled& operator[](graph_bundle_t)
           { return get_property(*this); }
      @@ -1035,326 +1028,211 @@ namespace boost {
         //=========================================================================
         // Functions required by the PropertyGraph concept
       
      -  // O(1)
      -  template 
      -  inline void
      -  set_property(adjacency_matrix& g, Tag, const Value& value)
      -  {
      -      get_property_value(g.m_property, Tag()) = value;
      -  }
      -
         template 
      -  inline typename graph_property, Tag>::type&
      -  get_property(adjacency_matrix& g, Tag)
      -  {
      -      return get_property_value(g.m_property, Tag());
      -  }
      +            typename Prop, typename Kind>
      +  struct adj_mat_pm_helper;
       
         template 
      -  inline const typename graph_property, Tag>::type&
      -  get_property(const adjacency_matrix& g, Tag)
      -  {
      -      return get_property_value(g.m_property, Tag());
      -  }
      +            typename Prop>
      +  struct adj_mat_pm_helper {
      +    typedef typename graph_traits >::vertex_descriptor arg_type;
      +    typedef typed_identity_property_map vi_map_type;
      +    typedef iterator_property_map::iterator, vi_map_type> all_map_type;
      +    typedef iterator_property_map::const_iterator, vi_map_type> all_map_const_type;
      +    typedef transform_value_property_map<
      +              detail::lookup_one_property_f,
      +              all_map_type>
      +      type;
      +    typedef transform_value_property_map<
      +              detail::lookup_one_property_f,
      +              all_map_const_type>
      +      const_type;
      +    typedef typename property_traits::reference single_nonconst_type;
      +    typedef typename property_traits::reference single_const_type;
      +
      +    static type get_nonconst(adjacency_matrix& g, Prop prop) {
      +      return type(prop, all_map_type(g.m_vertex_properties.begin(), vi_map_type()));
      +    }
       
      -  //=========================================================================
      -  // Vertex Property Map
      +    static const_type get_const(const adjacency_matrix& g, Prop prop) {
      +      return const_type(prop, all_map_const_type(g.m_vertex_properties.begin(), vi_map_type()));
      +    }
       
      -  template 
      -  class adj_matrix_vertex_property_map
      -    : public put_get_helper >
      -  {
      -  public:
      -    typedef T value_type;
      -    typedef R reference;
      -    typedef Vertex key_type;
      -    typedef boost::lvalue_property_map_tag category;
      -    adj_matrix_vertex_property_map() { }
      -    adj_matrix_vertex_property_map(GraphPtr g) : m_g(g) { }
      -    inline reference operator[](key_type v) const {
      -      return get_property_value(m_g->m_vertex_properties[v], Tag());
      +    static single_nonconst_type get_nonconst_one(adjacency_matrix& g, Prop prop, arg_type v) {
      +      return lookup_one_property::lookup(g.m_vertex_properties[v], prop);
           }
      -    GraphPtr m_g;
      -  };
       
      -  template 
      -  struct adj_matrix_vertex_id_map
      -    : public boost::put_get_helper >
      -  {
      -    typedef Vertex value_type;
      -    typedef Vertex reference;
      -    typedef Vertex key_type;
      -    typedef boost::readable_property_map_tag category;
      -     adj_matrix_vertex_id_map() { }
      -    template 
      -    inline adj_matrix_vertex_id_map(const Graph&) { }
      -    inline value_type operator[](key_type v) const { return v; }
      +    static single_const_type get_const_one(const adjacency_matrix& g, Prop prop, arg_type v) {
      +      return lookup_one_property::lookup(g.m_vertex_properties[v], prop);
      +    }
         };
       
      -  namespace detail {
      -
      -    struct adj_matrix_any_vertex_pa {
      -      template 
      -      struct bind_ {
      -        typedef typename property_value::type Value;
      -        typedef typename boost::graph_traits::vertex_descriptor Vertex;
      -
      -        typedef adj_matrix_vertex_property_map type;
      -        typedef adj_matrix_vertex_property_map const_type;
      -      };
      -    };
      -    struct adj_matrix_id_vertex_pa {
      -      template 
      -      struct bind_ {
      -        typedef typename Graph::vertex_descriptor Vertex;
      -        typedef adj_matrix_vertex_id_map type;
      -        typedef adj_matrix_vertex_id_map const_type;
      -      };
      -    };
      -
      -    template 
      -    struct adj_matrix_choose_vertex_pa_helper {
      -      typedef adj_matrix_any_vertex_pa type;
      -    };
      -    template <>
      -    struct adj_matrix_choose_vertex_pa_helper {
      -      typedef adj_matrix_id_vertex_pa type;
      -    };
      -
      -    template 
      -    struct adj_matrix_choose_vertex_pa {
      -      typedef typename adj_matrix_choose_vertex_pa_helper::type Helper;
      -      typedef typename Helper::template bind_ Bind;
      -      typedef typename Bind::type type;
      -      typedef typename Bind::const_type const_type;
      -    };
      -
      -    struct adj_matrix_vertex_property_selector {
      -      template 
      -      struct bind_ {
      -        typedef adj_matrix_choose_vertex_pa Choice;
      -        typedef typename Choice::type type;
      -        typedef typename Choice::const_type const_type;
      -      };
      +  template 
      +  struct adj_mat_pm_helper {
      +    typedef typename graph_traits >::edge_descriptor edge_descriptor;
      +
      +    template 
      +    struct lookup_property_from_edge {
      +      Tag tag;
      +      lookup_property_from_edge(Tag tag): tag(tag) {}
      +      typedef typename boost::mpl::if_::type ep_type_nonref;
      +      typedef ep_type_nonref& ep_type;
      +      typedef typename lookup_one_property::type& result_type;
      +      result_type operator()(edge_descriptor e) const {
      +        return lookup_one_property::lookup(*static_cast(e.get_property()), tag);
      +      }
           };
       
      -  } // namespace detail
      -
      -  template <>
      -  struct vertex_property_selector {
      -    typedef detail::adj_matrix_vertex_property_selector type;
      -  };
      +    typedef function_property_map<
      +              lookup_property_from_edge,
      +              typename graph_traits >::edge_descriptor> type;
      +    typedef function_property_map<
      +              lookup_property_from_edge,
      +              typename graph_traits >::edge_descriptor> const_type;
      +    typedef edge_descriptor arg_type;
      +    typedef typename lookup_property_from_edge::result_type single_nonconst_type;
      +    typedef typename lookup_property_from_edge::result_type single_const_type;
      +
      +    static type get_nonconst(adjacency_matrix& g, Tag tag) {
      +      return type(tag);
      +    }
       
      -  //=========================================================================
      -  // Edge Property Map
      +    static const_type get_const(const adjacency_matrix& g, Tag tag) {
      +      return const_type(tag);
      +    }
       
      +    static single_nonconst_type get_nonconst_one(adjacency_matrix& g, Tag tag, edge_descriptor e) {
      +      return lookup_one_property::lookup(*static_cast(e.get_property()), tag);
      +    }
       
      -  template 
      -  class adj_matrix_edge_property_map
      -    : public put_get_helper >
      -  {
      -  public:
      -    typedef T value_type;
      -    typedef R reference;
      -    typedef detail::matrix_edge_desc_impl key_type;
      -    typedef boost::lvalue_property_map_tag category;
      -    inline reference operator[](key_type e) const {
      -      Property& p = *(Property*)e.get_property();
      -      return get_property_value(p, Tag());
      +    static single_const_type get_const_one(const adjacency_matrix& g, Tag tag, edge_descriptor e) {
      +      return lookup_one_property::lookup(*static_cast(e.get_property()), tag);
           }
         };
      -  struct adj_matrix_edge_property_selector {
      -    template 
      -    struct bind_ {
      -      typedef typename property_value::type T;
      -      typedef typename Graph::vertex_descriptor Vertex;
      -      typedef adj_matrix_edge_property_map type;
      -      typedef adj_matrix_edge_property_map const_type;
      -    };
      -  };
      -  template <>
      -  struct edge_property_selector {
      -    typedef adj_matrix_edge_property_selector type;
      -  };
       
      -  //=========================================================================
      -  // Functions required by PropertyGraph
      +  template 
      +  struct property_map, Tag>
      +    : adj_mat_pm_helper, Tag>::type> {};
       
      -  namespace detail {
      +  template 
      +  typename property_map, Tag>::type
      +  get(Tag tag, adjacency_matrix& g) {
      +    return property_map, Tag>::get_nonconst(g, tag);
      +  }
       
      -    template 
      -    typename boost::property_map,
      -      Property>::type
      -    get_dispatch(adjacency_matrix& g, Property,
      -                 vertex_property_tag)
      -    {
      -      typedef adjacency_matrix Graph;
      -      typedef typename boost::property_map,
      -        Property>::type PA;
      -      return PA(&g);
      -    }
      -    template 
      -    typename boost::property_map,
      -      Property>::type
      -    get_dispatch(adjacency_matrix&, Property,
      -                 edge_property_tag)
      -    {
      -      typedef typename boost::property_map,
      -        Property>::type PA;
      -      return PA();
      -    }
      -    template 
      -    typename boost::property_map,
      -      Property>::const_type
      -    get_dispatch(const adjacency_matrix& g, Property,
      -                 vertex_property_tag)
      -    {
      -      typedef adjacency_matrix Graph;
      -      typedef typename boost::property_map,
      -        Property>::const_type PA;
      -      return PA(&g);
      -    }
      -    template 
      -    typename boost::property_map,
      -      Property>::const_type
      -    get_dispatch(const adjacency_matrix&, Property,
      -                 edge_property_tag)
      -    {
      -      typedef typename boost::property_map,
      -        Property>::const_type PA;
      -      return PA();
      -    }
      +  template 
      +  typename property_map, Tag>::const_type
      +  get(Tag tag, const adjacency_matrix& g) {
      +    return property_map, Tag>::get_const(g, tag);
      +  }
       
      -  } // namespace detail
      +  template 
      +  typename property_map, Tag>::single_nonconst_type
      +  get(Tag tag, adjacency_matrix& g, typename property_map, Tag>::arg_type a) {
      +    return property_map, Tag>::get_nonconst_one(g, tag, a);
      +  }
       
      -  template 
      -  inline
      -  typename property_map, Property>::type
      -  get(Property p, adjacency_matrix& g)
      -  {
      -    typedef typename property_kind::type Kind;
      -    return detail::get_dispatch(g, p, Kind());
      +  template 
      +  typename property_map, Tag>::single_const_type
      +  get(Tag tag, const adjacency_matrix& g, typename property_map, Tag>::arg_type a) {
      +    return property_map, Tag>::get_const_one(g, tag, a);
      +  }
      +
      +  template 
      +  void
      +  put(Tag tag,
      +      adjacency_matrix& g,
      +      typename property_map, Tag>::arg_type a,
      +      typename property_map, Tag>::single_const_type val) {
      +    property_map, Tag>::get_nonconst_one(g, tag, a) = val;
         }
       
      -  template 
      -  inline
      -  typename property_map, Property>::const_type
      -  get(Property p, const adjacency_matrix& g)
      +  // O(1)
      +  template 
      +  inline void
      +  set_property(adjacency_matrix& g, Tag tag, const Value& value)
         {
      -    typedef typename property_kind::type Kind;
      -    return detail::get_dispatch(g, p, Kind());
      +      get_property_value(g.m_property, tag) = value;
         }
       
      -  template 
      -  inline
      -  typename property_traits<
      -    typename property_map, Property>::const_type
      -  >::value_type
      -  get(Property p, const adjacency_matrix& g,
      -      const Key& key)
      +  template 
      +  inline typename graph_property, Tag>::type&
      +  get_property(adjacency_matrix& g, Tag tag)
         {
      -    return get(get(p, g), key);
      +      return get_property_value(g.m_property, tag);
         }
       
      -  template 
      -  inline void
      -  put(Property p, adjacency_matrix& g,
      -      const Key& key, const Value& value)
      +  template 
      +  inline const typename graph_property, Tag>::type&
      +  get_property(const adjacency_matrix& g, Tag tag)
         {
      -    typedef adjacency_matrix Graph;
      -    typedef typename boost::property_map::type Map;
      -    Map pmap = get(p, g);
      -    put(pmap, key, value);
      +      return get_property_value(g.m_property, tag);
         }
       
         //=========================================================================
      -  // Other Functions
      +  // Vertex Property Map
       
         template 
      -  typename adjacency_matrix::vertex_descriptor
      -  vertex(typename adjacency_matrix::vertices_size_type n,
      -         const adjacency_matrix&)
      -  {
      -    return n;
      +  struct property_map, vertex_index_t> {
      +    typedef typename adjacency_matrix::vertex_descriptor Vertex;
      +    typedef typed_identity_property_map type;
      +    typedef type const_type;
      +  };
      +
      +  template 
      +  typename property_map, vertex_index_t>::const_type
      +  get(vertex_index_t, adjacency_matrix&) {
      +    return typename property_map, vertex_index_t>::const_type();
         }
       
      -  // Support for bundled properties
      -#ifndef BOOST_GRAPH_NO_BUNDLED_PROPERTIES
      -  template 
      -  inline
      -  typename property_map,
      -                        T Bundle::*>::type
      -  get(T Bundle::* p, adjacency_matrix& g)
      -  {
      -    typedef typename property_map,
      -                                  T Bundle::*>::type
      -      result_type;
      -    return result_type(&g, p);
      +  template 
      +  typename adjacency_matrix::vertex_descriptor
      +  get(vertex_index_t,
      +      adjacency_matrix&,
      +      typename adjacency_matrix::vertex_descriptor v) {
      +    return v;
         }
       
      -  template 
      -  inline
      -  typename property_map,
      -                        T Bundle::*>::const_type
      -  get(T Bundle::* p, adjacency_matrix const & g)
      -  {
      -    typedef typename property_map,
      -                                  T Bundle::*>::const_type
      -      result_type;
      -    return result_type(&g, p);
      +  template 
      +  typename property_map, vertex_index_t>::const_type
      +  get(vertex_index_t, const adjacency_matrix&) {
      +    return typename property_map, vertex_index_t>::const_type();
         }
       
      -  template 
      -  inline T
      -  get(T Bundle::* p, adjacency_matrix const & g,
      -      const Key& key)
      -  {
      -    return get(get(p, g), key);
      +  template 
      +  typename adjacency_matrix::vertex_descriptor
      +  get(vertex_index_t,
      +      const adjacency_matrix&,
      +      typename adjacency_matrix::vertex_descriptor v) {
      +    return v;
         }
       
      -  template 
      -  inline void
      -  put(T Bundle::* p, adjacency_matrix& g,
      -      const Key& key, const T& value)
      +  //=========================================================================
      +  // Other Functions
      +
      +  template 
      +  typename adjacency_matrix::vertex_descriptor
      +  vertex(typename adjacency_matrix::vertices_size_type n,
      +         const adjacency_matrix&)
         {
      -    put(get(p, g), key, value);
      +    return n;
         }
       
      -#endif
      -
      -#define ADJMAT_PARAMS \
      -    typename D, typename VP, typename EP, typename GP, typename A
      -#define ADJMAT adjacency_matrix
      -template 
      -struct graph_mutability_traits {
      -    typedef mutable_edge_property_graph_tag category;
      +template 
      +struct graph_mutability_traits > {
      +  typedef mutable_edge_property_graph_tag category;
       };
      -#undef ADJMAT_PARAMS
      -#undef ADJMAT
       
       
       } // namespace boost
      diff --git a/include/boost/graph/bellman_ford_shortest_paths.hpp b/include/boost/graph/bellman_ford_shortest_paths.hpp
      index c80ebe7c7..e102d9220 100644
      --- a/include/boost/graph/bellman_ford_shortest_paths.hpp
      +++ b/include/boost/graph/bellman_ford_shortest_paths.hpp
      @@ -171,7 +171,7 @@ namespace boost {
           bool 
           bellman_dispatch2
             (VertexAndEdgeListGraph& g, 
      -       detail::error_property_not_found,
      +       param_not_found,
              Size N, WeightMap weight, PredecessorMap pred, DistanceMap distance,
              const bgl_named_params& params)
           {
      diff --git a/include/boost/graph/betweenness_centrality.hpp b/include/boost/graph/betweenness_centrality.hpp
      index 052f0633c..a4de17533 100644
      --- a/include/boost/graph/betweenness_centrality.hpp
      +++ b/include/boost/graph/betweenness_centrality.hpp
      @@ -498,14 +498,14 @@ namespace detail { namespace graph {
         };
       
         template<>
      -  struct brandes_betweenness_centrality_dispatch1
      +  struct brandes_betweenness_centrality_dispatch1
         {
           template
           static void 
           run(const Graph& g, CentralityMap centrality, 
               EdgeCentralityMap edge_centrality_map, VertexIndexMap vertex_index,
      -        error_property_not_found)
      +        param_not_found)
           {
             brandes_betweenness_centrality_dispatch2(g, centrality, edge_centrality_map,
                                                      vertex_index);
      @@ -532,7 +532,7 @@ brandes_betweenness_centrality(const Graph& g,
       {
         typedef bgl_named_params named_params;
       
      -  typedef typename property_value::type ew;
      +  typedef typename get_param_type::type ew;
         detail::graph::brandes_betweenness_centrality_dispatch1::run(
           g, 
           choose_param(get_param(params, vertex_centrality), 
      diff --git a/include/boost/graph/biconnected_components.hpp b/include/boost/graph/biconnected_components.hpp
      index 0fdbad0d2..f31b24a1d 100644
      --- a/include/boost/graph/biconnected_components.hpp
      +++ b/include/boost/graph/biconnected_components.hpp
      @@ -209,7 +209,7 @@ namespace boost
           };
           
           template <>
      -    struct bicomp_dispatch3
      +    struct bicomp_dispatch3
           {
             template& params, 
      -          error_property_not_found)
      +          param_not_found)
         {
           typedef typename graph_traits::vertex_descriptor vertex_t;
           std::vector pred(num_vertices(g));
      @@ -243,7 +243,7 @@ namespace boost
                 DiscoverTimeMap dtm, const bgl_named_params& params, 
                 LowPointMap lowpt)
             {
      -        typedef typename property_value< bgl_named_params,
      +        typedef typename get_param_type< bgl_named_params,
                   vertex_predecessor_t>::type dispatch_type;
       
               return bicomp_dispatch3::apply
      @@ -254,7 +254,7 @@ namespace boost
       
       
           template <>
      -    struct bicomp_dispatch2
      +    struct bicomp_dispatch2
           {
             template apply (const Graph& g, 
                 ComponentMap comp, OutputIterator out, VertexIndexMap index_map, 
                 DiscoverTimeMap dtm, const bgl_named_params& params, 
      -          error_property_not_found)
      +          param_not_found)
         {
           typedef typename graph_traits::vertices_size_type
             vertices_size_type;
           std::vector lowpt(num_vertices(g));
               vertices_size_type vst(0);
       
      -        typedef typename property_value< bgl_named_params,
      +        typedef typename get_param_type< bgl_named_params,
                   vertex_predecessor_t>::type dispatch_type;
         
               return bicomp_dispatch3::apply
      @@ -288,7 +288,7 @@ namespace boost
                 ComponentMap comp, OutputIterator out, VertexIndexMap index_map, 
                 const bgl_named_params& params, DiscoverTimeMap dtm)
             {
      -        typedef typename property_value< bgl_named_params,
      +        typedef typename get_param_type< bgl_named_params,
                   vertex_lowpoint_t>::type dispatch_type;
       
               return bicomp_dispatch2::apply
      @@ -298,20 +298,20 @@ namespace boost
           };
       
           template <>
      -    struct bicomp_dispatch1
      +    struct bicomp_dispatch1
           {
             template
             static std::pair apply(const Graph& g, 
                 ComponentMap comp, OutputIterator out, VertexIndexMap index_map, 
      -          const bgl_named_params& params, error_property_not_found)
      +          const bgl_named_params& params, param_not_found)
             {
               typedef typename graph_traits::vertices_size_type
                   vertices_size_type;
               std::vector discover_time(num_vertices(g));
           vertices_size_type vst(0);
       
      -        typedef typename property_value< bgl_named_params,
      +        typedef typename get_param_type< bgl_named_params,
                   vertex_lowpoint_t>::type dispatch_type;
       
               return bicomp_dispatch2::apply
      @@ -329,14 +329,14 @@ namespace boost
         biconnected_components(const Graph& g, ComponentMap comp, 
             OutputIterator out, DiscoverTimeMap dtm, LowPointMap lowpt)
         {
      -    typedef detail::error_property_not_found dispatch_type;
      +    typedef param_not_found dispatch_type;
       
           return detail::bicomp_dispatch3::apply
                   (g, comp, out, 
                    get(vertex_index, g), 
                    dtm, lowpt, 
                    bgl_named_params(0), 
      -             detail::error_property_not_found());
      +             param_not_found());
         }
       
         template & params)
         {
      -    typedef typename property_value< bgl_named_params,
      +    typedef typename get_param_type< bgl_named_params,
               vertex_discover_time_t>::type dispatch_type;
       
           return detail::bicomp_dispatch1::apply(g, comp, out, 
      diff --git a/include/boost/graph/breadth_first_search.hpp b/include/boost/graph/breadth_first_search.hpp
      index f65e47572..3af85f3f7 100644
      --- a/include/boost/graph/breadth_first_search.hpp
      +++ b/include/boost/graph/breadth_first_search.hpp
      @@ -53,11 +53,12 @@ namespace boost {
         };
       
       
      +  // Multiple-source version
         template 
      +            class ColorMap, class SourceIterator>
         void breadth_first_visit
           (const IncidenceGraph& g,
      -     typename graph_traits::vertex_descriptor s,
      +     SourceIterator sources_begin, SourceIterator sources_end,
            Buffer& Q, BFSVisitor vis, ColorMap color)
         {
           BOOST_CONCEPT_ASSERT(( IncidenceGraphConcept ));
      @@ -70,8 +71,11 @@ namespace boost {
           typedef color_traits Color;
           typename GTraits::out_edge_iterator ei, ei_end;
       
      -    put(color, s, Color::gray());             vis.discover_vertex(s, g);
      -    Q.push(s);
      +    for (; sources_begin != sources_end; ++sources_begin) {
      +      Vertex s = *sources_begin;
      +      put(color, s, Color::gray());           vis.discover_vertex(s, g);
      +      Q.push(s);
      +    }
           while (! Q.empty()) {
             Vertex u = Q.top(); Q.pop();            vis.examine_vertex(u, g);
             for (boost::tie(ei, ei_end) = out_edges(u, g); ei != ei_end; ++ei) {
      @@ -89,12 +93,25 @@ namespace boost {
           } // end while
         } // breadth_first_visit
       
      +  // Single-source version
      +  template 
      +  void breadth_first_visit
      +    (const IncidenceGraph& g,
      +     typename graph_traits::vertex_descriptor s,
      +     Buffer& Q, BFSVisitor vis, ColorMap color)
      +  {
      +    typename graph_traits::vertex_descriptor sources[1] = {s};
      +    breadth_first_visit(g, sources, sources + 1, Q, vis, color);
      +  }
       
      -  template 
         void breadth_first_search
           (const VertexListGraph& g,
      -     typename graph_traits::vertex_descriptor s,
      +     SourceIterator sources_begin, SourceIterator sources_end,
            Buffer& Q, BFSVisitor vis, ColorMap color)
         {
           // Initialization
      @@ -105,7 +122,18 @@ namespace boost {
             vis.initialize_vertex(*i, g);
             put(color, *i, Color::white());
           }
      -    breadth_first_visit(g, s, Q, vis, color);
      +    breadth_first_visit(g, sources_begin, sources_end, Q, vis, color);
      +  }
      +
      +  template 
      +  void breadth_first_search
      +    (const VertexListGraph& g,
      +     typename graph_traits::vertex_descriptor s,
      +     Buffer& Q, BFSVisitor vis, ColorMap color)
      +  {
      +    typename graph_traits::vertex_descriptor sources[1] = {s};
      +    breadth_first_search(g, sources, sources + 1, Q, vis, color);
         }
       
         namespace graph { struct bfs_visitor_event_not_overridden {}; }
      @@ -270,13 +298,13 @@ namespace boost {
           };
       
           template <>
      -    struct bfs_dispatch {
      +    struct bfs_dispatch {
             template 
             static void apply
             (VertexListGraph& g,
              typename graph_traits::vertex_descriptor s,
              const bgl_named_params& params,
      -       detail::error_property_not_found)
      +       param_not_found)
             {
               null_visitor null_vis;
       
      @@ -307,8 +335,7 @@ namespace boost {
           // graph is not really const since we may write to property maps
           // of the graph.
           VertexListGraph& ng = const_cast(g);
      -    typedef typename property_value< bgl_named_params,
      -      vertex_color_t>::type C;
      +    typedef typename get_param_type< vertex_color_t, bgl_named_params >::type C;
           detail::bfs_dispatch::apply(ng, s, params,
                                          get_param(params, vertex_color));
         }
      diff --git a/include/boost/graph/compressed_sparse_row_graph.hpp b/include/boost/graph/compressed_sparse_row_graph.hpp
      index 75e61659d..f4ff2dc86 100644
      --- a/include/boost/graph/compressed_sparse_row_graph.hpp
      +++ b/include/boost/graph/compressed_sparse_row_graph.hpp
      @@ -42,6 +42,7 @@
       #include 
       #include 
       #include 
      +#include 
       
       #ifdef BOOST_GRAPH_NO_BUNDLED_PROPERTIES
       #  error The Compressed Sparse Row graph only supports bundled properties.
      @@ -195,8 +196,8 @@ class compressed_sparse_row_graph::property graph_property_type;
      -  typedef typename graph_detail::graph_prop::bundle graph_bundled;
      +  typedef GraphProperty graph_property_type;
      +  typedef typename lookup_one_property::type graph_bundled;
       
         typedef detail::compressed_sparse_row_structure forward_type;
       
      @@ -746,8 +747,8 @@ class compressed_sparse_row_graph::property graph_property_type;
      -  typedef typename graph_detail::graph_prop::bundle graph_bundled;
      +  typedef GraphProperty graph_property_type;
      +  typedef typename lookup_one_property::type graph_bundled;
         // typedef GraphProperty graph_property_type;
       
         typedef detail::compressed_sparse_row_structure forward_type;
      @@ -1404,6 +1405,61 @@ get_property(const BOOST_CSR_GRAPH_TYPE& g, Tag)
         return get_property_value(g.m_property, Tag());
       }
       
      +template 
      +struct property_map {
      +  typedef typename detail::property_kind_from_graph::type kind;
      +  typedef typename boost::mpl::if_<
      +            boost::is_same,
      +            vertex_all_t,
      +            typename boost::mpl::if_<
      +              boost::is_same,
      +              edge_all_t,
      +              graph_all_t>::type>::type all_tag;
      +  typedef typename property_traits::type>::key_type key_type;
      +  typedef typename property_traits::type>::value_type plist_type;
      +  typedef transform_value_property_map, typename property_map::type> type;
      +  typedef transform_value_property_map, typename property_map::const_type> const_type;
      +};
      +
      +template 
      +typename property_map::type
      +get(Tag tag, BOOST_CSR_GRAPH_TYPE& g) {
      +  return typename property_map::type(tag, get(typename property_map::all_tag(), g));
      +}
      +
      +template 
      +typename property_map::const_type
      +get(Tag tag, const BOOST_CSR_GRAPH_TYPE& g) {
      +  return typename property_map::const_type(tag, get(typename property_map::all_tag(), g));
      +}
      +
      +template 
      +typename property_traits::type>::reference
      +get(Tag tag, BOOST_CSR_GRAPH_TYPE& g, typename property_map::key_type k) {
      +  typedef typename property_map::all_tag all_tag;
      +  typedef typename property_map::type outer_pm;
      +  return lookup_one_property::value_type, Tag>::lookup(get(all_tag(), g, k), tag);
      +}
      +
      +template 
      +typename property_traits::const_type>::reference
      +get(Tag tag, const BOOST_CSR_GRAPH_TYPE& g, typename property_map::key_type k) {
      +  typedef typename property_map::all_tag all_tag;
      +  typedef typename property_map::const_type outer_pm;
      +  return lookup_one_property::value_type, Tag>::lookup(get(all_tag(), g, k), tag);
      +}
      +
      +template 
      +void
      +put(Tag tag,
      +    BOOST_CSR_GRAPH_TYPE& g,
      +    typename property_map::key_type k,
      +    typename lookup_one_property::plist_type, Tag>::type val) {
      +  typedef typename property_map::all_tag all_tag;
      +  typedef typename property_map::type outer_pm;
      +  lookup_one_property::plist_type, Tag>::lookup(get(all_tag(), g, k), tag) = val;
      +}
      +
       template
       struct property_map
       {
      @@ -1419,14 +1475,14 @@ struct property_map
       };
       
       template
      -struct property_map
      +struct property_map
       {
         typedef typename BOOST_CSR_GRAPH_TYPE::inherited_vertex_properties::vertex_map_type type;
         typedef typename BOOST_CSR_GRAPH_TYPE::inherited_vertex_properties::const_vertex_map_type const_type;
       };
       
       template
      -struct property_map
      +struct property_map
       {
         typedef typename BOOST_CSR_GRAPH_TYPE::forward_type::inherited_edge_properties::edge_map_type type;
         typedef typename BOOST_CSR_GRAPH_TYPE::forward_type::inherited_edge_properties::const_edge_map_type const_type;
      @@ -1447,6 +1503,21 @@ get(vertex_index_t,
         return v;
       }
       
      +template
      +inline typed_identity_property_map
      +get(vertex_index_t, BOOST_CSR_GRAPH_TYPE&)
      +{
      +  return typed_identity_property_map();
      +}
      +
      +template
      +inline Vertex
      +get(vertex_index_t,
      +    BOOST_CSR_GRAPH_TYPE&, Vertex v)
      +{
      +  return v;
      +}
      +
       template
       inline typename property_map::const_type
       get(edge_index_t, const BOOST_CSR_GRAPH_TYPE&)
      @@ -1465,125 +1536,102 @@ get(edge_index_t, const BOOST_CSR_GRAPH_TYPE&,
       }
       
       template
      -inline typename property_map::type
      -get(vertex_bundle_t, BOOST_CSR_GRAPH_TYPE& g)
      +inline typename property_map::const_type
      +get(edge_index_t, BOOST_CSR_GRAPH_TYPE&)
      +{
      +  typedef typename property_map::const_type
      +    result_type;
      +  return result_type();
      +}
      +
      +template
      +inline EdgeIndex
      +get(edge_index_t, BOOST_CSR_GRAPH_TYPE&,
      +    typename BOOST_CSR_GRAPH_TYPE::edge_descriptor e)
      +{
      +  return e.idx;
      +}
      +
      +template
      +inline typename property_map::type
      +get(vertex_all_t, BOOST_CSR_GRAPH_TYPE& g)
       {
         return g.get_vertex_bundle(get(vertex_index, g));
       }
       
       template
      -inline typename property_map::const_type
      -get(vertex_bundle_t, const BOOST_CSR_GRAPH_TYPE& g)
      +inline typename property_map::const_type
      +get(vertex_all_t, const BOOST_CSR_GRAPH_TYPE& g)
       {
         return g.get_vertex_bundle(get(vertex_index, g));
       }
       
       template
       inline VertexProperty&
      -get(vertex_bundle_t,
      +get(vertex_all_t,
           BOOST_CSR_GRAPH_TYPE& g, Vertex v)
       {
      -  return get(vertex_bundle, g)[v];
      +  return get(vertex_all, g)[v];
       }
       
       template
       inline const VertexProperty&
      -get(vertex_bundle_t,
      +get(vertex_all_t,
           const BOOST_CSR_GRAPH_TYPE& g, Vertex v)
       {
      -  return get(vertex_bundle, g)[v];
      +  return get(vertex_all, g)[v];
       }
       
       template
       inline void
      -put(vertex_bundle_t,
      +put(vertex_all_t,
           BOOST_CSR_GRAPH_TYPE& g,
           Vertex v,
           const VertexProperty& val)
       {
      -  put(get(vertex_bundle, g), v, val);
      +  put(get(vertex_all, g), v, val);
       }
       
       template
      -inline typename property_map::type
      -get(edge_bundle_t, BOOST_CSR_GRAPH_TYPE& g)
      +inline typename property_map::type
      +get(edge_all_t, BOOST_CSR_GRAPH_TYPE& g)
       {
         return g.m_forward.get_edge_bundle(get(edge_index, g));
       }
       
       template
      -inline typename property_map::const_type
      -get(edge_bundle_t, const BOOST_CSR_GRAPH_TYPE& g)
      +inline typename property_map::const_type
      +get(edge_all_t, const BOOST_CSR_GRAPH_TYPE& g)
       {
         return g.m_forward.get_edge_bundle(get(edge_index, g));
       }
       
       template
       inline EdgeProperty&
      -get(edge_bundle_t,
      +get(edge_all_t,
           BOOST_CSR_GRAPH_TYPE& g,
           const typename BOOST_CSR_GRAPH_TYPE::edge_descriptor& e)
       {
      -  return get(edge_bundle, g)[e];
      +  return get(edge_all, g)[e];
       }
       
       template
       inline const EdgeProperty&
      -get(edge_bundle_t,
      +get(edge_all_t,
           const BOOST_CSR_GRAPH_TYPE& g,
           const typename BOOST_CSR_GRAPH_TYPE::edge_descriptor& e)
       {
      -  return get(edge_bundle, g)[e];
      +  return get(edge_all, g)[e];
       }
       
       template
       inline void
      -put(edge_bundle_t,
      +put(edge_all_t,
           BOOST_CSR_GRAPH_TYPE& g,
           const typename BOOST_CSR_GRAPH_TYPE::edge_descriptor& e,
           const EdgeProperty& val)
       {
      -  put(get(edge_bundle, g), e, val);
      -}
      -
      -template
      -inline
      -typename property_map::type
      -get(T Bundle::* p, BOOST_CSR_GRAPH_TYPE& g)
      -{
      -  typedef typename property_map::type
      -    result_type;
      -  return result_type(&g, p);
      -}
      -
      -template
      -inline
      -typename property_map::const_type
      -get(T Bundle::* p, BOOST_CSR_GRAPH_TYPE const & g)
      -{
      -  typedef typename property_map::const_type
      -    result_type;
      -  return result_type(&g, p);
      -}
      -
      -template
      -inline T
      -get(T Bundle::* p, BOOST_CSR_GRAPH_TYPE const & g,
      -    const Key& key)
      -{
      -  return get(get(p, g), key);
      -}
      -
      -template
      -inline void
      -put(T Bundle::* p, BOOST_CSR_GRAPH_TYPE& g,
      -    const Key& key, const T& value)
      -{
      -  put(get(p, g), key, value);
      +  put(get(edge_all, g), e, val);
       }
       
       #undef BOOST_CSR_GRAPH_TYPE
      diff --git a/include/boost/graph/copy.hpp b/include/boost/graph/copy.hpp
      index 0dc6c664a..21bb0fb01 100644
      --- a/include/boost/graph/copy.hpp
      +++ b/include/boost/graph/copy.hpp
      @@ -280,7 +280,7 @@ namespace boost {
             typedef choose_copier_parameter type;
           };
           template <>
      -    struct choose_edge_copy {
      +    struct choose_edge_copy {
             typedef choose_default_edge_copier type;
           };
           template 
      @@ -314,7 +314,7 @@ namespace boost {
             typedef choose_copier_parameter type;
           };
           template <>
      -    struct choose_vertex_copy {
      +    struct choose_vertex_copy {
             typedef choose_default_vertex_copier type;
           };
           template 
      diff --git a/include/boost/graph/detail/adjacency_list.hpp b/include/boost/graph/detail/adjacency_list.hpp
      index 100c44ba7..a3ea40aab 100644
      --- a/include/boost/graph/detail/adjacency_list.hpp
      +++ b/include/boost/graph/detail/adjacency_list.hpp
      @@ -37,11 +37,6 @@
       #include 
       #include 
       
      -// Symbol truncation problems with MSVC, trying to shorten names.
      -#define stored_edge se_
      -#define stored_edge_property sep_
      -#define stored_edge_iter sei_
      -
       /*
         Outline for this file:
       
      @@ -67,11 +62,6 @@
        */
       
       
      -#if BOOST_WORKAROUND(BOOST_MSVC, < 1300)
      -// Stay out of the way of the concept checking class
      -# define Graph Graph_
      -#endif
      -
       namespace boost {
       
         namespace detail {
      @@ -1511,10 +1501,16 @@ namespace boost {
             typedef typename Config::edges_size_type edges_size_type;
             typedef typename Config::degree_size_type degree_size_type;
             typedef typename Config::StoredEdge StoredEdge;
      +      typedef typename Config::vertex_property_type vertex_property_type;
             typedef typename Config::edge_property_type edge_property_type;
      +      typedef typename Config::graph_property_type graph_property_type;
       
             typedef typename Config::global_edgelist_selector
               global_edgelist_selector;
      +
      +      typedef typename lookup_one_property::type vertex_bundled;
      +      typedef typename lookup_one_property::type edge_bundled;
      +      typedef typename lookup_one_property::type graph_bundled;
           };
       
           template 
      @@ -1645,43 +1641,43 @@ namespace boost {
             inline
             typename boost::property_map::type
      -      get_dispatch(adj_list_helper&, Property,
      +      get_dispatch(adj_list_helper&, Property p,
                          boost::edge_property_tag) {
               typedef typename Config::graph_type Graph;
               typedef typename boost::property_map::type PA;
      -        return PA();
      +        return PA(p);
             }
             template 
             inline
             typename boost::property_map::const_type
      -      get_dispatch(const adj_list_helper&, Property,
      +      get_dispatch(const adj_list_helper&, Property p,
                          boost::edge_property_tag) {
               typedef typename Config::graph_type Graph;
               typedef typename boost::property_map::const_type PA;
      -        return PA();
      +        return PA(p);
             }
       
             template 
             inline
             typename boost::property_map::type
      -      get_dispatch(adj_list_helper& g, Property,
      +      get_dispatch(adj_list_helper& g, Property p,
                          boost::vertex_property_tag) {
               typedef typename Config::graph_type Graph;
               typedef typename boost::property_map::type PA;
      -        return PA(&static_cast(g));
      +        return PA(&static_cast(g), p);
             }
             template 
             inline
             typename boost::property_map::const_type
      -      get_dispatch(const adj_list_helper& g, Property,
      +      get_dispatch(const adj_list_helper& g, Property p,
                          boost::vertex_property_tag) {
               typedef typename Config::graph_type Graph;
               typedef typename boost::property_map::const_type PA;
               const Graph& cg = static_cast(g);
      -        return PA(&cg);
      +        return PA(&cg, p);
             }
       
           } // namespace detail
      @@ -1691,7 +1687,7 @@ namespace boost {
           inline
           typename boost::property_map::type
           get(Property p, adj_list_helper& g) {
      -      typedef typename property_kind::type Kind;
      +      typedef typename detail::property_kind_from_graph, Property>::type Kind;
             return detail::get_dispatch(g, p, Kind());
           }
           template 
      @@ -1699,7 +1695,7 @@ namespace boost {
           typename boost::property_map::const_type
           get(Property p, const adj_list_helper& g) {
      -      typedef typename property_kind::type Kind;
      +      typedef typename detail::property_kind_from_graph, Property>::type Kind;
             return detail::get_dispatch(g, p, Kind());
           }
       
      @@ -2427,15 +2423,15 @@ namespace boost {
             typedef Reference reference;
             typedef typename Graph::vertex_descriptor key_type;
             typedef boost::lvalue_property_map_tag category;
      -      inline adj_list_vertex_property_map() { }
      -      inline adj_list_vertex_property_map(const Graph*) { }
      +      inline adj_list_vertex_property_map(const Graph* = 0, Tag tag = Tag()): m_tag(tag) { }
             inline Reference operator[](key_type v) const {
               StoredVertex* sv = (StoredVertex*)v;
      -        return get_property_value(sv->m_property, Tag());
      +        return get_property_value(sv->m_property, m_tag);
             }
             inline Reference operator()(key_type v) const {
               return this->operator[](v);
             }
      +      Tag m_tag;
           };
       
           template 
      @@ -2449,8 +2445,7 @@ namespace boost {
             typedef PropRef reference;
             typedef typename Graph::vertex_descriptor key_type;
             typedef boost::lvalue_property_map_tag category;
      -      inline adj_list_vertex_all_properties_map() { }
      -      inline adj_list_vertex_all_properties_map(const Graph*) { }
      +      inline adj_list_vertex_all_properties_map(const Graph* = 0, vertex_all_t = vertex_all_t()) { }
             inline PropRef operator[](key_type v) const {
               StoredVertex* sv = (StoredVertex*)v;
               return sv->m_property;
      @@ -2473,15 +2468,15 @@ namespace boost {
             typedef Reference reference;
             typedef typename boost::graph_traits::vertex_descriptor key_type;
             typedef boost::lvalue_property_map_tag category;
      -      vec_adj_list_vertex_property_map() { }
      -      vec_adj_list_vertex_property_map(GraphPtr g) : m_g(g) { }
      +      vec_adj_list_vertex_property_map(GraphPtr g = 0, Tag tag = Tag()) : m_g(g), m_tag(tag) { }
             inline Reference operator[](key_type v) const {
      -        return get_property_value(m_g->m_vertices[v].m_property,  Tag());
      +        return get_property_value(m_g->m_vertices[v].m_property, m_tag);
             }
             inline Reference operator()(key_type v) const {
               return this->operator[](v);
             }
             GraphPtr m_g;
      +      Tag m_tag;
           };
       
           template 
      @@ -2495,8 +2490,7 @@ namespace boost {
             typedef PropertyRef reference;
             typedef typename boost::graph_traits::vertex_descriptor key_type;
             typedef boost::lvalue_property_map_tag category;
      -      vec_adj_list_vertex_all_properties_map() { }
      -      vec_adj_list_vertex_all_properties_map(GraphPtr g) : m_g(g) { }
      +      vec_adj_list_vertex_all_properties_map(GraphPtr g = 0, vertex_all_t = vertex_all_t()) : m_g(g) { }
             inline PropertyRef operator[](key_type v) const {
               return m_g->m_vertices[v].m_property;
             }
      @@ -2542,7 +2536,7 @@ namespace boost {
             typedef boost::readable_property_map_tag category;
             inline vec_adj_list_vertex_id_map() { }
             template 
      -      inline vec_adj_list_vertex_id_map(const Graph&) { }
      +      inline vec_adj_list_vertex_id_map(const Graph&, vertex_index_t) { }
             inline value_type operator[](key_type v) const { return v; }
             inline value_type operator()(key_type v) const { return v; }
           };
      @@ -2579,17 +2573,11 @@ namespace boost {
             };
           };
         namespace detail {
      -    template 
      -    struct adj_list_choose_vertex_pa_helper {
      -      typedef adj_list_any_vertex_pa type;
      -    };
      -    template <>
      -    struct adj_list_choose_vertex_pa_helper {
      -      typedef adj_list_all_vertex_pa type;
      -    };
           template 
           struct adj_list_choose_vertex_pa {
      -      typedef typename adj_list_choose_vertex_pa_helper::type Helper;
      +      typedef typename
      +        boost::mpl::if_, adj_list_all_vertex_pa, adj_list_any_vertex_pa>::type
      +        Helper;
             typedef typename Helper::template bind_ Bind;
             typedef typename Bind::type type;
             typedef typename Bind::const_type const_type;
      @@ -2629,13 +2617,16 @@ namespace boost {
                   Tag>
               >
           {
      +      Tag tag;
      +      explicit adj_list_edge_property_map(Tag tag = Tag()): tag(tag) {}
      +
             typedef Value value_type;
             typedef Ref reference;
             typedef detail::edge_desc_impl key_type;
             typedef boost::lvalue_property_map_tag category;
             inline Ref operator[](key_type e) const {
               Property& p = *(Property*)e.get_property();
      -        return get_property_value(p, Tag());
      +        return get_property_value(p, tag);
             }
             inline Ref operator()(key_type e) const {
               return this->operator[](e);
      @@ -2650,6 +2641,7 @@ namespace boost {
                   PropPtr, Vertex>
               >
           {
      +      explicit adj_list_edge_all_properties_map(edge_all_t = edge_all_t()) {}
             typedef Property value_type;
             typedef PropRef reference;
             typedef detail::edge_desc_impl key_type;
      @@ -2793,15 +2785,6 @@ namespace boost {
       #endif
       
       
      -#undef stored_edge
      -#undef stored_edge_property
      -#undef stored_edge_iter
      -
      -#if BOOST_WORKAROUND(BOOST_MSVC, < 1300)
      -// Stay out of the way of the concept checking class
      -#undef Graph
      -#endif
      -
       #endif // BOOST_GRAPH_DETAIL_DETAIL_ADJACENCY_LIST_CCT
       
       /*
      diff --git a/include/boost/graph/directed_graph.hpp b/include/boost/graph/directed_graph.hpp
      index 0bf025190..a20539ff5 100644
      --- a/include/boost/graph/directed_graph.hpp
      +++ b/include/boost/graph/directed_graph.hpp
      @@ -33,14 +33,12 @@ template <
       class directed_graph
       {
       public:
      -    typedef typename graph_detail::graph_prop::property graph_property_type;
      -    typedef typename graph_detail::graph_prop::bundle graph_bundled;
      -
      -    typedef typename graph_detail::vertex_prop::property vertex_property_type;
      -    typedef typename graph_detail::vertex_prop::bundle vertex_bundled;
      -
      -    typedef typename graph_detail::edge_prop::property edge_property_type;
      -    typedef typename graph_detail::edge_prop::bundle edge_bundled;
      +    typedef GraphProp graph_property_type;
      +    typedef VertexProp vertex_property_type;
      +    typedef EdgeProp edge_property_type;
      +    typedef typename lookup_one_property::type graph_bundled;
      +    typedef typename lookup_one_property::type vertex_bundled;
      +    typedef typename lookup_one_property::type edge_bundled;
       
       private:
           // Wrap the user-specified properties with an index.
      @@ -590,35 +588,6 @@ void
       set_property(DIRECTED_GRAPH& g, Property p, Value v)
       { return set_property(g.impl(), p, v); }
       
      -#ifndef BOOST_GRAPH_NO_BUNDLED_PROPERTIES
      -
      -template 
      -inline typename property_map::type
      -get(Type Bundle::* p, DIRECTED_GRAPH& g) {
      -    typedef typename property_map<
      -        DIRECTED_GRAPH, Type Bundle::*
      -    >::type return_type;
      -    return return_type(&g, p);
      -}
      -
      -template 
      -inline typename property_map::const_type
      -get(Type Bundle::* p, DIRECTED_GRAPH const& g) {
      -    typedef typename property_map<
      -        DIRECTED_GRAPH, Type Bundle::*
      -    >::const_type return_type;
      -    return return_type(&g, p);
      -}
      -
      -template 
      -inline Type get(Type Bundle::* p, DIRECTED_GRAPH const& g, Key const& k)
      -{ return get(p, g.impl(), k); }
      -
      -template 
      -inline void put(Type Bundle::* p, DIRECTED_GRAPH& g, Key const& k, Value const& v)
      -{ put(p, g.impl(), k, v); }
      -#endif
      -
       // Vertex index management
       
       template 
      diff --git a/include/boost/graph/edmonds_karp_max_flow.hpp b/include/boost/graph/edmonds_karp_max_flow.hpp
      index 6aba1d059..62d1271c4 100644
      --- a/include/boost/graph/edmonds_karp_max_flow.hpp
      +++ b/include/boost/graph/edmonds_karp_max_flow.hpp
      @@ -140,7 +140,7 @@ namespace boost {
             }
           };
           template<>
      -    struct edmonds_karp_dispatch2 {
      +    struct edmonds_karp_dispatch2 {
             template 
             static typename edge_capacity_value::type
             apply
      @@ -149,7 +149,7 @@ namespace boost {
              typename graph_traits::vertex_descriptor sink,
              PredMap pred,
              const bgl_named_params& params,
      -       detail::error_property_not_found)
      +       param_not_found)
             {
               typedef typename graph_traits::edge_descriptor edge_descriptor;
               typedef typename graph_traits::vertices_size_type size_type;
      @@ -183,13 +183,13 @@ namespace boost {
                   const bgl_named_params& params,
                   PredMap pred)
             {
      -        typedef typename property_value< bgl_named_params, vertex_color_t>::type C;
      +        typedef typename get_param_type< bgl_named_params, vertex_color_t>::type C;
               return edmonds_karp_dispatch2::apply
                 (g, src, sink, pred, params, get_param(params, vertex_color));
             }
           };
           template<>
      -    struct edmonds_karp_dispatch1 {
      +    struct edmonds_karp_dispatch1 {
       
             template 
             static typename edge_capacity_value::type
      @@ -198,7 +198,7 @@ namespace boost {
              typename graph_traits::vertex_descriptor src,
              typename graph_traits::vertex_descriptor sink,
              const bgl_named_params& params,
      -       detail::error_property_not_found)
      +       param_not_found)
             {
               typedef typename graph_traits::edge_descriptor edge_descriptor;
               typedef typename graph_traits::vertices_size_type size_type;
      @@ -206,7 +206,7 @@ namespace boost {
                 num_vertices(g) : 1;
               std::vector pred_vec(n);
               
      -        typedef typename property_value< bgl_named_params, vertex_color_t>::type C;
      +        typedef typename get_param_type< bgl_named_params, vertex_color_t>::type C;
               return edmonds_karp_dispatch2::apply
                 (g, src, sink, 
                  make_iterator_property_map(pred_vec.begin(), choose_const_pmap
      @@ -227,7 +227,7 @@ namespace boost {
            typename graph_traits::vertex_descriptor sink,
            const bgl_named_params& params)
         {
      -    typedef typename property_value< bgl_named_params, vertex_predecessor_t>::type Pred;
      +    typedef typename get_param_type< bgl_named_params, vertex_predecessor_t>::type Pred;
           return detail::edmonds_karp_dispatch1::apply
             (g, src, sink, params, get_param(params, vertex_predecessor));
         }
      diff --git a/include/boost/graph/fruchterman_reingold.hpp b/include/boost/graph/fruchterman_reingold.hpp
      index 4ce502e83..b10ced643 100644
      --- a/include/boost/graph/fruchterman_reingold.hpp
      +++ b/include/boost/graph/fruchterman_reingold.hpp
      @@ -363,7 +363,7 @@ namespace detail {
         };
       
         template<>
      -  struct fr_force_directed_layout
      +  struct fr_force_directed_layout
         {
           template& params)
           {
             typedef typename Topology::point_difference_type PointDiff;
      @@ -404,7 +404,7 @@ fruchterman_reingold_force_directed_layout
          const Topology& topology,
          const bgl_named_params& params)
       {
      -  typedef typename property_value,
      +  typedef typename get_param_type,
                                         vertex_displacement_t>::type D;
       
         detail::fr_force_directed_layout::run
      diff --git a/include/boost/graph/graph_traits.hpp b/include/boost/graph/graph_traits.hpp
      index fad82f9d2..eb0232d8f 100644
      --- a/include/boost/graph/graph_traits.hpp
      +++ b/include/boost/graph/graph_traits.hpp
      @@ -15,8 +15,11 @@
       #include  /* Primarily for std::pair */
       #include 
       #include 
      +#include 
       #include 
       #include 
      +#include 
      +#include 
       #include 
       #include 
       #include 
      @@ -218,28 +221,31 @@ namespace boost {
           //?? not the right place ?? Lee
           typedef boost::forward_traversal_tag multi_pass_input_iterator_tag;
       
      -    // Forward declare graph_bundle_t property name (from
      -    // boost/graph/properties.hpp, which includes this file) for
      -    // bundled_result.
      -    enum graph_bundle_t {graph_bundle};
      +    namespace detail {
      +      BOOST_MPL_HAS_XXX_TRAIT_DEF(graph_property_type)
      +      BOOST_MPL_HAS_XXX_TRAIT_DEF(edge_property_type)
      +      BOOST_MPL_HAS_XXX_TRAIT_DEF(vertex_property_type)
      +
      +      template  struct get_graph_property_type {typedef typename G::graph_property_type type;};
      +      template  struct get_edge_property_type {typedef typename G::edge_property_type type;};
      +      template  struct get_vertex_property_type {typedef typename G::vertex_property_type type;};
      +    }
       
           template 
      -    struct graph_property_type {
      -      typedef typename G::graph_property_type type;
      -    };
      +    struct graph_property_type
      +      : boost::mpl::eval_if,
      +                            detail::get_graph_property_type,
      +                            boost::mpl::void_> {};
           template 
      -    struct edge_property_type {
      -      typedef typename G::edge_property_type type;
      -    };
      +    struct edge_property_type
      +      : boost::mpl::eval_if,
      +                            detail::get_edge_property_type,
      +                            boost::mpl::void_> {};
           template 
      -    struct vertex_property_type {
      -      typedef typename G::vertex_property_type type;
      -    };
      -
      -    struct no_bundle { };
      -    struct no_graph_bundle : no_bundle { };
      -    struct no_vertex_bundle : no_bundle { };
      -    struct no_edge_bundle : no_bundle { };
      +    struct vertex_property_type
      +      : boost::mpl::eval_if,
      +                            detail::get_vertex_property_type,
      +                            boost::mpl::void_> {};
       
           template
           struct graph_bundle_type {
      @@ -281,7 +287,7 @@ namespace boost {
             // A helper metafunction for determining whether or not a type is
             // bundled.
             template 
      -      struct is_no_bundle : mpl::bool_::value>
      +      struct is_no_bundle : mpl::bool_::value>
             { };
           } // namespace graph_detail
       
      diff --git a/include/boost/graph/named_function_params.hpp b/include/boost/graph/named_function_params.hpp
      index c5e35fa54..ea4690b6e 100644
      --- a/include/boost/graph/named_function_params.hpp
      +++ b/include/boost/graph/named_function_params.hpp
      @@ -111,15 +111,16 @@ namespace boost {
           BOOST_BGL_ONE_PARAM_REF(max_priority_queue, max_priority_queue)
       
         template 
      -  struct bgl_named_params : public Base
      +  struct bgl_named_params
         {
           typedef bgl_named_params self;
           typedef Base next_type;
           typedef Tag tag_type;
           typedef T value_type;
           bgl_named_params(T v = T()) : m_value(v) { }
      -    bgl_named_params(T v, const Base& b) : Base(b), m_value(v) { }
      +    bgl_named_params(T v, const Base& b) : m_value(v), m_base(b) { }
           T m_value;
      +    Base m_base;
       
       #define BOOST_BGL_ONE_PARAM_REF(name, key) \
           template  \
      @@ -182,145 +183,142 @@ BOOST_BGL_DECLARE_NAMED_PARAMS
         //===========================================================================
         // Functions for extracting parameters from bgl_named_params
       
      -  template 
      -  inline
      -  typename property_value< bgl_named_params, Tag2>::type
      -  get_param(const bgl_named_params& p, Tag2 tag2)
      -  {
      -    enum { match = detail::same_property::value };
      -    typedef typename
      -      property_value< bgl_named_params, Tag2>::type T2;
      -    T2* t2 = 0;
      -    typedef detail::property_value_dispatch Dispatcher;
      -    return Dispatcher::const_get_value(p, t2, tag2);
      -  }
      +  template 
      +  struct lookup_named_param {};
       
      +  template 
      +  struct lookup_named_param > {
      +    typedef T type;
      +    static const T& get(const bgl_named_params& p) {
      +      return p.m_value;
      +    }
      +  };
       
      -  namespace detail {
      -    // MSVC++ workaround
      -    template 
      -    struct choose_param_helper {
      -      template  struct result { typedef Param type; };
      -      template 
      -      static const Param& apply(const Param& p, const Default&) { return p; }
      -    };
      -    template <>
      -    struct choose_param_helper {
      -      template  struct result { typedef Default type; };
      -      template 
      -      static const Default& apply(const error_property_not_found&, const Default& d)
      -        { return d; }
      -    };
      -  } // namespace detail
      +  template 
      +  struct lookup_named_param > {
      +    typedef typename lookup_named_param::type type;
      +    static const type& get(const bgl_named_params& p) {
      +      return lookup_named_param::get(p.m_base);
      +    }
      +  };
       
      -  template  
      -  const typename detail::choose_param_helper

      ::template result::type& - choose_param(const P& param, const Default& d) { - return detail::choose_param_helper

      ::apply(param, d); - } + template + struct lookup_named_param_def { + typedef Def type; + static const Def& get(const Args&, const Def& def) {return def;} + }; - template - inline bool is_default_param(const T&) { return false; } + template + struct lookup_named_param_def, Def> { + typedef T type; + static const type& get(const bgl_named_params& p, const Def&) { + return p.m_value; + } + }; - inline bool is_default_param(const detail::error_property_not_found&) - { return true; } + template + struct lookup_named_param_def, Def> { + typedef typename lookup_named_param_def::type type; + static const type& get(const bgl_named_params& p, const Def& def) { + return lookup_named_param_def::get(p.m_base, def); + } + }; - namespace detail { + struct param_not_found {}; - struct choose_parameter { - template - struct bind_ { - typedef const P& const_result_type; - typedef const P& result_type; - typedef P type; - }; - - template - static typename bind_::const_result_type - const_apply(const P& p, const Graph&, Tag&) - { return p; } - - template - static typename bind_::result_type - apply(const P& p, Graph&, Tag&) - { return p; } - }; + template + struct get_param_type: + lookup_named_param_def {}; - struct choose_default_param { - template - struct bind_ { - typedef typename property_map::type - result_type; - typedef typename property_map::const_type - const_result_type; - typedef typename property_map::const_type - type; - }; - - template - static typename bind_::const_result_type - const_apply(const P&, const Graph& g, Tag tag) { - return get(tag, g); - } - template - static typename bind_::result_type - apply(const P&, Graph& g, Tag tag) { - return get(tag, g); - } - }; + template + inline + const typename lookup_named_param_def::type& + get_param(const Args& p, Tag) { + return lookup_named_param_def::get(p, param_not_found()); + } - template - struct choose_property_map { - typedef choose_parameter type; - }; - template <> - struct choose_property_map { - typedef choose_default_param type; - }; + template + const P& choose_param(const P& param, const Default&) { + return param; + } - template - struct choose_pmap_helper { - typedef typename choose_property_map::type Selector; - typedef typename Selector:: template bind_ Bind; - typedef Bind type; - typedef typename Bind::result_type result_type; - typedef typename Bind::const_result_type const_result_type; - typedef typename Bind::type result; - }; + template + Default choose_param(const param_not_found&, const Default& d) { + return d; + } - // used in the max-flow algorithms - template - struct edge_capacity_value - { - typedef bgl_named_params Params; - typedef typename property_value< Params, edge_capacity_t>::type Param; - typedef typename detail::choose_pmap_helper::result CapacityEdgeMap; - typedef typename property_traits::value_type type; - }; + template + inline bool is_default_param(const T&) { return false; } + + inline bool is_default_param(const param_not_found&) + { return true; } + namespace detail { + template + struct const_type_as_type {typedef typename T::const_type type;}; } // namespace detail // Use this function instead of choose_param() when you want // to avoid requiring get(tag, g) when it is not used. + namespace detail { + template + struct choose_impl_result: + boost::mpl::eval_if< + boost::is_same, + boost::mpl::eval_if< + GraphIsConst, + detail::const_type_as_type >, + property_map >, + boost::mpl::identity > {}; + + // Parameters are (NotFound, GraphIsConst, Graph, Param, Tag) + template + typename property_map::const_type + choose_impl(boost::mpl::true_, boost::mpl::true_, const Graph& g, const Param&, PropertyTag tag) { + return get(tag, g); + } + + template + typename property_map::type + choose_impl(boost::mpl::true_, boost::mpl::false_, Graph& g, const Param&, PropertyTag tag) { + return get(tag, g); + } + + template + Param + choose_impl(boost::mpl::false_, GraphIsConst, const Graph&, const Param& p, PropertyTag) { + return p; + } + } + template - typename - detail::choose_pmap_helper::const_result_type + typename detail::choose_impl_result::type choose_const_pmap(const Param& p, const Graph& g, PropertyTag tag) { - typedef typename - detail::choose_pmap_helper::Selector Choice; - return Choice::const_apply(p, g, tag); + return detail::choose_impl(boost::mpl::bool_::value>(), + boost::mpl::true_(), g, p, tag); } template - typename detail::choose_pmap_helper::result_type + typename detail::choose_impl_result::type choose_pmap(const Param& p, Graph& g, PropertyTag tag) { - typedef typename - detail::choose_pmap_helper::Selector Choice; - return Choice::apply(p, g, tag); + return detail::choose_impl(boost::mpl::bool_::value>(), + boost::mpl::false_(), g, p, tag); + } + + namespace detail { + + // used in the max-flow algorithms + template + struct edge_capacity_value + { + typedef bgl_named_params Params; + typedef typename detail::choose_impl_result::type, edge_capacity_t>::type CapacityEdgeMap; + typedef typename property_traits::value_type type; + }; + } // Declare all new tags @@ -353,7 +351,7 @@ BOOST_BGL_DECLARE_NAMED_PARAMS typedef convert_bgl_params_to_boost_parameter rest_conv; typedef boost::parameter::aux::arg_list type; static type conv(const T& x) { - return type(tagged_arg_type(x.m_value), rest_conv::conv(x)); + return type(tagged_arg_type(x.m_value), rest_conv::conv(x.m_base)); } }; @@ -362,7 +360,7 @@ BOOST_BGL_DECLARE_NAMED_PARAMS typedef convert_bgl_params_to_boost_parameter rest_conv; typedef typename rest_conv::type type; static type conv(const bgl_named_params& x) { - return rest_conv::conv(x); + return rest_conv::conv(x.m_base); } }; @@ -375,7 +373,7 @@ BOOST_BGL_DECLARE_NAMED_PARAMS template <> struct convert_bgl_params_to_boost_parameter { typedef boost::parameter::aux::empty_arg_list type; - static type conv(const boost::no_property&) {return type();} + static type conv(const boost::no_named_parameters&) {return type();} }; struct bgl_parameter_not_found_type {}; diff --git a/include/boost/graph/named_graph.hpp b/include/boost/graph/named_graph.hpp index 38f4ca0e1..f49c09707 100644 --- a/include/boost/graph/named_graph.hpp +++ b/include/boost/graph/named_graph.hpp @@ -155,51 +155,6 @@ struct internal_vertex_constructor > : internal_vertex_constructor { }; #endif -/******************************************************************* - * Named graph-specific metafunctions * - *******************************************************************/ -namespace detail { - /** @internal - * Extracts the type of a bundled vertex property from a vertex - * property. The primary template matches when we have hit the end - * of the @c property<> list. - */ - template - struct extract_bundled_vertex - { - typedef VertexProperty type; - }; - - /** @internal - * Recursively extract the bundled vertex property from a vertex - * property. - */ - template - struct extract_bundled_vertex > - : extract_bundled_vertex - { }; - - /** - * We have found the bundled vertex property type, marked with - * vertex_bundle_t. - */ - template - struct extract_bundled_vertex > - { - typedef T type; - }; - - /** - * Translate @c no_property into @c error_property_not_found when we - * have failed to extract a bundled vertex property type. - */ - template<> - struct extract_bundled_vertex - { - typedef boost::detail::error_property_not_found type; - }; -} - /******************************************************************* * Named graph mixin * *******************************************************************/ @@ -228,7 +183,7 @@ class named_graph typedef typename internal_vertex_name::type extract_name_type; /// The type of the "bundled" property, from which the name can be /// extracted. - typedef typename detail::extract_bundled_vertex::type + typedef typename lookup_one_property::type bundled_vertex_property_type; /// The type of the function object that generates vertex properties @@ -477,7 +432,7 @@ struct maybe_named_graph { /// The type of the "bundled" property, from which the name can be /// extracted. - typedef typename detail::extract_bundled_vertex::type + typedef typename lookup_one_property::type bundled_vertex_property_type; /// Notify the named_graph that we have added the given vertex. This diff --git a/include/boost/graph/neighbor_bfs.hpp b/include/boost/graph/neighbor_bfs.hpp index 4585f2e29..edfcbbb45 100644 --- a/include/boost/graph/neighbor_bfs.hpp +++ b/include/boost/graph/neighbor_bfs.hpp @@ -250,13 +250,13 @@ namespace boost { }; template <> - struct neighbor_bfs_dispatch { + struct neighbor_bfs_dispatch { template static void apply (VertexListGraph& g, typename graph_traits::vertex_descriptor s, const bgl_named_params& params, - detail::error_property_not_found) + param_not_found) { std::vector color_vec(num_vertices(g)); null_visitor null_vis; @@ -288,7 +288,7 @@ namespace boost { // graph is not really const since we may write to property maps // of the graph. VertexListGraph& ng = const_cast(g); - typedef typename property_value< bgl_named_params, + typedef typename get_param_type< bgl_named_params, vertex_color_t>::type C; detail::neighbor_bfs_dispatch::apply(ng, s, params, get_param(params, vertex_color)); diff --git a/include/boost/graph/properties.hpp b/include/boost/graph/properties.hpp index bc498bbf9..40a39da70 100644 --- a/include/boost/graph/properties.hpp +++ b/include/boost/graph/properties.hpp @@ -68,26 +68,20 @@ namespace boost { struct vertex_property_tag { }; struct edge_property_tag { }; -#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION // See examples/edge_property.cpp for how to use this. #define BOOST_INSTALL_PROPERTY(KIND, NAME) \ template <> struct property_kind { \ typedef KIND##_property_tag type; \ } -#else -#define BOOST_INSTALL_PROPERTY(KIND, NAME) \ - template <> struct property_kind { \ - typedef KIND##_property_tag type; \ - } -#endif #define BOOST_DEF_PROPERTY(KIND, NAME) \ enum KIND##_##NAME##_t { KIND##_##NAME }; \ BOOST_INSTALL_PROPERTY(KIND, NAME) - BOOST_DEF_PROPERTY(vertex, all); - BOOST_DEF_PROPERTY(edge, all); - BOOST_DEF_PROPERTY(graph, all); + // These three are defined in boost/pending/property.hpp + BOOST_INSTALL_PROPERTY(vertex, all); + BOOST_INSTALL_PROPERTY(edge, all); + BOOST_INSTALL_PROPERTY(graph, all); BOOST_DEF_PROPERTY(vertex, index); BOOST_DEF_PROPERTY(vertex, index1); BOOST_DEF_PROPERTY(vertex, index2); @@ -128,10 +122,10 @@ namespace boost { BOOST_DEF_PROPERTY(graph, visitor); // These tags are used for property bundles - // BOOST_DEF_PROPERTY(graph, bundle); -- needed in graph_traits.hpp, so enum is defined there + // These three are defined in boost/pending/property.hpp BOOST_INSTALL_PROPERTY(graph, bundle); - BOOST_DEF_PROPERTY(vertex, bundle); - BOOST_DEF_PROPERTY(edge, bundle); + BOOST_INSTALL_PROPERTY(vertex, bundle); + BOOST_INSTALL_PROPERTY(edge, bundle); // These tags are used to denote the owners and local descriptors // for the vertices and edges of a distributed graph. @@ -148,6 +142,25 @@ namespace boost { namespace detail { + template + struct property_kind_from_graph: property_kind {}; + +#ifndef BOOST_GRAPH_NO_BUNDLED_PROPERTIES + template + struct property_kind_from_graph { + typedef typename boost::mpl::if_< + boost::is_same::type>, + vertex_property_tag, + typename boost::mpl::if_< + boost::is_same::type>, + edge_property_tag, + typename boost::mpl::if_< + boost::is_same::type>, + graph_property_tag, + void>::type>::type>::type type; + }; +#endif + struct dummy_edge_property_selector { template struct bind_ { @@ -213,45 +226,16 @@ namespace boost { typedef typename Bind::type type; typedef typename Bind::const_type const_type; }; - - // This selects the kind of property map, whether is maps from - // edges or from vertices. - // - // It is overly complicated because it's a workaround for - // partial specialization. - struct choose_vertex_property_map { - template - struct bind_ { - typedef vertex_property_map type; - }; - }; - struct choose_edge_property_map { - template - struct bind_ { - typedef edge_property_map type; - }; - }; - template - struct property_map_kind_selector { - // VC++ gets confused if this isn't defined, even though - // this never gets used. - typedef choose_vertex_property_map type; - }; - template <> struct property_map_kind_selector { - typedef choose_vertex_property_map type; - }; - template <> struct property_map_kind_selector { - typedef choose_edge_property_map type; - }; } // namespace detail template struct property_map { // private: - typedef typename property_kind::type Kind; - typedef typename detail::property_map_kind_selector::type Selector; - typedef typename Selector::template bind_ Bind; - typedef typename Bind::type Map; + typedef typename detail::property_kind_from_graph::type Kind; + typedef typename mpl::if_< + is_same, + detail::edge_property_map, + detail::vertex_property_map >::type Map; public: typedef typename Map::type type; typedef typename Map::const_type const_type; @@ -273,16 +257,8 @@ namespace boost { >::type type; }; - template - class vertex_property { - public: - typedef typename Graph::vertex_property_type type; - }; - template - class edge_property { - public: - typedef typename Graph::edge_property_type type; - }; + template class vertex_property: vertex_property_type {}; + template class edge_property: edge_property_type {}; template class degree_property_map @@ -383,99 +359,6 @@ namespace boost { # define BOOST_GRAPH_NO_BUNDLED_PROPERTIES #endif -#ifndef BOOST_GRAPH_NO_BUNDLED_PROPERTIES - template - struct bundle_property_map - : put_get_helper > - { - typedef Descriptor key_type; - typedef typename remove_const::type value_type; - typedef T& reference; - typedef lvalue_property_map_tag category; - - bundle_property_map() { } - bundle_property_map(Graph* g_, T Bundle::* pm_) : g(g_), pm(pm_) {} - - reference operator[](key_type k) const { return (*g)[k].*pm; } - private: - Graph* g; - T Bundle::* pm; - }; - - namespace detail { - template - struct is_vertex_bundle - : mpl::and_, - mpl::and_ >, - mpl::not_ > > > - { }; - } - - // Specialize the property map template to generate bundled property maps. - template - struct property_map - { - private: - typedef graph_traits traits; - typedef typename Graph::vertex_bundled vertex_bundled; - typedef typename Graph::edge_bundled edge_bundled; - typedef typename mpl::if_c<(detail::is_vertex_bundle::value), - typename traits::vertex_descriptor, - typename traits::edge_descriptor>::type - descriptor; - typedef typename mpl::if_c<(detail::is_vertex_bundle::value), - vertex_bundled, - edge_bundled>::type - actual_bundle; - - public: - typedef bundle_property_map type; - typedef bundle_property_map - const_type; - }; -#endif - -// These metafunctions help implement the process of determining the vertex -// and edge properties of a graph. -namespace graph_detail { - template - struct retagged_property { - typedef typename Retag::type type; - }; - - // Search the normalized PropList (as returned by retagged<>::type) for - // the given bundle. Return the type error if no such bundle can be found. - template - struct retagged_bundle { - typedef typename property_value::type Value; - typedef typename mpl::if_< - is_same, no_bundle, Value - >::type type; - }; - - template - class normal_property { - // Normalize the property into a property list. - typedef detail::retag_property_list List; - public: - // Extract the normalized property and bundle types. - typedef typename retagged_property::type property; - typedef typename retagged_bundle::type bundle; - }; - - template - struct graph_prop : normal_property - { }; - - template - struct vertex_prop : normal_property - { }; - - template - struct edge_prop : normal_property - { }; -} // namespace graph_detail - // NOTE: These functions are declared, but never defined since they need to // be overloaded by graph implementations. However, we need them to be // declared for the functions below. @@ -498,17 +381,11 @@ get_property(Graph& g) { template inline typename graph_property::type const& -get_property(Graph const& g) { +get_property(const Graph& g) { return get_property(g, graph_bundle); } #endif } // namespace boost -#if BOOST_WORKAROUND(BOOST_MSVC, < 1300) -// Stay out of the way of the concept checking class -# undef Graph -# undef RandomAccessIterator -#endif - -#endif /* BOOST_GRAPH_PROPERTIES_HPPA */ +#endif /* BOOST_GRAPH_PROPERTIES_HPP */ diff --git a/include/boost/graph/reverse_graph.hpp b/include/boost/graph/reverse_graph.hpp index 48c4e0576..84509a330 100644 --- a/include/boost/graph/reverse_graph.hpp +++ b/include/boost/graph/reverse_graph.hpp @@ -358,36 +358,23 @@ namespace detail { } }; - struct reverse_graph_vertex_property_selector { - template - struct bind_ { - typedef typename ReverseGraph::base_type Graph; - typedef property_map PMap; - typedef typename PMap::type type; - typedef typename PMap::const_type const_type; - }; - }; - - struct reverse_graph_edge_property_selector { - template - struct bind_ { - typedef typename ReverseGraph::base_type Graph; - typedef property_map PMap; - typedef reverse_graph_edge_property_map type; - typedef reverse_graph_edge_property_map const_type; - }; - }; - } // namespace detail -template <> -struct vertex_property_selector { - typedef detail::reverse_graph_vertex_property_selector type; +template +struct property_map, Property> { + typedef boost::is_same::type, edge_property_tag> is_edge_prop; + typedef typename property_map::type orig_type; + typedef typename property_map::const_type orig_const_type; + typedef typename boost::mpl::if_, orig_type>::type type; + typedef typename boost::mpl::if_, orig_const_type>::type const_type; }; -template <> -struct edge_property_selector { - typedef detail::reverse_graph_edge_property_selector type; +template +struct property_map, Property> { + typedef boost::is_same::type, edge_property_tag> is_edge_prop; + typedef typename property_map::const_type orig_const_type; + typedef typename boost::mpl::if_, orig_const_type>::type const_type; + typedef const_type type; }; template @@ -407,7 +394,7 @@ get(Property p, const reverse_graph& g) template typename property_traits< - typename property_map::const_type + typename property_map, Property>::const_type >::value_type get(Property p, const reverse_graph& g, const Key& k) { @@ -459,6 +446,23 @@ struct property_map, edge_underlying_t> { typedef detail::underlying_edge_desc_map_type const_type; }; +template +detail::underlying_edge_desc_map_type::edge_descriptor> +get(edge_underlying_t, + reverse_graph& g) +{ + return detail::underlying_edge_desc_map_type::edge_descriptor>(); +} + +template +typename graph_traits::edge_descriptor +get(edge_underlying_t, + reverse_graph& g, + const typename graph_traits >::edge_descriptor& k) +{ + return k.underlying_descx; +} + template detail::underlying_edge_desc_map_type::edge_descriptor> get(edge_underlying_t, diff --git a/include/boost/graph/strong_components.hpp b/include/boost/graph/strong_components.hpp index ba5d45907..61345bdcb 100644 --- a/include/boost/graph/strong_components.hpp +++ b/include/boost/graph/strong_components.hpp @@ -131,7 +131,7 @@ namespace boost { template <> - struct strong_comp_dispatch2 { + struct strong_comp_dispatch2 { template inline static typename property_traits::value_type @@ -139,7 +139,7 @@ namespace boost { ComponentMap comp, RootMap r_map, const bgl_named_params& params, - detail::error_property_not_found) + param_not_found) { typedef typename graph_traits::vertices_size_type size_type; size_type n = num_vertices(g) > 0 ? num_vertices(g) : 1; @@ -179,7 +179,7 @@ namespace boost { } }; template <> - struct strong_comp_dispatch1 { + struct strong_comp_dispatch1 { template @@ -187,7 +187,7 @@ namespace boost { apply(const Graph& g, ComponentMap comp, const bgl_named_params& params, - detail::error_property_not_found) + param_not_found) { typedef typename graph_traits::vertex_descriptor Vertex; typename std::vector::size_type diff --git a/include/boost/graph/subgraph.hpp b/include/boost/graph/subgraph.hpp index 1860c8ce7..2f529add3 100644 --- a/include/boost/graph/subgraph.hpp +++ b/include/boost/graph/subgraph.hpp @@ -103,13 +103,11 @@ class subgraph { typedef typename Traits::in_edge_iterator in_edge_iterator; - typedef typename Graph::edge_property_type edge_property_type; - typedef typename Graph::vertex_property_type vertex_property_type; - typedef typename Graph::vertex_bundled vertex_bundled; - typedef typename Graph::edge_bundled edge_bundled; + typedef typename edge_property_type::type edge_property_type; + typedef typename vertex_property_type::type vertex_property_type; typedef subgraph_tag graph_tag; typedef Graph graph_type; - typedef typename Graph::graph_property_type graph_property_type; + typedef typename graph_property_type::type graph_property_type; // Create the main graph, the root of the subgraph tree subgraph() @@ -348,9 +346,6 @@ class subgraph { } }; -#ifndef BOOST_GRAPH_NO_BUNDLED_PROPERTIES -// TODO: I don't think these are required since the default metafunction -// returns Graph::vertex_bundled. template struct vertex_bundle_type > : vertex_bundle_type @@ -360,7 +355,11 @@ template struct edge_bundle_type > : edge_bundle_type { }; -#endif // BOOST_GRAPH_NO_BUNDLED_PROPERTIES + +template +struct graph_bundle_type > + : graph_bundle_type +{ }; //=========================================================================== // Functions special to the Subgraph Class @@ -786,18 +785,19 @@ class subgraph_global_property_map subgraph_global_property_map() { } - subgraph_global_property_map(GraphPtr g) - : m_g(g) + subgraph_global_property_map(GraphPtr g, Tag tag) + : m_g(g), m_tag(tag) { } reference operator[](key_type e) const { - PropertyMap pmap = get(Tag(), m_g->root().m_graph); + PropertyMap pmap = get(m_tag, m_g->root().m_graph); return m_g->is_root() ? pmap[e] : pmap[m_g->local_to_global(e)]; } GraphPtr m_g; + Tag m_tag; }; /** @@ -824,17 +824,18 @@ class subgraph_local_property_map subgraph_local_property_map() { } - subgraph_local_property_map(GraphPtr g) - : m_g(g) + subgraph_local_property_map(GraphPtr g, Tag tag) + : m_g(g), m_tag(tag) { } reference operator[](key_type e) const { // Get property map on the underlying graph. - PropertyMap pmap = get(Tag(), m_g->m_graph); + PropertyMap pmap = get(m_tag, m_g->m_graph); return pmap[e]; } GraphPtr m_g; + Tag m_tag; }; namespace detail { @@ -949,139 +950,37 @@ struct edge_property_selector { typedef detail::subgraph_property_generator type; }; -#ifndef BOOST_GRAPH_NO_BUNDLED_PROPERTIES -/** @internal - * This property map implements local or global bundled property access on - * an underlying graph. The LocalGlobal template template parameter must be - * one of the local_property or global_property templates. - */ -template < - typename Graph, typename Descriptor, typename Bundle, typename T, - template class LocalGlobal> -struct subgraph_lg_bundle_property_map - : put_get_helper< - T&, - subgraph_lg_bundle_property_map - > -{ -private: - typedef LocalGlobal Wrap; -public: - typedef Descriptor key_type; - typedef typename remove_const::type value_type; - typedef T& reference; - typedef lvalue_property_map_tag category; - - subgraph_lg_bundle_property_map() - { } - - subgraph_lg_bundle_property_map(Graph* g, T Bundle::* p) - : m_g(g), m_prop(p) - { } - - reference operator[](key_type k) const - { return (*m_g)[Wrap(k)].*m_prop; } - -private: - Graph* m_g; - T Bundle::* m_prop; -}; - -// Specialize the property map template to generate bundled property maps. -// NOTE: I'm cheating (actually double-dipping) with the local/global subgraph -// property templates. I'm not using them store descriptors, just specialize -// the property map template for specific lookups. -namespace graph_detail { - // Help decoding some of the types required for property map definitions. - template - struct bundled_subgraph_pmap_helper { - typedef subgraph Subgraph; - typedef graph_traits Traits; - typedef typename Subgraph::vertex_bundled VertBundled; - typedef typename Subgraph::edge_bundled EdgeBundled; - - // Deduce the descriptor from the template params - typedef typename mpl::if_< - detail::is_vertex_bundle, - typename Traits::vertex_descriptor, typename Traits::edge_descriptor - >::type Desc; - - // Deduce the bundled property type - typedef typename mpl::if_< - detail::is_vertex_bundle, - VertBundled, EdgeBundled - >::type Prop; - }; -} // namespace graph_detail - -template -struct property_map, local_property > - : graph_detail::bundled_subgraph_pmap_helper -{ -private: - typedef graph_detail::bundled_subgraph_pmap_helper Base; - typedef typename Base::Subgraph Subgraph; - typedef typename Base::Desc Desc; - typedef typename Base::Prop Prop; -public: - typedef subgraph_lg_bundle_property_map< - Subgraph, Desc, Prop, T, local_property - > type; - typedef subgraph_lg_bundle_property_map< - Subgraph const, Desc, Prop, T const, local_property - > const_type; -}; - -template -struct property_map, global_property > - : graph_detail::bundled_subgraph_pmap_helper -{ -private: - typedef graph_detail::bundled_subgraph_pmap_helper Base; - typedef typename Base::Subgraph Subgraph; - typedef typename Base::Desc Desc; - typedef typename Base::Prop Prop; -public: - typedef subgraph_lg_bundle_property_map< - Subgraph, Desc, Prop, T, global_property - > type; - typedef subgraph_lg_bundle_property_map< - Subgraph const, Desc, Prop, T const, global_property - > const_type; -}; -#endif - // ================================================== // get(p, g), get(p, g, k), and put(p, g, k, v) // ================================================== template typename property_map, Property>::type -get(Property, subgraph& g) { +get(Property p, subgraph& g) { typedef typename property_map< subgraph, Property>::type PMap; - return PMap(&g); + return PMap(&g, p); } template typename property_map, Property>::const_type -get(Property, const subgraph& g) { +get(Property p, const subgraph& g) { typedef typename property_map< subgraph, Property>::const_type PMap; - return PMap(&g); + return PMap(&g, p); } template typename property_traits< typename property_map, Property>::const_type >::value_type -get(Property, const subgraph& g, const Key& k) { +get(Property p, const subgraph& g, const Key& k) { typedef typename property_map< subgraph, Property>::const_type PMap; - PMap pmap(&g); + PMap pmap(&g, p); return pmap[k]; } template -void put(Property, subgraph& g, const Key& k, const Value& val) { +void put(Property p, subgraph& g, const Key& k, const Value& val) { typedef typename property_map< subgraph, Property>::type PMap; - PMap pmap(&g); + PMap pmap(&g, p); pmap[k] = val; } @@ -1091,20 +990,20 @@ void put(Property, subgraph& g, const Key& k, const Value& val) { // ================================================== template typename property_map, global_property >::type -get(global_property, subgraph& g) { +get(global_property p, subgraph& g) { typedef typename property_map< subgraph, global_property >::type Map; - return Map(&g); + return Map(&g, p.value); } template typename property_map, global_property >::const_type -get(global_property, const subgraph& g) { +get(global_property p, const subgraph& g) { typedef typename property_map< subgraph, global_property >::const_type Map; - return Map(&g); + return Map(&g, p.value); } // ================================================== @@ -1113,112 +1012,22 @@ get(global_property, const subgraph& g) { // ================================================== template typename property_map, local_property >::type -get(local_property, subgraph& g) { +get(local_property p, subgraph& g) { typedef typename property_map< subgraph, local_property >::type Map; - return Map(&g); + return Map(&g, p.value); } template typename property_map, local_property >::const_type -get(local_property, const subgraph& g) { +get(local_property p, const subgraph& g) { typedef typename property_map< subgraph, local_property >::const_type Map; - return Map(&g); -} - -#ifndef BOOST_GRAPH_NO_BUNDLED_PROPERTIES -// ================================================== -// get(bundle(p), g) -// ================================================== - -template -inline typename property_map, T Bundle::*>::type -get(T Bundle::* p, subgraph& g) { - typedef typename property_map, T Bundle::*>::type Map; - return Map(&g, p); -} - -template -inline typename property_map, T Bundle::*>::const_type -get(T Bundle::* p, subgraph const& g) { - typedef typename property_map, T Bundle::*>::const_type Map; - return Map(&g, p); -} - -template -inline Type get(Type Bundle::* p, subgraph const& g, Key const& k) -{ return get(get(p, g), k); } - -template -inline void put(Type Bundle::* p, Graph& g, Key const& k, Value const& v) -{ put(get(p, g), k, v); } - -// ========================================================= -// Local bundled, get - -template -inline typename property_map< - subgraph, local_property ->::type -get(local_property p, subgraph& g) { - typedef typename property_map< - subgraph, local_property - >::type Map; return Map(&g, p.value); } -template -inline typename property_map< - subgraph, local_property ->::const_type -get(local_property p, subgraph const& g) { - typedef typename property_map< - subgraph, local_property - >::const_type Map; - return Map(&g, p.value); -} - -template -inline Type get(local_property p, subgraph const& g, - Key const& k) -{ return get(get(p, g), k); } - -// ========================================================= -// Global bundled, get - -template -inline typename property_map< - subgraph, global_property ->::type -get(global_property p, subgraph& g) { - typedef typename property_map< - subgraph, global_property - >::type Map; - return Map(&g, p.value); -} - -template -inline typename property_map< - subgraph, global_property ->::const_type -get(global_property p, subgraph const& g) { - typedef typename property_map< - subgraph, global_property - >::const_type Map; - return Map(&g, p.value); -} - -template -inline Type get(global_property p, subgraph const& g, - Key const& k) -{ return get(get(p, g), k); } - -#endif - template inline typename graph_property::type& get_property(subgraph& g, Tag tag) { diff --git a/include/boost/graph/undirected_dfs.hpp b/include/boost/graph/undirected_dfs.hpp index df31d22b2..0dcc9c284 100644 --- a/include/boost/graph/undirected_dfs.hpp +++ b/include/boost/graph/undirected_dfs.hpp @@ -188,7 +188,7 @@ namespace boost { }; template <> - struct udfs_dispatch { + struct udfs_dispatch { template @@ -196,7 +196,7 @@ namespace boost { apply(const Graph& g, DFSVisitor vis, Vertex start_vertex, const bgl_named_params& params, EdgeColorMap edge_color, - detail::error_property_not_found) + param_not_found) { std::vector color_vec(num_vertices(g)); default_color_type c = white_color; // avoid warning about un-init @@ -219,7 +219,7 @@ namespace boost { undirected_dfs(const Graph& g, const bgl_named_params& params) { - typedef typename property_value< bgl_named_params, + typedef typename get_param_type< bgl_named_params, vertex_color_t>::type C; detail::udfs_dispatch::apply (g, diff --git a/include/boost/graph/undirected_graph.hpp b/include/boost/graph/undirected_graph.hpp index 3178b42af..884f5dbe8 100644 --- a/include/boost/graph/undirected_graph.hpp +++ b/include/boost/graph/undirected_graph.hpp @@ -38,14 +38,12 @@ template < class undirected_graph { public: - typedef typename graph_detail::graph_prop::property graph_property_type; - typedef typename graph_detail::graph_prop::bundle graph_bundled; - - typedef typename graph_detail::vertex_prop::property vertex_property_type; - typedef typename graph_detail::vertex_prop::bundle vertex_bundled; - - typedef typename graph_detail::edge_prop::property edge_property_type; - typedef typename graph_detail::edge_prop::bundle edge_bundled; + typedef GraphProp graph_property_type; + typedef VertexProp vertex_property_type; + typedef EdgeProp edge_property_type; + typedef typename lookup_one_property::type graph_bundled; + typedef typename lookup_one_property::type vertex_bundled; + typedef typename lookup_one_property::type edge_bundled; private: // Embed indices into the vertex type. @@ -530,36 +528,12 @@ remove_in_edge_if(typename UNDIRECTED_GRAPH::vertex_descriptor v, UNDIRECTED_GRAPH& g) { return remove_in_edge_if(v, pred, g.impl()); } -// Helper code for working with property maps -namespace detail { - struct undirected_graph_vertex_property_selector { - template - struct bind_ { - typedef typename UndirectedGraph::graph_type Graph; - typedef property_map PropertyMap; - typedef typename PropertyMap::type type; - typedef typename PropertyMap::const_type const_type; - }; - }; - - struct undirected_graph_edge_property_selector { - template - struct bind_ { - typedef typename UndirectedGraph::graph_type Graph; - typedef property_map PropertyMap; - typedef typename PropertyMap::type type; - typedef typename PropertyMap::const_type const_type; - }; - }; -} // namespace detail - -template <> -struct vertex_property_selector -{ typedef detail::undirected_graph_vertex_property_selector type; }; - -template <> -struct edge_property_selector -{ typedef detail::undirected_graph_edge_property_selector type; }; +template +struct property_map { + typedef typename UNDIRECTED_GRAPH::graph_type Graph; + typedef typename property_map::type type; + typedef typename property_map::const_type const_type; +}; // PropertyGraph concepts template @@ -599,36 +573,6 @@ template inline void set_property(UNDIRECTED_GRAPH& g, Property p, Value v) { return set_property(g.impl(), p, v); } -#ifndef BOOST_GRAPH_NO_BUNDLED_PROPERTIES -template -inline typename property_map::type -get(Type Bundle::* p, UNDIRECTED_GRAPH& g) { - typedef typename property_map< - UNDIRECTED_GRAPH, Type Bundle::* - >::type return_type; - return return_type(&g, p); -} - -template -inline typename property_map::const_type -get(Type Bundle::* p, UNDIRECTED_GRAPH const& g) { - typedef typename property_map< - UNDIRECTED_GRAPH, Type Bundle::* - >::const_type return_type; - return return_type(&g, p); -} - -template -inline Type -get(Type Bundle::* p, UNDIRECTED_GRAPH const& g, Key const& k) -{ return get(p, g.impl(), k); } - -template -inline void -put(Type Bundle::* p, UNDIRECTED_GRAPH& g, Key const& k, Value const& v) -{ put(p, g.impl(), k, v); } -#endif - // Indexed Vertex graph template diff --git a/include/boost/pending/detail/property.hpp b/include/boost/pending/detail/property.hpp index 09e8866cf..42c7ce07d 100644 --- a/include/boost/pending/detail/property.hpp +++ b/include/boost/pending/detail/property.hpp @@ -13,147 +13,8 @@ namespace boost { namespace detail { - template - struct same_property { - enum { value = is_same::value }; - }; - struct error_property_not_found { }; - template - struct property_value_dispatch { - template - inline static T& get_value(PropertyTag& p, T*, Tag) { - return p.m_value; - } - template - inline static const T& const_get_value(const PropertyTag& p, T*, Tag) { - return p.m_value; - } - }; - - template - struct property_value_end { - template struct result { typedef T type; }; - - template - inline static T& get_value(PropertyList& p, T* t, Tag tag) { - typedef typename PropertyList::next_type Next; - typedef typename Next::tag_type Next_tag; - enum { match = same_property::value }; - return property_value_dispatch - ::get_value(static_cast(p), t, tag); - } - template - inline static const T& const_get_value(const PropertyList& p, T* t, Tag tag) { - typedef typename PropertyList::next_type Next; - typedef typename Next::tag_type Next_tag; - enum { match = same_property::value }; - return property_value_dispatch - ::const_get_value(static_cast(p), t, tag); - } - }; - template <> - struct property_value_end { - template struct result { - typedef detail::error_property_not_found type; - }; - - // Stop the recursion and return error - template - inline static detail::error_property_not_found& - get_value(no_property&, T*, Tag) { - static error_property_not_found s_prop_not_found; - return s_prop_not_found; - } - template - inline static const detail::error_property_not_found& - const_get_value(const no_property&, T*, Tag) { - static error_property_not_found s_prop_not_found; - return s_prop_not_found; - } - }; - - template <> - struct property_value_dispatch<0> { - template - inline static typename property_value_end::template result::type& - get_value(PropertyList& p, T* t, Tag tag) { - return property_value_end::get_value(p, t, tag); - } - template - inline static const typename property_value_end::template result::type& - const_get_value(const PropertyList& p, T* t, Tag tag) { - return property_value_end::const_get_value(p, t, tag); - } - }; - - template - struct build_property_tag_value_alist - { - typedef typename PropertyList::next_type NextProperty; - typedef typename PropertyList::value_type Value; - typedef typename PropertyList::tag_type Tag; - typedef typename build_property_tag_value_alist::type Next; - typedef std::pair< std::pair, Next> type; - }; - template <> - struct build_property_tag_value_alist - { - typedef no_property type; - }; - -#if !defined BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION - template - struct extract_value { - typedef error_property_not_found type; - }; - template - struct extract_value< std::pair,Rest>, Tag2> { - typedef typename extract_value::type type; - }; - template - struct extract_value< std::pair,Rest>, Tag> { - typedef Value type; - }; -#else - // VC++ workaround: - // The main idea here is to replace partial specialization with - // nested template member classes. Of course there is the - // further complication that the outer class of the nested - // template class cannot itself be a template class. - // Hence the need for the ev_selector. -JGS - - struct recursive_extract; - struct end_extract; - - template - struct ev_selector { typedef recursive_extract type; }; - template <> - struct ev_selector { typedef end_extract type; }; - - struct recursive_extract { - template - struct bind_ { - typedef typename TagValueAList::first_type AListFirst; - typedef typename AListFirst::first_type Tag2; - typedef typename AListFirst::second_type Value; - enum { match = same_property::value }; - typedef typename TagValueAList::second_type Next; - typedef typename ev_selector::type Extractor; - typedef typename boost::ct_if< match, Value, - typename Extractor::template bind_::type - >::type type; - }; - }; - struct end_extract { - template - struct bind_ { - typedef error_property_not_found type; - }; - }; -#endif //!defined BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION - } // namespace detail } // namespace boost diff --git a/include/boost/pending/property.hpp b/include/boost/pending/property.hpp index c9880458c..93b3cd84d 100644 --- a/include/boost/pending/property.hpp +++ b/include/boost/pending/property.hpp @@ -7,32 +7,146 @@ #define BOOST_PROPERTY_HPP #include +#include +#include +#include namespace boost { - struct no_property { - typedef no_property tag_type; - typedef no_property next_type; - typedef no_property value_type; - enum { num = 0 }; - typedef void kind; - }; + struct no_property {}; template - struct property : public Base { + struct property { typedef Base next_type; typedef Tag tag_type; typedef T value_type; -#if BOOST_WORKAROUND (__GNUC__, < 3) - property() { } -#else - property() : m_value() { } -#endif - property(const T& v) : m_value(v) { } - property(const T& v, const Base& b) : Base(b), m_value(v) { } + property(const T& v = T()) : m_value(v) { } + property(const T& v, const Base& b) : m_value(v), m_base(b) { } // copy constructor and assignment operator will be generated by compiler T m_value; + Base m_base; + }; + + // Kinds of properties + template + struct property_kind { + typedef typename PropertyTag::kind type; + }; + + // Some standard properties defined independently of Boost.Graph: + enum vertex_all_t {vertex_all}; + enum edge_all_t {edge_all}; + enum graph_all_t {graph_all}; + enum vertex_bundle_t {vertex_bundle}; + enum edge_bundle_t {edge_bundle}; + enum graph_bundle_t {graph_bundle}; + + // Code to look up one property in a property list: + template + struct lookup_one_property_internal {BOOST_STATIC_CONSTANT(bool, found = false);}; + + // Special-case properties (vertex_all, edge_all, graph_all) +#define BGL_ALL_PROP(tag) \ + template \ + struct lookup_one_property_internal { \ + BOOST_STATIC_CONSTANT(bool, found = true); \ + typedef T type; \ + static T& lookup(T& x, tag) {return x;} \ + static const T& lookup(const T& x, tag) {return x;} \ + }; \ + template \ + struct lookup_one_property_internal, tag> { /* Avoid ambiguity */ \ + BOOST_STATIC_CONSTANT(bool, found = true); \ + typedef property type; \ + static type& lookup(type& x, tag) {return x;} \ + static const type& lookup(const type& x, tag) {return x;} \ + }; + + BGL_ALL_PROP(vertex_all_t) + BGL_ALL_PROP(edge_all_t) + BGL_ALL_PROP(graph_all_t) +#undef BGL_ALL_PROP + + // *_bundled; these need to be macros rather than inheritance to resolve ambiguities + #define BGL_DO_ONE_BUNDLE_TYPE(kind) \ + template \ + struct lookup_one_property_internal { \ + BOOST_STATIC_CONSTANT(bool, found = true); \ + typedef T type; \ + static T& lookup(T& x, BOOST_JOIN(kind, _bundle_t)) {return x;} \ + static const T& lookup(const T& x, BOOST_JOIN(kind, _bundle_t)) {return x;} \ + }; \ + \ + template \ + struct lookup_one_property_internal, BOOST_JOIN(kind, _bundle_t)>: lookup_one_property_internal { \ + private: \ + typedef lookup_one_property_internal base_type; \ + public: \ + static typename base_type::type& lookup(property& p, BOOST_JOIN(kind, _bundle_t)) {return base_type::lookup(p.m_base, BOOST_JOIN(kind, _bundle_t)());} \ + static const typename base_type::type& lookup(const property& p, BOOST_JOIN(kind, _bundle_t)) {return base_type::lookup(p.m_base, BOOST_JOIN(kind, _bundle_t)());} \ + }; \ + + BGL_DO_ONE_BUNDLE_TYPE(vertex) + BGL_DO_ONE_BUNDLE_TYPE(edge) + BGL_DO_ONE_BUNDLE_TYPE(graph) +#undef BGL_DO_ONE_BUNDLE_TYPE + + // Normal old-style properties; second case also handles chaining of bundled property accesses + template + struct lookup_one_property_internal, Tag> { + BOOST_STATIC_CONSTANT(bool, found = true); + typedef property prop; + typedef T type; + template + static typename enable_if, T&>::type + lookup(U& prop, const Tag&) {return prop.m_value;} + template + static typename enable_if, const T&>::type + lookup(const U& prop, const Tag&) {return prop.m_value;} + }; + + template + struct lookup_one_property_internal, PropName>: lookup_one_property_internal { + private: + typedef lookup_one_property_internal base_type; + public: + template + static typename enable_if >, typename base_type::type&>::type + lookup(PL& prop, const PropName& tag) { + return base_type::lookup(prop.m_base, tag); + } + template + static typename enable_if >, const typename base_type::type&>::type + lookup(const PL& prop, const PropName& tag) { + return base_type::lookup(prop.m_base, tag); + } + }; + + // Pointer-to-member access to bundled properties +#ifndef BOOST_GRAPH_NO_BUNDLED_PROPERTIES + template + struct lookup_one_property_internal { + BOOST_STATIC_CONSTANT(bool, found = true); + typedef R type; + static R& lookup(T& x, R T::*ptr) {return x.*ptr;} + static const R& lookup(const T& x, R T::*ptr) {return x.*ptr;} + }; +#endif + + // Version of above handling const property lists properly + template + struct lookup_one_property: lookup_one_property_internal {}; + + template + struct lookup_one_property { + BOOST_STATIC_CONSTANT(bool, found = (lookup_one_property_internal::found)); + typedef const typename lookup_one_property_internal::type type; + template + static typename enable_if, const typename lookup_one_property_internal::type&>::type + lookup(const U& p, Tag tag) { + return lookup_one_property_internal::lookup(p, tag); + } }; // The BGL properties specialize property_kind and @@ -41,11 +155,6 @@ namespace boost { // instead with a nested kind type and num. Also, we may want to // switch BGL back to using class types for properties at some point. - template - struct property_kind { - typedef typename PropertyTag::kind type; - }; - template struct has_property : boost::mpl::true_ {}; template <> @@ -58,45 +167,18 @@ namespace boost { namespace boost { template - struct property_value { -#if !defined BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION - typedef typename detail::build_property_tag_value_alist::type AList; - typedef typename detail::extract_value::type type; -#else - typedef typename detail::build_property_tag_value_alist::type AList; - typedef typename detail::ev_selector::type Extractor; - typedef typename Extractor::template bind_::type type; -#endif - }; + struct property_value: lookup_one_property {}; - template - inline detail::error_property_not_found - get_property_value(const no_property&, Tag2) { - return detail::error_property_not_found(); + template + inline typename lookup_one_property::type& + get_property_value(PropertyList& p, Tag tag) { + return lookup_one_property::lookup(p, tag); } - template - inline typename property_value, Tag2>::type& - get_property_value(property& p, Tag2 tag2) { - BOOST_STATIC_CONSTANT(bool, - match = (detail::same_property::value)); - typedef property Prop; - typedef typename property_value::type T2; - T2* t2 = 0; - typedef detail::property_value_dispatch Dispatcher; - return Dispatcher::get_value(p, t2, tag2); - } - template - inline - const typename property_value, Tag2>::type& - get_property_value(const property& p, Tag2 tag2) { - BOOST_STATIC_CONSTANT(bool, - match = (detail::same_property::value)); - typedef property Prop; - typedef typename property_value::type T2; - T2* t2 = 0; - typedef detail::property_value_dispatch Dispatcher; - return Dispatcher::const_get_value(p, t2, tag2); + template + inline const typename lookup_one_property::type& + get_property_value(const PropertyList& p, Tag tag) { + return lookup_one_property::lookup(p, tag); } namespace detail { @@ -107,7 +189,6 @@ namespace boost { : mpl::bool_::value> { }; -#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) /** @internal @name Retag Property List * This metafunction is used internally to normalize a property if it is * actually modeling a property. Specifically this is used in Boost.Graph @@ -159,7 +240,40 @@ namespace boost { typedef no_property retagged; }; //@} -#endif + + template + class lookup_one_property_f; + + template struct lookup_one_property_f_result; + + template + struct lookup_one_property_f_result(PList)> { + typedef typename lookup_one_property::type type; + }; + + template + struct lookup_one_property_f_result(PList&)> { + typedef typename lookup_one_property::type& type; + }; + + template + struct lookup_one_property_f_result(const PList&)> { + typedef const typename lookup_one_property::type& type; + }; + + template + class lookup_one_property_f { + Tag tag; + public: + lookup_one_property_f(Tag tag): tag(tag) {} + template struct result: lookup_one_property_f_result {}; + + typename lookup_one_property_f_result::type + operator()(PList& pl) const { + return lookup_one_property::lookup(pl, tag); + } + }; + } // namespace detail } // namesapce boost From 068b2916b394c65cbe505605f8dc9e9d828938c2 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Wed, 28 Mar 2012 20:20:45 +0000 Subject: [PATCH 142/333] Fixed categories of property maps for subgraph based on constness of graph; fixes #6739 [SVN r77609] --- include/boost/graph/subgraph.hpp | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/include/boost/graph/subgraph.hpp b/include/boost/graph/subgraph.hpp index 2f529add3..22706bc61 100644 --- a/include/boost/graph/subgraph.hpp +++ b/include/boost/graph/subgraph.hpp @@ -24,7 +24,9 @@ #include #include -#include +#include +#include +#include namespace boost { @@ -777,7 +779,10 @@ class subgraph_global_property_map { typedef property_traits Traits; public: - typedef typename Traits::category category; + typedef typename mpl::if_::type>, + readable_property_map_tag, + typename Traits::category>::type + category; typedef typename Traits::value_type value_type; typedef typename Traits::key_type key_type; typedef typename Traits::reference reference; @@ -813,7 +818,10 @@ class subgraph_local_property_map { typedef property_traits Traits; public: - typedef typename Traits::category category; + typedef typename mpl::if_::type>, + readable_property_map_tag, + typename Traits::category>::type + category; typedef typename Traits::value_type value_type; typedef typename Traits::key_type key_type; typedef typename Traits::reference reference; From 118a055bc4d014787599be7350f97695806f5e5a Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Wed, 28 Mar 2012 20:27:30 +0000 Subject: [PATCH 143/333] Fixed narrowing conversion [SVN r77610] --- example/astar_maze.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/example/astar_maze.cpp b/example/astar_maze.cpp index 20cff4fdd..840bce541 100644 --- a/example/astar_maze.cpp +++ b/example/astar_maze.cpp @@ -221,7 +221,7 @@ std::ostream& operator<<(std::ostream& output, const maze& m) { if (x == 0) output << BARRIER; // Put the character representing this point in the maze grid. - vertex_descriptor u = {{x, y}}; + vertex_descriptor u = {{x, vertices_size_type(y)}}; if (m.solution_contains(u)) output << "."; else if (m.has_barrier(u)) From 9092da0b8f134bf1e17be86d00d5d91a0104b9b7 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Wed, 28 Mar 2012 20:40:15 +0000 Subject: [PATCH 144/333] Changed default version of property_map to use inheritance to try to get SFINAE in more cases [SVN r77611] --- include/boost/graph/properties.hpp | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/include/boost/graph/properties.hpp b/include/boost/graph/properties.hpp index 40a39da70..6656d962e 100644 --- a/include/boost/graph/properties.hpp +++ b/include/boost/graph/properties.hpp @@ -229,17 +229,12 @@ namespace boost { } // namespace detail template - struct property_map { - // private: - typedef typename detail::property_kind_from_graph::type Kind; - typedef typename mpl::if_< - is_same, - detail::edge_property_map, - detail::vertex_property_map >::type Map; - public: - typedef typename Map::type type; - typedef typename Map::const_type const_type; - }; + struct property_map: + mpl::if_< + is_same::type, edge_property_tag>, + detail::edge_property_map, + detail::vertex_property_map >::type + {}; // shortcut for accessing the value type of the property map template From 7fccfd1f424fcee493f2e88e0c8d83cbe1d4d126 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Wed, 28 Mar 2012 20:56:44 +0000 Subject: [PATCH 145/333] Added graph property to serialization, and made default graph property no_property to allow serialization; fixes #5310 [SVN r77615] --- include/boost/graph/adj_list_serialize.hpp | 3 +++ include/boost/graph/graph_traits.hpp | 6 +++--- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/include/boost/graph/adj_list_serialize.hpp b/include/boost/graph/adj_list_serialize.hpp index c1ff4111d..01db50282 100644 --- a/include/boost/graph/adj_list_serialize.hpp +++ b/include/boost/graph/adj_list_serialize.hpp @@ -61,6 +61,8 @@ inline void save( ar << serialization::make_nvp("v" , indices[target(e,graph)]); ar << serialization::make_nvp("edge_property", get(edge_all_t(), graph, e) ); } + + ar << serialization::make_nvp("graph_property", get_property(graph, graph_all_t()) ); } @@ -95,6 +97,7 @@ inline void load( boost::tie(e,inserted) = add_edge(verts[u], verts[v], graph); ar >> serialization::make_nvp("edge_property", get(edge_all_t(), graph, e) ); } + ar >> serialization::make_nvp("graph_property", get_property(graph, graph_all_t()) ); } template diff --git a/include/boost/graph/graph_traits.hpp b/include/boost/graph/graph_traits.hpp index eb0232d8f..625429e61 100644 --- a/include/boost/graph/graph_traits.hpp +++ b/include/boost/graph/graph_traits.hpp @@ -235,17 +235,17 @@ namespace boost { struct graph_property_type : boost::mpl::eval_if, detail::get_graph_property_type, - boost::mpl::void_> {}; + no_property> {}; template struct edge_property_type : boost::mpl::eval_if, detail::get_edge_property_type, - boost::mpl::void_> {}; + no_property> {}; template struct vertex_property_type : boost::mpl::eval_if, detail::get_vertex_property_type, - boost::mpl::void_> {}; + no_property> {}; template struct graph_bundle_type { From 771d9307cc76ab23db031dfceeb0fd70f66a45a1 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Wed, 28 Mar 2012 20:57:02 +0000 Subject: [PATCH 146/333] Added forwarding of values of property tags to fix bundled properties [SVN r77616] --- include/boost/graph/compressed_sparse_row_graph.hpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/include/boost/graph/compressed_sparse_row_graph.hpp b/include/boost/graph/compressed_sparse_row_graph.hpp index f4ff2dc86..a26fd977e 100644 --- a/include/boost/graph/compressed_sparse_row_graph.hpp +++ b/include/boost/graph/compressed_sparse_row_graph.hpp @@ -1383,26 +1383,26 @@ edges(const BOOST_CSR_GRAPH_TYPE& g) // Graph properties template inline void -set_property(BOOST_CSR_GRAPH_TYPE& g, Tag, const Value& value) +set_property(BOOST_CSR_GRAPH_TYPE& g, Tag tag, const Value& value) { - get_property_value(g.m_property, Tag()) = value; + get_property_value(g.m_property, tag) = value; } template inline typename graph_property::type& -get_property(BOOST_CSR_GRAPH_TYPE& g, Tag) +get_property(BOOST_CSR_GRAPH_TYPE& g, Tag tag) { - return get_property_value(g.m_property, Tag()); + return get_property_value(g.m_property, tag); } template inline const typename graph_property::type& -get_property(const BOOST_CSR_GRAPH_TYPE& g, Tag) +get_property(const BOOST_CSR_GRAPH_TYPE& g, Tag tag) { - return get_property_value(g.m_property, Tag()); + return get_property_value(g.m_property, tag); } template From 5d1e1ce628bb4c051038d704cd82b8bb09ee7e8d Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Thu, 29 Mar 2012 18:42:04 +0000 Subject: [PATCH 147/333] Changed more things to inheritance to allow more SFINAE and fixed accessibility problem [SVN r77632] --- include/boost/graph/detail/adjacency_list.hpp | 53 +++++++------------ include/boost/graph/properties.hpp | 36 ++++++------- include/boost/graph/undirected_graph.hpp | 6 +-- 3 files changed, 35 insertions(+), 60 deletions(-) diff --git a/include/boost/graph/detail/adjacency_list.hpp b/include/boost/graph/detail/adjacency_list.hpp index a3ea40aab..cab4cecbc 100644 --- a/include/boost/graph/detail/adjacency_list.hpp +++ b/include/boost/graph/detail/adjacency_list.hpp @@ -2574,14 +2574,13 @@ namespace boost { }; namespace detail { template - struct adj_list_choose_vertex_pa { - typedef typename - boost::mpl::if_, adj_list_all_vertex_pa, adj_list_any_vertex_pa>::type - Helper; - typedef typename Helper::template bind_ Bind; - typedef typename Bind::type type; - typedef typename Bind::const_type const_type; - }; + struct adj_list_choose_vertex_pa + : boost::mpl::if_< + boost::is_same, + adj_list_all_vertex_pa, + adj_list_any_vertex_pa>::type + ::template bind_ + {}; template @@ -2597,12 +2596,9 @@ namespace boost { typedef vec_adj_list_all_vertex_pa type; }; template - struct vec_adj_list_choose_vertex_pa { - typedef typename vec_adj_list_choose_vertex_pa_helper::type Helper; - typedef typename Helper::template bind_ Bind; - typedef typename Bind::type type; - typedef typename Bind::const_type const_type; - }; + struct vec_adj_list_choose_vertex_pa + : vec_adj_list_choose_vertex_pa_helper::type::template bind_ + {}; } // namespace detail //========================================================================= @@ -2693,19 +2689,12 @@ namespace boost { typedef adj_list_all_edge_pmap type; }; template - struct adj_list_choose_edge_pmap { - typedef typename adj_list_choose_edge_pmap_helper::type Helper; - typedef typename Helper::template bind_ Bind; - typedef typename Bind::type type; - typedef typename Bind::const_type const_type; - }; + struct adj_list_choose_edge_pmap + : adj_list_choose_edge_pmap_helper::type::template bind_ + {}; struct adj_list_edge_property_selector { template - struct bind_ { - typedef adj_list_choose_edge_pmap Choice; - typedef typename Choice::type type; - typedef typename Choice::const_type const_type; - }; + struct bind_: adj_list_choose_edge_pmap {}; }; } // namespace detail @@ -2722,11 +2711,9 @@ namespace boost { struct adj_list_vertex_property_selector { template - struct bind_ { - typedef detail::adj_list_choose_vertex_pa Choice; - typedef typename Choice::type type; - typedef typename Choice::const_type const_type; - }; + struct bind_ + : detail::adj_list_choose_vertex_pa + {}; }; template <> struct vertex_property_selector { @@ -2735,11 +2722,7 @@ namespace boost { struct vec_adj_list_vertex_property_selector { template - struct bind_ { - typedef detail::vec_adj_list_choose_vertex_pa Choice; - typedef typename Choice::type type; - typedef typename Choice::const_type const_type; - }; + struct bind_: detail::vec_adj_list_choose_vertex_pa {}; }; template <> struct vertex_property_selector { diff --git a/include/boost/graph/properties.hpp b/include/boost/graph/properties.hpp index 6656d962e..6b5ade974 100644 --- a/include/boost/graph/properties.hpp +++ b/include/boost/graph/properties.hpp @@ -205,27 +205,23 @@ namespace boost { }; template - struct edge_property_map { - typedef typename edge_property_type::type Property; - typedef typename graph_tag_or_void::type graph_tag; - typedef typename edge_property_selector::type Selector; - typedef typename Selector::template bind_ - Bind; - typedef typename Bind::type type; - typedef typename Bind::const_type const_type; - }; + struct edge_property_map + : edge_property_selector< + typename graph_tag_or_void::type + >::type::template bind_< + Graph, + typename edge_property_type::type, + PropertyTag> + {}; template - class vertex_property_map { - public: - typedef typename vertex_property_type::type Property; - typedef typename graph_tag_or_void::type graph_tag; - typedef typename vertex_property_selector::type Selector; - typedef typename Selector::template bind_ - Bind; - public: - typedef typename Bind::type type; - typedef typename Bind::const_type const_type; - }; + struct vertex_property_map + : vertex_property_selector< + typename graph_tag_or_void::type + >::type::template bind_< + Graph, + typename vertex_property_type::type, + PropertyTag> + {}; } // namespace detail template diff --git a/include/boost/graph/undirected_graph.hpp b/include/boost/graph/undirected_graph.hpp index 884f5dbe8..b22fb9597 100644 --- a/include/boost/graph/undirected_graph.hpp +++ b/include/boost/graph/undirected_graph.hpp @@ -529,11 +529,7 @@ remove_in_edge_if(typename UNDIRECTED_GRAPH::vertex_descriptor v, { return remove_in_edge_if(v, pred, g.impl()); } template -struct property_map { - typedef typename UNDIRECTED_GRAPH::graph_type Graph; - typedef typename property_map::type type; - typedef typename property_map::const_type const_type; -}; +struct property_map: property_map {}; // PropertyGraph concepts template From 428762da2b07e45623d6422beb2e80b41e9c195a Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Thu, 29 Mar 2012 18:42:53 +0000 Subject: [PATCH 148/333] Keeping tag values around to allow bundled properties [SVN r77633] --- include/boost/graph/graph_test.hpp | 10 +++++----- include/boost/graph/stanford_graph.hpp | 8 ++++++-- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/include/boost/graph/graph_test.hpp b/include/boost/graph/graph_test.hpp index 7b3a5402b..69d89f34f 100644 --- a/include/boost/graph/graph_test.hpp +++ b/include/boost/graph/graph_test.hpp @@ -325,10 +325,10 @@ namespace boost { template void test_readable_vertex_property_graph - (const std::vector& vertex_prop, PropertyTag, const Graph& g) + (const std::vector& vertex_prop, PropertyTag tag, const Graph& g) { typedef typename property_map::const_type const_Map; - const_Map pmap = get(PropertyTag(), g); + const_Map pmap = get(tag, g); typename std::vector::const_iterator i = vertex_prop.begin(); for (typename boost::graph_traits::vertex_iterator @@ -339,7 +339,7 @@ namespace boost { ++bgl_first_9) { //BGL_FORALL_VERTICES_T(v, g, Graph) { typename property_traits::value_type - pval1 = get(pmap, v), pval2 = get(PropertyTag(), g, v); + pval1 = get(pmap, v), pval2 = get(tag, g, v); BOOST_CHECK(pval1 == pval2); BOOST_CHECK(pval1 == *i++); } @@ -350,7 +350,7 @@ namespace boost { (const std::vector& vertex_prop, PropertyTag tag, Graph& g) { typedef typename property_map::type PMap; - PMap pmap = get(PropertyTag(), g); + PMap pmap = get(tag, g); typename std::vector::const_iterator i = vertex_prop.begin(); for (typename boost::graph_traits::vertex_iterator bgl_first_9 = vertices(g).first, bgl_last_9 = vertices(g).second; @@ -368,7 +368,7 @@ namespace boost { typename std::vector::const_iterator j = vertex_prop.begin(); BGL_FORALL_VERTICES_T(v, g, Graph) - put(PropertyTag(), g, v, *j++); + put(tag, g, v, *j++); test_readable_vertex_property_graph(vertex_prop, tag, g); } diff --git a/include/boost/graph/stanford_graph.hpp b/include/boost/graph/stanford_graph.hpp index 0bb798c0f..89f5e34b2 100644 --- a/include/boost/graph/stanford_graph.hpp +++ b/include/boost/graph/stanford_graph.hpp @@ -318,13 +318,15 @@ namespace boost { class sgb_vertex_util_map : public boost::put_get_helper > { + Tag tag; public: + explicit sgb_vertex_util_map(Tag tag = Tag()): tag(tag) {} typedef boost::lvalue_property_map_tag category; typedef typename Tag::type value_type; typedef Vertex* key_type; typedef Ref reference; reference operator[](Vertex* v) const { - return get_util_field(v, Tag()); + return get_util_field(v, tag); } }; @@ -333,13 +335,15 @@ namespace boost { class sgb_edge_util_map : public boost::put_get_helper > { + Tag tag; public: + explicit sgb_edge_util_map(Tag tag = Tag()): tag(tag) {} typedef boost::lvalue_property_map_tag category; typedef typename Tag::type value_type; typedef Vertex* key_type; typedef Ref reference; reference operator[](const sgb_edge& e) const { - return get_util_field(e._arc, Tag()); + return get_util_field(e._arc, tag); } }; From eaebaf87a6c84c38d5cc7df4e3d9320be38891c9 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Thu, 29 Mar 2012 18:43:26 +0000 Subject: [PATCH 149/333] Fixing things so bundled graph properties will not crash [SVN r77634] --- include/boost/graph/adjacency_list.hpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/include/boost/graph/adjacency_list.hpp b/include/boost/graph/adjacency_list.hpp index 7b121637a..21b7500d2 100644 --- a/include/boost/graph/adjacency_list.hpp +++ b/include/boost/graph/adjacency_list.hpp @@ -393,20 +393,20 @@ namespace boost { #define ADJLIST adjacency_list template - inline void set_property(ADJLIST& g, Tag, Value const& value) { - get_property_value(*g.m_property, Tag()) = value; + inline void set_property(ADJLIST& g, Tag tag, Value const& value) { + get_property_value(*g.m_property, tag) = value; } template inline typename graph_property::type& - get_property(ADJLIST& g, Tag) { - return get_property_value(*g.m_property, Tag()); + get_property(ADJLIST& g, Tag tag) { + return get_property_value(*g.m_property, tag); } template inline typename graph_property::type const& - get_property(ADJLIST const& g, Tag) { - return get_property_value(*g.m_property, Tag()); + get_property(ADJLIST const& g, Tag tag) { + return get_property_value(*g.m_property, tag); } // dwa 09/25/00 - needed to be more explicit so reverse_graph would work. From d70d07b0ba517862650bedcdcefc8f63a9ada02f Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Fri, 30 Mar 2012 17:50:17 +0000 Subject: [PATCH 150/333] Trying to fix choose_pmap on more compilers [SVN r77650] --- include/boost/graph/named_function_params.hpp | 45 ++++++++++--------- 1 file changed, 25 insertions(+), 20 deletions(-) diff --git a/include/boost/graph/named_function_params.hpp b/include/boost/graph/named_function_params.hpp index ea4690b6e..0d65a032c 100644 --- a/include/boost/graph/named_function_params.hpp +++ b/include/boost/graph/named_function_params.hpp @@ -272,40 +272,45 @@ BOOST_BGL_DECLARE_NAMED_PARAMS property_map >, boost::mpl::identity > {}; - // Parameters are (NotFound, GraphIsConst, Graph, Param, Tag) - template - typename property_map::const_type - choose_impl(boost::mpl::true_, boost::mpl::true_, const Graph& g, const Param&, PropertyTag tag) { - return get(tag, g); - } + // Parameters of f are (GraphIsConst, Graph, Param, Tag) + template struct choose_impl_helper; + + template <> struct choose_impl_helper { + template + static typename property_map::const_type + f(boost::mpl::true_, const Graph& g, const Param&, PropertyTag tag) { + return get(tag, g); + } - template - typename property_map::type - choose_impl(boost::mpl::true_, boost::mpl::false_, Graph& g, const Param&, PropertyTag tag) { - return get(tag, g); - } + template + static typename property_map::type + f(boost::mpl::false_, Graph& g, const Param&, PropertyTag tag) { + return get(tag, g); + } + }; - template - Param - choose_impl(boost::mpl::false_, GraphIsConst, const Graph&, const Param& p, PropertyTag) { - return p; - } + template <> struct choose_impl_helper { + template + static Param f(GraphIsConst, const Graph&, const Param& p, PropertyTag) { + return p; + } + }; } template typename detail::choose_impl_result::type choose_const_pmap(const Param& p, const Graph& g, PropertyTag tag) { - return detail::choose_impl(boost::mpl::bool_::value>(), - boost::mpl::true_(), g, p, tag); + return detail::choose_impl_helper::value> + ::f(boost::mpl::true_(), g, p, tag); } template typename detail::choose_impl_result::type choose_pmap(const Param& p, Graph& g, PropertyTag tag) { - return detail::choose_impl(boost::mpl::bool_::value>(), - boost::mpl::false_(), g, p, tag); + return detail::choose_impl_helper::value> + ::f(boost::mpl::false_(), g, p, tag); } namespace detail { From 8ecd3a986c71ddb035f7963e31a684ae5e568aba Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Sun, 1 Apr 2012 19:23:18 +0000 Subject: [PATCH 151/333] Disabling abort for Windows CE [SVN r77693] --- include/boost/graph/isomorphism.hpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/include/boost/graph/isomorphism.hpp b/include/boost/graph/isomorphism.hpp index f8e448675..a3e036d73 100644 --- a/include/boost/graph/isomorphism.hpp +++ b/include/boost/graph/isomorphism.hpp @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -309,7 +310,14 @@ fi_adj_loop_k:++fi_adj.first; case match_continuation::pos_G2_vertex_loop: {G2_verts = this_k.G2_verts; iter = this_k.iter; dfs_num_k = this_k.dfs_num_k; k.pop_back(); in_S[*G2_verts.first] = false; i = source(*iter, G1); j = target(*iter, G2); goto G2_loop_k;} case match_continuation::pos_fi_adj_loop: {fi_adj = this_k.fi_adj; iter = this_k.iter; dfs_num_k = this_k.dfs_num_k; k.pop_back(); in_S[*fi_adj.first] = false; i = source(*iter, G1); j = target(*iter, G2); goto fi_adj_loop_k;} case match_continuation::pos_dfs_num: {k.pop_back(); goto return_point_false;} - default: assert (!"Bad position"); abort(); + default: { + BOOST_ASSERT(!"Bad position"); +#ifdef UNDER_CE + exit(-1); +#else + abort(); +#endif + } } } } From 63200dc0eae2949b90d81953defab70396682340 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Tue, 3 Apr 2012 04:39:03 +0000 Subject: [PATCH 152/333] Added null_vertex() required by Graph concept [SVN r77730] --- include/boost/graph/graph_archetypes.hpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/include/boost/graph/graph_archetypes.hpp b/include/boost/graph/graph_archetypes.hpp index 9b364bb81..81f9c2c8a 100644 --- a/include/boost/graph/graph_archetypes.hpp +++ b/include/boost/graph/graph_archetypes.hpp @@ -53,6 +53,8 @@ namespace boost { // should use a different namespace for this typedef void in_edge_iterator; typedef void vertex_iterator; typedef void edge_iterator; + + static vertex_descriptor null_vertex() {return vertex_descriptor();} }; template V source(const typename incidence_graph_archetype::edge_descriptor&, @@ -105,6 +107,8 @@ namespace boost { // should use a different namespace for this typedef void out_edge_iterator; typedef void vertex_iterator; typedef void edge_iterator; + + static vertex_descriptor null_vertex() {return vertex_descriptor();} }; template @@ -154,6 +158,8 @@ namespace boost { // should use a different namespace for this typedef void in_edge_iterator; typedef void edge_iterator; + + static vertex_descriptor null_vertex() {return vertex_descriptor();} }; template From 30026490ee945da1e8e1e94c9e9d4b43d2515b21 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Tue, 3 Apr 2012 04:42:25 +0000 Subject: [PATCH 153/333] Changed to manual token-testing code to avoid use of Boost.Xpressive (allowing use on more compilers) [SVN r77731] --- include/boost/graph/graphviz.hpp | 36 ++++++++++++++++++++++++++++++-- 1 file changed, 34 insertions(+), 2 deletions(-) diff --git a/include/boost/graph/graphviz.hpp b/include/boost/graph/graphviz.hpp index aedce5553..50ee5d9b2 100644 --- a/include/boost/graph/graphviz.hpp +++ b/include/boost/graph/graphviz.hpp @@ -15,6 +15,7 @@ #include #include #include +#include #include // for FILE #include #include @@ -31,7 +32,9 @@ #include #include #include +#if 0 #include +#endif #include namespace boost { @@ -65,10 +68,39 @@ namespace boost { template inline std::string escape_dot_string(const T& obj) { + std::string s(boost::lexical_cast(obj)); +#if 0 using namespace boost::xpressive; static sregex valid_unquoted_id = (((alpha | '_') >> *_w) | (!as_xpr('-') >> (('.' >> *_d) | (+_d >> !('.' >> *_d))))); - std::string s(boost::lexical_cast(obj)); - if (regex_match(s, valid_unquoted_id)) { + bool ok = regex_match(s, valid_unquoted_id); +#else + bool ok; + using std::isdigit; using std::isalpha; + if (s.empty()) { + ok = false; + } else if (isdigit(s[0]) || s[0] == '-' || s[0] == '.') { // Number + size_t startpos = (s[0] == '-' ? 1 : 0); + size_t dot_maybe = s.find('.', startpos); + if (dot_maybe != std::string::npos && s.find('.', dot_maybe + 1) != std::string::npos) { + ok = false; // Has two decimal points + } else { + for (size_t i = startpos; i < s.size(); ++i) { + if (!(isdigit(s[i]) || s[i] == '.')) {ok = false; break;} + } + } + } else if (isalpha(s[0]) || s[0] == '_') { // Identifier + ok = true; + for (size_t i = 1; i < s.size(); ++i) { + if (!(isalpha(s[i]) || isdigit(s[i]) || s[i] == '_')) { + ok = false; + break; + } + } + } else { + ok = false; + } +#endif + if (ok) { return s; } else { boost::algorithm::replace_all(s, "\"", "\\\""); From 755c77e7c139b045172fda8ba2f819ee018d418c Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Tue, 3 Apr 2012 04:44:08 +0000 Subject: [PATCH 154/333] Added functions to get null_vertex and default starting vertex, added code to generate wrappers to allow user-visible Boost.Parameter-enabled versions of BGL functions [SVN r77732] --- include/boost/graph/named_function_params.hpp | 50 +++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/include/boost/graph/named_function_params.hpp b/include/boost/graph/named_function_params.hpp index 0d65a032c..15d216b39 100644 --- a/include/boost/graph/named_function_params.hpp +++ b/include/boost/graph/named_function_params.hpp @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -463,6 +464,36 @@ BOOST_BGL_DECLARE_NAMED_PARAMS >()(g, ap[t | 0]); } +#define BOOST_GRAPH_MAKE_FORWARDING_FUNCTION(name, nfixed, nnamed_max) \ + /* Entry point for conversion from BGL-style named parameters */ \ + template \ + typename detail::BOOST_PP_CAT(name, _impl)::result_type \ + BOOST_PP_CAT(name, _with_named_params)(BOOST_PP_ENUM_BINARY_PARAMS(nfixed, const Param, & param) BOOST_PP_COMMA_IF(nfixed) const ArgPack& arg_pack) { \ + return detail::BOOST_PP_CAT(name, _impl)()(BOOST_PP_ENUM_PARAMS(nfixed, param) BOOST_PP_COMMA_IF(nfixed) arg_pack); \ + } \ + /* Individual functions taking Boost.Parameter-style keyword arguments */ \ + BOOST_PP_REPEAT(nnamed_max, BOOST_GRAPH_MAKE_FORWARDING_FUNCTION_ONE, (name)(nfixed)) + +#define BOOST_GRAPH_MAKE_FORWARDING_FUNCTION_ONE(z, nnamed, seq) \ + BOOST_GRAPH_MAKE_FORWARDING_FUNCTION_ONEX(z, nnamed, BOOST_PP_SEQ_ELEM(0, seq), BOOST_PP_SEQ_ELEM(1, seq)) + +#define BOOST_GRAPH_MAKE_FORWARDING_FUNCTION_ONEX(z, nnamed, name, nfixed) \ + template \ + typename detail::BOOST_PP_CAT(name, _impl)::result_type \ + name(BOOST_PP_ENUM_BINARY_PARAMS(nfixed, const Param, & param) \ + BOOST_PP_ENUM_TRAILING(nnamed, BOOST_GRAPH_MAKE_PAIR_PARAM, ~)) { \ + return detail::BOOST_PP_CAT(name, _impl)() \ + (BOOST_PP_ENUM_PARAMS(nfixed, param), \ + (boost::parameter::aux::empty_arg_list() BOOST_PP_ENUM_TRAILING_PARAMS(nnamed, kw))); \ + } + +#define BOOST_GRAPH_TEMPLATE_ARGS_FOR_IMPL(nnamed, nfixed) \ + BOOST_PP_ENUM_PARAMS(nfixed, Param), \ + BOOST_PP_REPEAT(nnamed, BOOST_GRAPH_OPENING_PART_OF_PAIR, BOOST_PP_DEC(nnamed)) boost::parameter::aux::empty_arg_list BOOST_PP_REPEAT(nnamed, > BOOST_PP_TUPLE_EAT(3), ~) + +#define BOOST_GRAPH_OPENING_PART_OF_PAIR(z, i, n) boost::parameter::aux::arg_list, +#define BOOST_GRAPH_MAKE_PAIR_PARAM(z, i, _) const boost::parameter::aux::tagged_argument& BOOST_PP_CAT(kw, i) + } namespace detail { @@ -619,6 +650,25 @@ BOOST_BGL_DECLARE_NAMED_PARAMS } }; + template + typename boost::graph_traits::vertex_descriptor + get_null_vertex(const G&) {return boost::graph_traits::null_vertex();} + + template + typename boost::graph_traits::vertex_descriptor + get_default_starting_vertex(const G& g) { + std::pair::vertex_iterator, typename boost::graph_traits::vertex_iterator> iters = vertices(g); + return (iters.first == iters.second) ? boost::graph_traits::null_vertex() : *iters.first; + } + + template + struct get_default_starting_vertex_t { + typedef typename boost::graph_traits::vertex_descriptor result_type; + const G& g; + get_default_starting_vertex_t(const G& g): g(g) {} + result_type operator()() const {return get_default_starting_vertex(g);} + }; + } // namespace detail } // namespace boost From ce845156b8a69ad6f32bb2db2ae5290374dbb0b5 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Tue, 3 Apr 2012 04:44:40 +0000 Subject: [PATCH 155/333] Added null_vertex() [SVN r77733] --- include/boost/graph/vector_as_graph.hpp | 1 + 1 file changed, 1 insertion(+) diff --git a/include/boost/graph/vector_as_graph.hpp b/include/boost/graph/vector_as_graph.hpp index c1799993c..7bc8ac380 100644 --- a/include/boost/graph/vector_as_graph.hpp +++ b/include/boost/graph/vector_as_graph.hpp @@ -79,6 +79,7 @@ namespace boost { typedef typename std::vector::size_type vertices_size_type; typedef void edges_size_type; typedef typename EdgeList::size_type degree_size_type; + static V null_vertex() {return V(-1);} }; template struct edge_property_type< std::vector > From aaedb9bac7c8167909d7a04a84e24a334503c76b Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Tue, 3 Apr 2012 04:45:47 +0000 Subject: [PATCH 156/333] Added user-visible Boost.Parameter version; changed to use new wrapper functions, and to allow old named-parameter version to call it, changed detection of starting vertex [SVN r77734] --- include/boost/graph/depth_first_search.hpp | 30 ++++++++++++++++------ 1 file changed, 22 insertions(+), 8 deletions(-) diff --git a/include/boost/graph/depth_first_search.hpp b/include/boost/graph/depth_first_search.hpp index d38ad603d..3e461dc10 100644 --- a/include/boost/graph/depth_first_search.hpp +++ b/include/boost/graph/depth_first_search.hpp @@ -21,6 +21,7 @@ #include #include #include +#include #include #include @@ -198,7 +199,7 @@ namespace boost { put(color, u, Color::white()); vis.initialize_vertex(u, g); } - if (start_vertex != implicit_cast(*vertices(g).first)){ vis.start_vertex(start_vertex, g); + if (start_vertex != detail::get_default_starting_vertex(g)){ vis.start_vertex(start_vertex, g); detail::depth_first_visit_impl(g, start_vertex, vis, color, detail::nontruth2()); } @@ -221,7 +222,7 @@ namespace boost { if (verts.first == verts.second) return; - depth_first_search(g, vis, color, *verts.first); + depth_first_search(g, vis, color, detail::get_default_starting_vertex(g)); } template @@ -282,6 +283,24 @@ namespace boost { } typedef dfs_visitor<> default_dfs_visitor; + // Boost.Parameter named parameter variant + namespace graph { + namespace detail { + template + struct depth_first_search_impl { + typedef void result_type; + void operator()(const Graph& g, const ArgPack& arg_pack) { + using namespace boost::graph::keywords; + boost::depth_first_search(g, + arg_pack[_visitor | make_dfs_visitor(null_visitor())], + boost::detail::make_color_map_from_arg_pack(g, arg_pack), + arg_pack[_root_vertex || boost::detail::get_default_starting_vertex_t(g)]); + } + }; + } + BOOST_GRAPH_MAKE_FORWARDING_FUNCTION(depth_first_search, 1, 4) + } + // Named Parameter Variant template void @@ -295,12 +314,7 @@ namespace boost { using namespace boost::graph::keywords; typedef bgl_named_params params_type; BOOST_GRAPH_DECLARE_CONVERTED_PARAMETERS(params_type, params) - depth_first_search - (g, - arg_pack[_visitor | make_dfs_visitor(null_visitor())], - boost::detail::make_color_map_from_arg_pack(g, arg_pack), - arg_pack[_root_vertex | *vertices(g).first] - ); + boost::graph::depth_first_search_with_named_params(g, arg_pack); } template From 7d3b9f0b4bec4e1b51748258b795ce103ac2b05d Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Tue, 3 Apr 2012 05:49:07 +0000 Subject: [PATCH 157/333] Qualified call to isomorphism [SVN r77735] --- include/boost/graph/is_kuratowski_subgraph.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/boost/graph/is_kuratowski_subgraph.hpp b/include/boost/graph/is_kuratowski_subgraph.hpp index 8791b4cf1..668043ab4 100644 --- a/include/boost/graph/is_kuratowski_subgraph.hpp +++ b/include/boost/graph/is_kuratowski_subgraph.hpp @@ -301,11 +301,11 @@ namespace boost if (target_graph == detail::tg_k_5) { - return isomorphism(K_5,contracted_graph); + return boost::isomorphism(K_5,contracted_graph); } else //target_graph == tg_k_3_3 { - return isomorphism(K_3_3,contracted_graph); + return boost::isomorphism(K_3_3,contracted_graph); } From 28cf285c4ddad1332491277fd826f16c7acb0b87 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Tue, 3 Apr 2012 05:49:36 +0000 Subject: [PATCH 158/333] Added no-named-parameter version and simplified code [SVN r77736] --- include/boost/graph/depth_first_search.hpp | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/include/boost/graph/depth_first_search.hpp b/include/boost/graph/depth_first_search.hpp index 3e461dc10..c5ce5053c 100644 --- a/include/boost/graph/depth_first_search.hpp +++ b/include/boost/graph/depth_first_search.hpp @@ -289,7 +289,7 @@ namespace boost { template struct depth_first_search_impl { typedef void result_type; - void operator()(const Graph& g, const ArgPack& arg_pack) { + void operator()(const Graph& g, const ArgPack& arg_pack) const { using namespace boost::graph::keywords; boost::depth_first_search(g, arg_pack[_visitor | make_dfs_visitor(null_visitor())], @@ -307,16 +307,19 @@ namespace boost { depth_first_search(const VertexListGraph& g, const bgl_named_params& params) { - typedef typename boost::graph_traits::vertex_iterator vi; - std::pair verts = vertices(g); - if (verts.first == verts.second) - return; - using namespace boost::graph::keywords; typedef bgl_named_params params_type; BOOST_GRAPH_DECLARE_CONVERTED_PARAMETERS(params_type, params) boost::graph::depth_first_search_with_named_params(g, arg_pack); } + template + void + depth_first_search(const VertexListGraph& g) + { + BOOST_GRAPH_DECLARE_CONVERTED_PARAMETERS(no_named_parameters, no_named_parameters()) + boost::graph::depth_first_search_with_named_params(g, arg_pack); + } + template void depth_first_visit (const IncidenceGraph& g, From 8400e599ca61e4c60f0aefba9fa04e005d30c373 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Tue, 3 Apr 2012 05:50:09 +0000 Subject: [PATCH 159/333] Starting on converting to Boost.Parameter; not finished yet because of interaction with PBGL [SVN r77737] --- include/boost/graph/breadth_first_search.hpp | 47 +++++++++++++++++++- 1 file changed, 46 insertions(+), 1 deletion(-) diff --git a/include/boost/graph/breadth_first_search.hpp b/include/boost/graph/breadth_first_search.hpp index 3af85f3f7..80683204e 100644 --- a/include/boost/graph/breadth_first_search.hpp +++ b/include/boost/graph/breadth_first_search.hpp @@ -322,7 +322,7 @@ namespace boost { } // namespace detail - +#if 1 // Named Parameter Variant template void breadth_first_search @@ -339,6 +339,7 @@ namespace boost { detail::bfs_dispatch::apply(ng, s, params, get_param(params, vertex_color)); } +#endif // This version does not initialize colors, user has to. @@ -370,6 +371,50 @@ namespace boost { ); } + namespace graph { + namespace detail { + template + struct breadth_first_search_impl { + typedef void result_type; + void operator()(const Graph& g, const Source& source, const ArgPack& arg_pack) { + using namespace boost::graph::keywords; + typename boost::graph_traits::vertex_descriptor sources[1] = {source}; + boost::queue::vertex_descriptor> Q; + boost::breadth_first_search(g, + &sources[0], + &sources[1], + boost::unwrap_ref(arg_pack[_buffer | boost::ref(Q)]), + arg_pack[_visitor | make_bfs_visitor(null_visitor())], + boost::detail::make_color_map_from_arg_pack(g, arg_pack)); + } + }; + } + BOOST_GRAPH_MAKE_FORWARDING_FUNCTION(breadth_first_search, 2, 4) + } + +#if 0 + // Named Parameter Variant + template + void + breadth_first_search(const VertexListGraph& g, + typename graph_traits::vertex_descriptor s, + const bgl_named_params& params) + { + typedef bgl_named_params params_type; + BOOST_GRAPH_DECLARE_CONVERTED_PARAMETERS(params_type, params) + boost::graph::breadth_first_search_with_named_params(g, s, arg_pack); + } + + template + void + breadth_first_search(const VertexListGraph& g, + typename graph_traits::vertex_descriptor s) + { + BOOST_GRAPH_DECLARE_CONVERTED_PARAMETERS(no_named_parameters, no_named_parameters()) + boost::graph::breadth_first_search_with_named_params(g, s, arg_pack); + } +#endif + } // namespace boost #ifdef BOOST_GRAPH_USE_MPI From a4806bed3b281110214e7bd8c8b9814220563971 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Tue, 3 Apr 2012 05:50:29 +0000 Subject: [PATCH 160/333] Fixed off-by-one bug [SVN r77738] --- include/boost/graph/named_function_params.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/boost/graph/named_function_params.hpp b/include/boost/graph/named_function_params.hpp index 15d216b39..2eda0e873 100644 --- a/include/boost/graph/named_function_params.hpp +++ b/include/boost/graph/named_function_params.hpp @@ -472,7 +472,7 @@ BOOST_BGL_DECLARE_NAMED_PARAMS return detail::BOOST_PP_CAT(name, _impl)()(BOOST_PP_ENUM_PARAMS(nfixed, param) BOOST_PP_COMMA_IF(nfixed) arg_pack); \ } \ /* Individual functions taking Boost.Parameter-style keyword arguments */ \ - BOOST_PP_REPEAT(nnamed_max, BOOST_GRAPH_MAKE_FORWARDING_FUNCTION_ONE, (name)(nfixed)) + BOOST_PP_REPEAT(BOOST_PP_INC(nnamed_max), BOOST_GRAPH_MAKE_FORWARDING_FUNCTION_ONE, (name)(nfixed)) #define BOOST_GRAPH_MAKE_FORWARDING_FUNCTION_ONE(z, nnamed, seq) \ BOOST_GRAPH_MAKE_FORWARDING_FUNCTION_ONEX(z, nnamed, BOOST_PP_SEQ_ELEM(0, seq), BOOST_PP_SEQ_ELEM(1, seq)) From eeaee30dd31a154b7f5103239ffe18cfb81c338b Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Tue, 3 Apr 2012 05:50:40 +0000 Subject: [PATCH 161/333] Converted to Boost.Parameter [SVN r77739] --- include/boost/graph/isomorphism.hpp | 80 ++++++++++++++++++++++------- 1 file changed, 62 insertions(+), 18 deletions(-) diff --git a/include/boost/graph/isomorphism.hpp b/include/boost/graph/isomorphism.hpp index a3e036d73..c4950ccb0 100644 --- a/include/boost/graph/isomorphism.hpp +++ b/include/boost/graph/isomorphism.hpp @@ -467,9 +467,64 @@ fi_adj_loop_k:++fi_adj.first; index_map1, index_map2 ); } + + template + struct make_degree_invariant { + const G& g; + const Index& index; + make_degree_invariant(const G& g, const Index& index): g(g), index(index) {} + typedef typename boost::graph_traits::degree_size_type degree_size_type; + typedef shared_array_property_map prop_map_type; + typedef degree_vertex_invariant result_type; + result_type operator()() const { + prop_map_type pm = make_shared_array_property_map(num_vertices(g), degree_size_type(), index); + compute_in_degree(g, pm); + return result_type(pm, g); + } + }; } // namespace detail + namespace graph { + namespace detail { + template + struct isomorphism_impl { + typedef bool result_type; + bool operator()(const Graph1& g1, const Graph2& g2, const ArgPack& arg_pack) const { + using namespace boost::graph::keywords; + typedef typename boost::detail::override_const_property_result::type index1_map_type; + typedef typename boost::detail::override_const_property_result::type index2_map_type; + index1_map_type index1_map = boost::detail::override_const_property(arg_pack, _vertex_index1_map, g1, boost::vertex_index); + index2_map_type index2_map = boost::detail::override_const_property(arg_pack, _vertex_index2_map, g2, boost::vertex_index); + typedef typename graph_traits::vertex_descriptor vertex2_t; + typename std::vector::size_type n = (typename std::vector::size_type)num_vertices(g1); + std::vector f(n); + typename boost::parameter::lazy_binding< + ArgPack, + tag::vertex_invariant1, + boost::detail::make_degree_invariant >::type + invariant1 = + arg_pack[_vertex_invariant1 || boost::detail::make_degree_invariant(g1, index1_map)]; + typename boost::parameter::lazy_binding< + ArgPack, + tag::vertex_invariant2, + boost::detail::make_degree_invariant >::type + invariant2 = + arg_pack[_vertex_invariant2 || boost::detail::make_degree_invariant(g2, index2_map)]; + return boost::isomorphism + (g1, g2, + choose_param(arg_pack[_isomorphism_map | boost::param_not_found()], + make_shared_array_property_map(num_vertices(g1), vertex2_t(), index1_map)), + invariant1, + invariant2, + arg_pack[_vertex_max_invariant | (invariant2.max)()], + index1_map, + index2_map); + } + }; + } + BOOST_GRAPH_MAKE_FORWARDING_FUNCTION(isomorphism, 2, 6) + } // Named parameter interface template @@ -477,30 +532,19 @@ fi_adj_loop_k:++fi_adj.first; const Graph2& g2, const bgl_named_params& params) { - typedef typename graph_traits::vertex_descriptor vertex2_t; - typename std::vector::size_type n = num_vertices(g1); - std::vector f(n); - return detail::isomorphism_impl - (g1, g2, - choose_param(get_param(params, vertex_isomorphism_t()), - make_safe_iterator_property_map(f.begin(), f.size(), - choose_const_pmap(get_param(params, vertex_index1), - g1, vertex_index), vertex2_t())), - choose_const_pmap(get_param(params, vertex_index1), g1, vertex_index), - choose_const_pmap(get_param(params, vertex_index2), g2, vertex_index), - params - ); + typedef bgl_named_params params_type; + BOOST_GRAPH_DECLARE_CONVERTED_PARAMETERS(params_type, params) + return boost::graph::isomorphism_with_named_params(g1, g2, arg_pack); } - // All defaults interface template - bool isomorphism(const Graph1& g1, const Graph2& g2) + bool isomorphism(const Graph1& g1, + const Graph2& g2) { - return isomorphism(g1, g2, - bgl_named_params(0));// bogus named param + BOOST_GRAPH_DECLARE_CONVERTED_PARAMETERS(no_named_parameters, no_named_parameters()) + return boost::graph::isomorphism_with_named_params(g1, g2, arg_pack); } - // Verify that the given mapping iso_map from the vertices of g1 to the // vertices of g2 describes an isomorphism. // Note: this could be made much faster by specializing based on the graph From 3d43c1a8ecdf4a3b12ee20ffdf0b6f9247c74bba Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Tue, 10 Apr 2012 19:51:59 +0000 Subject: [PATCH 162/333] Added algorithm from Michele Caini for common spanning trees of two graphs; fixes #6401 [SVN r77893] --- doc/table_of_contents.html | 5 + doc/two_graphs_common_spanning_trees.html | 143 +++ example/Jamfile.v2 | 1 + example/two_graphs_common_spanning_trees.cpp | 94 ++ .../two_graphs_common_spanning_trees.hpp | 870 ++++++++++++++++++ test/Jamfile.v2 | 1 + .../two_graphs_common_spanning_trees_test.cpp | 148 +++ 7 files changed, 1262 insertions(+) create mode 100644 doc/two_graphs_common_spanning_trees.html create mode 100644 example/two_graphs_common_spanning_trees.cpp create mode 100644 include/boost/graph/two_graphs_common_spanning_trees.hpp create mode 100644 test/two_graphs_common_spanning_trees_test.cpp diff --git a/doc/table_of_contents.html b/doc/table_of_contents.html index 090053bb5..90f2b7546 100644 --- a/doc/table_of_contents.html +++ b/doc/table_of_contents.html @@ -186,6 +186,11 @@

      Table of Contents: the Boost Graph Library
    6. random_spanning_tree
    +
  • Algorithm for Common Spanning Trees of Two Graphs +
      +
    1. two_graphs_common_spanning_trees +
  • Connected Components Algorithms
    1. connected_components diff --git a/doc/two_graphs_common_spanning_trees.html b/doc/two_graphs_common_spanning_trees.html new file mode 100644 index 000000000..f06825b04 --- /dev/null +++ b/doc/two_graphs_common_spanning_trees.html @@ -0,0 +1,143 @@ + + + +Boost Graph Library: Two-Graphs Common Spanning Trees + +C++ Boost + +
      + +

      Two-Graphs Common Spanning Trees (MRT Algorithm)

      + +

      +The MRT algorithm, based on an academic article of Mint, Read and +Tarjan, is an efficient algorithm for the common spanning tree problem.
      +This kind of algorithm is widely used in electronics, being the basis of the +analysis of electrical circuits. Another area of interest may be that of the +networking. +

      + +

      +The proposed algorithm receives several arguments and works with callbacks.
      +The prototypes are: +

      + +

      +// Ordered Edges List +

      +template < typename Graph, typename Order, typename Func, typename Seq >
      +void two_graphs_common_spanning_trees
      +  (
      +    const Graph& iG,
      +    Order iG_map,
      +    const Graph& vG,
      +    Order vG_map,
      +    Func func,
      +    Seq inL
      +  )
      +
      + +// Unordered Edges List +
      +template < typename Graph, typename Func, typename Seq >
      +void two_graphs_common_spanning_trees
      +  (
      +    const Graph& iG,
      +    const Graph& vG,
      +    Func func,
      +    Seq inL
      +  )
      +
      +

      + +

      +The problem of common spanning tree is easily described.
      +Imagine we have two graphs that are represented as lists of edges. A common +spanning tree is a set of indices that identifies a spanning tree for both +the first and for the second of the two graphs. Despite it is easily accomplished +with edge list representation for graphs, it is intuitively difficult to achieve +with adjacency list representation. This is due to the fact that it is necessary +to represent an edge with an absolute index. +

      +

      +Note that the set of common spanning trees of the two graphs is a subset of +the set of spanning trees of the first graph, as well as those of the second +graph. +

      + +

      Where Defined

      + +

      +boost/graph/two_graphs_common_spanning_trees.hpp + +

      Parameters

      + +const Graph& iG, const Graph& vG +
      +These are the graphs to be analyzed.
      +They must comply with the concepts VertexAndEdgeListGraphConcept and IncidenceGraphConcept.
      +In addition, the directed_category should be of type undirected_tag. +
      + +Order iG_map, Order vG_map +
      +These are lists of references to edges, that define the preferred order for access to the lists of edges.
      +They must comply with the concept RandomAccessContainer. +
      + +Func func +
      +This is a callback that is invoked by the algorithm for each common spanning tree found.
      +It must comply with the concept UnaryFunction with void as return value, and an object of type typeof(inL) as argument. +
      + +Seq inL[1] +
      +This is the way in which the edges are marked as belonging to the common spanning tree.
      +It must comply with the concept Mutable_RandomAccessContainer. In addition, the value_type should be of type bool. +If the i-th edge or inL[i] is true, then it belongs to the common spanning tree, otherwise it does not belong. +
      + +

      Example

      + +

      +The file +examples/two_graphs_common_spanning_trees.cpp +contains an example of finding common spanning trees of two undirected graphs. +

      + +

      Notes

      + +

      +[1]
      + The presence of inL may seem senseless. The algorithm can use a vector of + placeholders internally generated. However, doing so has more flexibility on + the callback function. Moreover, being largely involved in the electronics + world, there are cases where some edges have to be forced in every tree (ie + you want to search all the trees that have the same root): With this + solution, the problem is easily solved.
      + Intuitively from the above, inL must be of a size equal to (V-1), where + V is the number of vertices of the graph. +

      + +
      +
      + + + + + +
      Copyright © 2012Michele Caini, (michele.caini@gmail.com)
      + + + diff --git a/example/Jamfile.v2 b/example/Jamfile.v2 index ca46194a4..b33b4f9df 100644 --- a/example/Jamfile.v2 +++ b/example/Jamfile.v2 @@ -38,3 +38,4 @@ exe adjacency_list_io : adjacency_list_io.cpp ; exe undirected_adjacency_list : undirected_adjacency_list.cpp ; exe directed_graph : directed_graph.cpp ; exe undirected_graph : undirected_graph.cpp ; +exe two_graphs_common_spanning_trees : two_graphs_common_spanning_trees.cpp ; diff --git a/example/two_graphs_common_spanning_trees.cpp b/example/two_graphs_common_spanning_trees.cpp new file mode 100644 index 000000000..5835aad5e --- /dev/null +++ b/example/two_graphs_common_spanning_trees.cpp @@ -0,0 +1,94 @@ +// Copyright (C) 2012, Michele Caini. +// 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) + +// Two Graphs Common Spanning Trees Algorithm +// Based on academic article of Mint, Read and Tarjan +// Efficient Algorithm for Common Spanning Tree Problem +// Electron. Lett., 28 April 1983, Volume 19, Issue 9, p.346–347 + + +#include +#include +#include +#include + + +using namespace std; + +typedef +boost::adjacency_list + < + boost::vecS, // OutEdgeList + boost::vecS, // VertexList + boost::undirectedS, // Directed + boost::no_property, // VertexProperties + boost::no_property, // EdgeProperties + boost::no_property, // GraphProperties + boost::listS // EdgeList + > +Graph +; + +typedef +boost::graph_traits::vertex_descriptor +vertex_descriptor; + +typedef +boost::graph_traits::edge_descriptor +edge_descriptor; + +typedef +boost::graph_traits::vertex_iterator +vertex_iterator; + +typedef +boost::graph_traits::edge_iterator +edge_iterator; + + +int main(int argc, char **argv) +{ + Graph iG, vG; + vector< edge_descriptor > iG_o; + vector< edge_descriptor > vG_o; + + iG_o.push_back(boost::add_edge(0, 1, iG).first); + iG_o.push_back(boost::add_edge(0, 2, iG).first); + iG_o.push_back(boost::add_edge(0, 3, iG).first); + iG_o.push_back(boost::add_edge(0, 4, iG).first); + iG_o.push_back(boost::add_edge(1, 2, iG).first); + iG_o.push_back(boost::add_edge(3, 4, iG).first); + + vG_o.push_back(boost::add_edge(1, 2, vG).first); + vG_o.push_back(boost::add_edge(2, 0, vG).first); + vG_o.push_back(boost::add_edge(2, 3, vG).first); + vG_o.push_back(boost::add_edge(4, 3, vG).first); + vG_o.push_back(boost::add_edge(0, 3, vG).first); + vG_o.push_back(boost::add_edge(0, 4, vG).first); + + vector inL(iG_o.size(), false); + + std::vector< std::vector > coll; + boost::tree_collector< + std::vector< std::vector >, + std::vector + > tree_collector(coll); + boost::two_graphs_common_spanning_trees + ( + iG, + iG_o, + vG, + vG_o, + tree_collector, + inL + ); + + std::vector< std::vector >::iterator it; + for(it = coll.begin(); it != coll.end(); ++it) { + // Here you can play with the trees that the algorithm has found. + } + + return 0; +} diff --git a/include/boost/graph/two_graphs_common_spanning_trees.hpp b/include/boost/graph/two_graphs_common_spanning_trees.hpp new file mode 100644 index 000000000..8a62a367f --- /dev/null +++ b/include/boost/graph/two_graphs_common_spanning_trees.hpp @@ -0,0 +1,870 @@ +// Copyright (C) 2012, Michele Caini. +// 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) + +// Two Graphs Common Spanning Trees Algorithm +// Based on academic article of Mint, Read and Tarjan +// Efficient Algorithm for Common Spanning Tree Problem +// Electron. Lett., 28 April 1983, Volume 19, Issue 9, p.346–347 + + +#ifndef BOOST_GRAPH_TWO_GRAPHS_COMMON_SPANNING_TREES_HPP +#define BOOST_GRAPH_TWO_GRAPHS_COMMON_SPANNING_TREES_HPP + + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +namespace boost +{ + + +namespace detail { + + + template + < + typename TreeMap, + typename PredMap, + typename DistMap, + typename LowMap, + typename Buffer + > + struct bridges_visitor: public default_dfs_visitor + { + bridges_visitor( + TreeMap tree, + PredMap pred, + DistMap dist, + LowMap low, + Buffer& buffer + ): mTree(tree), mPred(pred), mDist(dist), mLow(low), mBuffer(buffer) + { mNum = -1; } + + template + void initialize_vertex(const Vertex& u, const Graph& g) + { + put(mPred, u, u); + put(mDist, u, -1); + } + + template + void discover_vertex(const Vertex& u, const Graph& g) + { + put(mDist, u, ++mNum); + put(mLow, u, get(mDist, u)); + } + + template + void tree_edge(const Edge& e, const Graph& g) + { + put(mPred, target(e, g), source(e, g)); + put(mTree, target(e, g), e); + } + + template + void back_edge(const Edge& e, const Graph& g) + { + put(mLow, source(e, g), + std::min(get(mLow, source(e, g)), get(mDist, target(e, g)))); + } + + template + void finish_vertex(const Vertex& u, const Graph& g) + { + Vertex parent = get(mPred, u); + if(get(mLow, u) > get(mDist, parent)) + mBuffer.push(get(mTree, u)); + put(mLow, parent, + std::min(get(mLow, parent), get(mLow, u))); + } + + TreeMap mTree; + PredMap mPred; + DistMap mDist; + LowMap mLow; + Buffer& mBuffer; + int mNum; + }; + + + template + struct cycle_finder: public base_visitor< cycle_finder > + { + typedef on_back_edge event_filter; + cycle_finder(): mBuffer(0) { } + cycle_finder(Buffer* buffer) + : mBuffer(buffer) { } + template + void operator()(const Edge& e, const Graph& g) + { + if(mBuffer) + mBuffer->push(e); + } + Buffer* mBuffer; + }; + + + template + struct deleted_edge_status + { + deleted_edge_status() { } + deleted_edge_status(DeletedMap map): mMap(map) { } + template + bool operator()(const Edge& e) const + { return (!get(mMap, e)); } + DeletedMap mMap; + }; + + + template + struct inL_edge_status + { + inL_edge_status() { } + inL_edge_status(InLMap map): mMap(map) { } + template + bool operator()(const Edge& e) const + { return get(mMap, e); } + InLMap mMap; + }; + + + template < + typename Graph, + typename Func, + typename Seq, + typename Map + > + void rec_two_graphs_common_spanning_trees + ( + const Graph& iG, + bimap< + bimaps::set_of, + bimaps::set_of< typename graph_traits::edge_descriptor > + > iG_bimap, + Map aiG_inL, + Map diG, + const Graph& vG, + bimap< + bimaps::set_of, + bimaps::set_of< typename graph_traits::edge_descriptor > + > vG_bimap, + Map avG_inL, + Map dvG, + Func func, + Seq inL + ) + { + typedef graph_traits GraphTraits; + + typedef typename GraphTraits::vertex_descriptor vertex_descriptor; + typedef typename GraphTraits::edge_descriptor edge_descriptor; + + typedef typename Seq::size_type seq_size_type; + + int edges = num_vertices(iG) - 1; +// +// [ Michele Caini ] +// +// Using the condition (edges != 0) leads to the accidental submission of +// sub-graphs ((V-1+1)-fake-tree, named here fat-tree). +// Remove this condition is a workaround for the problem of fat-trees. +// Please do not add that condition, even if it improves performance. +// +// Here is proposed the previous guard (that was wrong): +// for(seq_size_type i = 0; (i < inL.size()) && (edges != 0); ++i) +// + { + for(seq_size_type i = 0; i < inL.size(); ++i) + if(inL[i]) + --edges; + + if(edges < 0) + return; + } + + bool is_tree = (edges == 0); + if(is_tree) { + func(inL); + } else { + std::map vertex_color; + std::map edge_color; + + std::stack iG_buf, vG_buf; + bool found = false; + + seq_size_type m; + for(seq_size_type j = 0; j < inL.size() && !found; ++j) { + if(!inL[j] + && !get(diG, iG_bimap.left.at(j)) + && !get(dvG, vG_bimap.left.at(j))) + { + put(aiG_inL, iG_bimap.left.at(j), true); + put(avG_inL, vG_bimap.left.at(j), true); + + undirected_dfs( + make_filtered_graph(iG, + detail::inL_edge_status< associative_property_map< + std::map > >(aiG_inL)), + make_dfs_visitor( + detail::cycle_finder< std::stack > (&iG_buf)), + associative_property_map< + std::map >(vertex_color), + associative_property_map< + std::map >(edge_color) + ); + undirected_dfs( + make_filtered_graph(vG, + detail::inL_edge_status< associative_property_map< + std::map > >(avG_inL)), + make_dfs_visitor( + detail::cycle_finder< std::stack > (&vG_buf)), + associative_property_map< + std::map >(vertex_color), + associative_property_map< + std::map >(edge_color) + ); + + if(iG_buf.empty() && vG_buf.empty()) { + inL[j] = true; + found = true; + m = j; + } else { + while(!iG_buf.empty()) iG_buf.pop(); + while(!vG_buf.empty()) vG_buf.pop(); + put(aiG_inL, iG_bimap.left.at(j), false); + put(avG_inL, vG_bimap.left.at(j), false); + } + } + } + + if(found) { + + std::stack iG_buf_copy, vG_buf_copy; + for(seq_size_type j = 0; j < inL.size(); ++j) { + if(!inL[j] + && !get(diG, iG_bimap.left.at(j)) + && !get(dvG, vG_bimap.left.at(j))) + { + + put(aiG_inL, iG_bimap.left.at(j), true); + put(avG_inL, vG_bimap.left.at(j), true); + + undirected_dfs( + make_filtered_graph(iG, + detail::inL_edge_status< associative_property_map< + std::map > >(aiG_inL)), + make_dfs_visitor( + detail::cycle_finder< + std::stack > (&iG_buf)), + associative_property_map< std::map< + vertex_descriptor, default_color_type> >(vertex_color), + associative_property_map< + std::map >(edge_color) + ); + undirected_dfs( + make_filtered_graph(vG, + detail::inL_edge_status< associative_property_map< + std::map > >(avG_inL)), + make_dfs_visitor( + detail::cycle_finder< + std::stack > (&vG_buf)), + associative_property_map< std::map< + vertex_descriptor, default_color_type> >(vertex_color), + associative_property_map< + std::map >(edge_color) + ); + + if(!iG_buf.empty() || !vG_buf.empty()) { + while(!iG_buf.empty()) iG_buf.pop(); + while(!vG_buf.empty()) vG_buf.pop(); + put(diG, iG_bimap.left.at(j), true); + put(dvG, vG_bimap.left.at(j), true); + iG_buf_copy.push(iG_bimap.left.at(j)); + vG_buf_copy.push(vG_bimap.left.at(j)); + } + + put(aiG_inL, iG_bimap.left.at(j), false); + put(avG_inL, vG_bimap.left.at(j), false); + } + } + + // REC + detail::rec_two_graphs_common_spanning_trees + (iG, iG_bimap, aiG_inL, diG, vG, vG_bimap, aiG_inL, dvG, func, inL); + + while(!iG_buf_copy.empty()) { + put(diG, iG_buf_copy.top(), false); + put(dvG, vG_bimap.left.at( + iG_bimap.right.at(iG_buf_copy.top())), false); + iG_buf_copy.pop(); + } + while(!vG_buf_copy.empty()) { + put(dvG, vG_buf_copy.top(), false); + put(diG, iG_bimap.left.at( + vG_bimap.right.at(vG_buf_copy.top())), false); + vG_buf_copy.pop(); + } + + inL[m] = false; + put(aiG_inL, iG_bimap.left.at(m), false); + put(avG_inL, vG_bimap.left.at(m), false); + + put(diG, iG_bimap.left.at(m), true); + put(dvG, vG_bimap.left.at(m), true); + + std::map tree_map; + std::map pred_map; + std::map dist_map, low_map; + + detail::bridges_visitor< + associative_property_map< + std::map + >, + associative_property_map< + std::map + >, + associative_property_map< std::map >, + associative_property_map< std::map >, + std::stack + > + iG_vis( + associative_property_map< + std::map< vertex_descriptor, edge_descriptor> >(tree_map), + associative_property_map< + std::map< vertex_descriptor, vertex_descriptor> >(pred_map), + associative_property_map< + std::map< vertex_descriptor, int> >(dist_map), + associative_property_map< + std::map< vertex_descriptor, int> >(low_map), + iG_buf + ), + vG_vis( + associative_property_map< + std::map< vertex_descriptor, edge_descriptor> >(tree_map), + associative_property_map< + std::map< vertex_descriptor, vertex_descriptor> >(pred_map), + associative_property_map< + std::map< vertex_descriptor, int> >(dist_map), + associative_property_map< + std::map< vertex_descriptor, int> >(low_map), + vG_buf + ); + + undirected_dfs(make_filtered_graph(iG, + detail::deleted_edge_status< associative_property_map< + std::map > >(diG)), + iG_vis, + associative_property_map< + std::map >(vertex_color), + associative_property_map< + std::map >(edge_color) + ); + undirected_dfs(make_filtered_graph(vG, + detail::deleted_edge_status< associative_property_map< + std::map > >(dvG)), + vG_vis, + associative_property_map< + std::map >(vertex_color), + associative_property_map< + std::map >(edge_color) + ); + + found = false; + std::stack iG_buf_tmp, vG_buf_tmp; + while(!iG_buf.empty() && !found) { + if(!inL[iG_bimap.right.at(iG_buf.top())]) { + put(aiG_inL, iG_buf.top(), true); + put(avG_inL, vG_bimap.left.at( + iG_bimap.right.at(iG_buf.top())), true); + + undirected_dfs( + make_filtered_graph(iG, + detail::inL_edge_status< associative_property_map< + std::map > >(aiG_inL)), + make_dfs_visitor( + detail::cycle_finder< + std::stack > (&iG_buf_tmp)), + associative_property_map< + std::map< + vertex_descriptor, default_color_type> >(vertex_color), + associative_property_map< + std::map >(edge_color) + ); + undirected_dfs( + make_filtered_graph(vG, + detail::inL_edge_status< associative_property_map< + std::map > >(avG_inL)), + make_dfs_visitor( + detail::cycle_finder< + std::stack > (&vG_buf_tmp)), + associative_property_map< + std::map< + vertex_descriptor, default_color_type> >(vertex_color), + associative_property_map< + std::map >(edge_color) + ); + + if(!iG_buf_tmp.empty() || !vG_buf_tmp.empty()) { + found = true; + } else { + while(!iG_buf_tmp.empty()) iG_buf_tmp.pop(); + while(!vG_buf_tmp.empty()) vG_buf_tmp.pop(); + iG_buf_copy.push(iG_buf.top()); + } + + put(aiG_inL, iG_buf.top(), false); + put(avG_inL, vG_bimap.left.at( + iG_bimap.right.at(iG_buf.top())), false); + } + iG_buf.pop(); + } + while(!vG_buf.empty() && !found) { + if(!inL[vG_bimap.right.at(vG_buf.top())]) { + put(avG_inL, vG_buf.top(), true); + put(aiG_inL, iG_bimap.left.at( + vG_bimap.right.at(vG_buf.top())), true); + + undirected_dfs( + make_filtered_graph(iG, + detail::inL_edge_status< associative_property_map< + std::map > >(aiG_inL)), + make_dfs_visitor( + detail::cycle_finder< + std::stack > (&iG_buf_tmp)), + associative_property_map< + std::map< + vertex_descriptor, default_color_type> >(vertex_color), + associative_property_map< + std::map >(edge_color) + ); + undirected_dfs( + make_filtered_graph(vG, + detail::inL_edge_status< associative_property_map< + std::map > >(avG_inL)), + make_dfs_visitor( + detail::cycle_finder< + std::stack > (&vG_buf_tmp)), + associative_property_map< + std::map< + vertex_descriptor, default_color_type> >(vertex_color), + associative_property_map< + std::map >(edge_color) + ); + + if(!iG_buf_tmp.empty() || !vG_buf_tmp.empty()) { + found = true; + } else { + while(!iG_buf_tmp.empty()) iG_buf_tmp.pop(); + while(!vG_buf_tmp.empty()) vG_buf_tmp.pop(); + vG_buf_copy.push(vG_buf.top()); + } + + put(avG_inL, vG_buf.top(), false); + put(aiG_inL, iG_bimap.left.at( + vG_bimap.right.at(vG_buf.top())), false); + } + vG_buf.pop(); + } + + if(!found) { + + while(!iG_buf_copy.empty()) { + inL[iG_bimap.right.at(iG_buf_copy.top())] = true; + put(aiG_inL, iG_buf_copy.top(), true); + put(avG_inL, vG_bimap.left.at( + iG_bimap.right.at(iG_buf_copy.top())), true); + iG_buf.push(iG_buf_copy.top()); + iG_buf_copy.pop(); + } + while(!vG_buf_copy.empty()) { + inL[vG_bimap.right.at(vG_buf_copy.top())] = true; + put(avG_inL, vG_buf_copy.top(), true); + put(aiG_inL, iG_bimap.left.at( + vG_bimap.right.at(vG_buf_copy.top())), true); + vG_buf.push(vG_buf_copy.top()); + vG_buf_copy.pop(); + } + + // REC + detail::rec_two_graphs_common_spanning_trees< + Graph, Func, Seq, Map> + (iG, iG_bimap, aiG_inL, diG, vG, vG_bimap, aiG_inL, dvG, func, inL); + + while(!iG_buf.empty()) { + inL[iG_bimap.right.at(iG_buf.top())] = false; + put(aiG_inL, iG_buf.top(), false); + put(avG_inL, vG_bimap.left.at( + iG_bimap.right.at(iG_buf.top())), false); + iG_buf.pop(); + } + while(!vG_buf.empty()) { + inL[vG_bimap.right.at(vG_buf.top())] = false; + put(avG_inL, vG_buf.top(), false); + put(aiG_inL, iG_bimap.left.at( + vG_bimap.right.at(vG_buf.top())), false); + vG_buf.pop(); + } + + } + + put(diG, iG_bimap.left.at(m), false); + put(dvG, vG_bimap.left.at(m), false); + + } + } + } + +} // namespace detail + + + +template +struct tree_collector +{ + +public: + BOOST_CONCEPT_ASSERT((BackInsertionSequence)); + BOOST_CONCEPT_ASSERT((RandomAccessContainer)); + BOOST_CONCEPT_ASSERT((CopyConstructible)); + + typedef typename Coll::value_type coll_value_type; + typedef typename Seq::value_type seq_value_type; + + BOOST_STATIC_ASSERT((is_same::value)); + BOOST_STATIC_ASSERT((is_same::value)); + + tree_collector(Coll& seqs): mSeqs(seqs) { } + + inline void operator()(Seq seq) + { mSeqs.push_back(seq); } + +private: + Coll& mSeqs; + +}; + + + +template < + typename Graph, + typename Order, + typename Func, + typename Seq +> +BOOST_CONCEPT_REQUIRES( + ((RandomAccessContainer)) + ((IncidenceGraphConcept)) + ((UnaryFunction)) + ((Mutable_RandomAccessContainer)) + ((VertexAndEdgeListGraphConcept)), + (void) +) +two_graphs_common_spanning_trees + ( + const Graph& iG, + Order iG_map, + const Graph& vG, + Order vG_map, + Func func, + Seq inL + ) +{ + typedef graph_traits GraphTraits; + + typedef typename GraphTraits::directed_category directed_category; + typedef typename GraphTraits::vertex_descriptor vertex_descriptor; + typedef typename GraphTraits::edge_descriptor edge_descriptor; + + typedef typename GraphTraits::edges_size_type edges_size_type; + typedef typename GraphTraits::edge_iterator edge_iterator; + + typedef typename Seq::const_iterator seq_const_iterator; + typedef typename Seq::difference_type seq_diff_type; + typedef typename Seq::value_type seq_value_type; + typedef typename Seq::size_type seq_size_type; + typedef typename Seq::iterator seq_iterator; + + typedef typename Order::const_iterator order_const_iterator; + typedef typename Order::difference_type order_diff_type; + typedef typename Order::value_type order_value_type; + typedef typename Order::size_type order_size_type; + typedef typename Order::iterator order_iterator; + + BOOST_STATIC_ASSERT((is_same::value)); + BOOST_CONCEPT_ASSERT((Convertible)); + + BOOST_CONCEPT_ASSERT((Convertible)); + BOOST_STATIC_ASSERT((is_same::value)); + + BOOST_STATIC_ASSERT((is_same::value)); + + if(num_vertices(iG) != num_vertices(vG)) + return; + + if(inL.size() != num_edges(iG) + || inL.size() != num_edges(vG)) + return; + + if(iG_map.size() != num_edges(iG) + || vG_map.size() != num_edges(vG)) + return; + + typedef bimaps::bimap< + bimaps::set_of< int >, + bimaps::set_of< order_value_type > + > bimap_type; + typedef typename bimap_type::value_type bimap_value; + + bimap_type iG_bimap, vG_bimap; + for(order_size_type i = 0; i < iG_map.size(); ++i) + iG_bimap.insert(bimap_value(i, iG_map[i])); + for(order_size_type i = 0; i < vG_map.size(); ++i) + vG_bimap.insert(bimap_value(i, vG_map[i])); + + edge_iterator current, last; + tie(current, last) = edges(iG); + for(; current != last; ++current) + if(iG_bimap.right.find(*current) == iG_bimap.right.end()) + return; + tie(current, last) = edges(vG); + for(; current != last; ++current) + if(vG_bimap.right.find(*current) == vG_bimap.right.end()) + return; + + std::stack iG_buf, vG_buf; + + std::map tree_map; + std::map pred_map; + std::map dist_map, low_map; + + detail::bridges_visitor< + associative_property_map< + std::map + >, + associative_property_map< + std::map + >, + associative_property_map< std::map >, + associative_property_map< std::map >, + std::stack + > + iG_vis( + associative_property_map< + std::map< vertex_descriptor, edge_descriptor> >(tree_map), + associative_property_map< + std::map< vertex_descriptor, vertex_descriptor> >(pred_map), + associative_property_map >(dist_map), + associative_property_map >(low_map), + iG_buf + ), + vG_vis( + associative_property_map< + std::map< vertex_descriptor, edge_descriptor> >(tree_map), + associative_property_map< + std::map< vertex_descriptor, vertex_descriptor> >(pred_map), + associative_property_map >(dist_map), + associative_property_map >(low_map), + vG_buf + ); + + std::map vertex_color; + std::map edge_color; + + undirected_dfs(iG, iG_vis, + associative_property_map< + std::map >(vertex_color), + associative_property_map< + std::map >(edge_color) + ); + undirected_dfs(vG, vG_vis, + associative_property_map< + std::map >(vertex_color), + associative_property_map< + std::map >(edge_color) + ); + + while(!iG_buf.empty()) { + inL[iG_bimap.right.at(iG_buf.top())] = true; + iG_buf.pop(); + } + while(!vG_buf.empty()) { + inL[vG_bimap.right.at(vG_buf.top())] = true; + vG_buf.pop(); + } + + std::map iG_inL, vG_inL; + associative_property_map< std::map > + aiG_inL(iG_inL), avG_inL(vG_inL); + + for(seq_size_type i = 0; i < inL.size(); ++i) + { + if(inL[i]) { + put(aiG_inL, iG_bimap.left.at(i), true); + put(avG_inL, vG_bimap.left.at(i), true); + } else { + put(aiG_inL, iG_bimap.left.at(i), false); + put(avG_inL, vG_bimap.left.at(i), false); + } + } + + undirected_dfs( + make_filtered_graph(iG, + detail::inL_edge_status< associative_property_map< + std::map > >(aiG_inL)), + make_dfs_visitor( + detail::cycle_finder< std::stack > (&iG_buf)), + associative_property_map< + std::map >(vertex_color), + associative_property_map< + std::map >(edge_color) + ); + undirected_dfs( + make_filtered_graph(vG, + detail::inL_edge_status< associative_property_map< + std::map > >(avG_inL)), + make_dfs_visitor( + detail::cycle_finder< std::stack > (&vG_buf)), + associative_property_map< + std::map >(vertex_color), + associative_property_map< + std::map >(edge_color) + ); + + if(iG_buf.empty() && vG_buf.empty()) { + + std::map iG_deleted, vG_deleted; + associative_property_map< std::map > diG(iG_deleted); + associative_property_map< std::map > dvG(vG_deleted); + + tie(current, last) = edges(iG); + for(; current != last; ++current) + put(diG, *current, false); + tie(current, last) = edges(vG); + for(; current != last; ++current) + put(dvG, *current, false); + + for(seq_size_type j = 0; j < inL.size(); ++j) { + if(!inL[j]) { + put(aiG_inL, iG_bimap.left.at(j), true); + put(avG_inL, vG_bimap.left.at(j), true); + + undirected_dfs( + make_filtered_graph(iG, + detail::inL_edge_status< associative_property_map< + std::map > >(aiG_inL)), + make_dfs_visitor( + detail::cycle_finder< std::stack > (&iG_buf)), + associative_property_map< + std::map >(vertex_color), + associative_property_map< + std::map >(edge_color) + ); + undirected_dfs( + make_filtered_graph(vG, + detail::inL_edge_status< associative_property_map< + std::map > >(avG_inL)), + make_dfs_visitor( + detail::cycle_finder< std::stack > (&vG_buf)), + associative_property_map< + std::map >(vertex_color), + associative_property_map< + std::map >(edge_color) + ); + + if(!iG_buf.empty() || !vG_buf.empty()) { + while(!iG_buf.empty()) iG_buf.pop(); + while(!vG_buf.empty()) vG_buf.pop(); + put(diG, iG_bimap.left.at(j), true); + put(dvG, vG_bimap.left.at(j), true); + } + + put(aiG_inL, iG_bimap.left.at(j), false); + put(avG_inL, vG_bimap.left.at(j), false); + } + } + + int cc = 0; + + std::map com_map; + cc += connected_components( + make_filtered_graph(iG, + detail::deleted_edge_status > >(diG)), + associative_property_map >(com_map) + ); + cc += connected_components( + make_filtered_graph(vG, + detail::deleted_edge_status > >(dvG)), + associative_property_map< std::map >(com_map) + ); + + if(cc != 2) + return; + + // REC + detail::rec_two_graphs_common_spanning_trees > > + (iG, iG_bimap, aiG_inL, diG, vG, vG_bimap, aiG_inL, dvG, func, inL); + + } + +} + + +template < + typename Graph, + typename Func, + typename Seq +> +BOOST_CONCEPT_REQUIRES( + ((IncidenceGraphConcept)) + ((EdgeListGraphConcept)), + (void) +) +two_graphs_common_spanning_trees + ( + const Graph& iG, + const Graph& vG, + Func func, + Seq inL + ) +{ + typedef graph_traits GraphTraits; + + typedef typename GraphTraits::edge_descriptor edge_descriptor; + typedef typename GraphTraits::edges_size_type edges_size_type; + typedef typename GraphTraits::edge_iterator edge_iterator; + + std::vector iGO, vGO; + edge_iterator curr, last; + + tie(curr, last) = edges(iG); + for(; curr != last; ++curr) + iGO.push_back(*curr); + + tie(curr, last) = edges(vG); + for(; curr != last; ++curr) + vGO.push_back(*curr); + + two_graphs_common_spanning_trees(iG, iGO, vG, vGO, func, inL); +} + + +} // namespace boost + + +#endif // BOOST_GRAPH_TWO_GRAPHS_COMMON_SPANNING_TREES_HPP diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 8d26b17c4..fd6e967cd 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -119,6 +119,7 @@ test-suite graph_test : [ compile grid_graph_cc.cpp ] [ run grid_graph_test.cpp ] [ run incremental_components_test.cpp ] + [ run two_graphs_common_spanning_trees_test.cpp ] [ run random_spanning_tree_test.cpp ../build//boost_graph ] [ run graphml_test.cpp ../build//boost_graph : : "graphml_test.xml" ] [ run stoer_wagner_test.cpp ../../test/build//boost_unit_test_framework/static : $(TEST_DIR) ] diff --git a/test/two_graphs_common_spanning_trees_test.cpp b/test/two_graphs_common_spanning_trees_test.cpp new file mode 100644 index 000000000..e8cb3ad19 --- /dev/null +++ b/test/two_graphs_common_spanning_trees_test.cpp @@ -0,0 +1,148 @@ +// Copyright (C) 2012, Michele Caini. +// 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) + +// Two Graphs Common Spanning Trees Algorithm +// Based on academic article of Mint, Read and Tarjan +// Efficient Algorithm for Common Spanning Tree Problem +// Electron. Lett., 28 April 1983, Volume 19, Issue 9, p.346–347 + + +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace boost::assign; + + +namespace boost +{ + + +typedef +boost::adjacency_list + < + boost::vecS, // OutEdgeList + boost::vecS, // VertexList + boost::undirectedS, // Directed + boost::no_property, // VertexProperties + boost::no_property, // EdgeProperties + boost::no_property, // GraphProperties + boost::listS // EdgeList + > +Graph +; + +typedef +boost::graph_traits::vertex_descriptor +vertex_descriptor; + +typedef +boost::graph_traits::edge_descriptor +edge_descriptor; + +typedef +boost::graph_traits::vertex_iterator +vertex_iterator; + +typedef +boost::graph_traits::edge_iterator +edge_iterator; + + +template < typename Coll, typename Seq > +struct check_edge +{ +public: + BOOST_CONCEPT_ASSERT((RandomAccessContainer)); + BOOST_CONCEPT_ASSERT((RandomAccessContainer)); + + typedef typename Coll::value_type coll_value_type; + typedef typename Seq::value_type seq_value_type; + + BOOST_STATIC_ASSERT((is_same::value)); + BOOST_STATIC_ASSERT((is_same::value)); + + void operator()(Coll& coll, Seq& seq) + { + bool found = false; + + for(typename Coll::iterator iterator = coll.begin(); + !found && iterator != coll.end(); ++iterator) + { + Seq& coll_seq = *iterator; + + BOOST_REQUIRE(coll_seq.size() == seq.size()); + + found = true; + for(typename Seq::size_type pos = 0; found && pos < seq.size(); ++pos) { + found &= coll_seq[pos] == seq[pos]; + } + } + + BOOST_REQUIRE(found); + } +}; + + +void two_graphs_common_spanning_trees_test() +{ + Graph iG, vG; + std::vector< edge_descriptor > iG_o; + std::vector< edge_descriptor > vG_o; + + iG_o.push_back(boost::add_edge(0, 1, iG).first); + iG_o.push_back(boost::add_edge(1, 3, iG).first); + iG_o.push_back(boost::add_edge(3, 2, iG).first); + iG_o.push_back(boost::add_edge(1, 5, iG).first); + iG_o.push_back(boost::add_edge(5, 4, iG).first); + iG_o.push_back(boost::add_edge(5, 6, iG).first); + iG_o.push_back(boost::add_edge(5, 3, iG).first); + iG_o.push_back(boost::add_edge(3, 1, iG).first); + iG_o.push_back(boost::add_edge(1, 3, iG).first); + + vG_o.push_back(boost::add_edge(0, 2, vG).first); + vG_o.push_back(boost::add_edge(0, 4, vG).first); + vG_o.push_back(boost::add_edge(0, 5, vG).first); + vG_o.push_back(boost::add_edge(5, 1, vG).first); + vG_o.push_back(boost::add_edge(5, 3, vG).first); + vG_o.push_back(boost::add_edge(5, 6, vG).first); + vG_o.push_back(boost::add_edge(5, 4, vG).first); + vG_o.push_back(boost::add_edge(5, 2, vG).first); + vG_o.push_back(boost::add_edge(2, 6, vG).first); + + std::vector< std::vector > coll; + boost::tree_collector< + std::vector< std::vector >, std::vector + > collector(coll); + std::vector inL(iG_o.size(), false); + + boost::two_graphs_common_spanning_trees(iG, iG_o, vG, vG_o, collector, inL); + + check_edge< std::vector< std::vector >, std::vector > checker; + std::vector check; + + check.clear(); + check += true, true, true, true, true, true, false, false, false; + checker(coll, check); + + check.clear(); + check += true, true, true, true, true, true, false, false, false; + checker(coll, check); +} + + +} + + +int test_main ( int argc, char** argv ) +{ + boost::two_graphs_common_spanning_trees_test(); + return EXIT_SUCCESS; +} From 706859b5952d5763b66fb2bfb6865b43d007b409 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Wed, 11 Apr 2012 16:26:51 +0000 Subject: [PATCH 163/333] Removed uses of Boost.Typeof to hopefully help on XLC [SVN r77916] --- test/stoer_wagner_test.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/stoer_wagner_test.cpp b/test/stoer_wagner_test.cpp index 112bf495c..8f9fc819f 100644 --- a/test/stoer_wagner_test.cpp +++ b/test/stoer_wagner_test.cpp @@ -206,9 +206,9 @@ BOOST_AUTO_TEST_CASE(test_prgen_20_70_2) boost::associative_property_map > components(component); BOOST_CHECK_EQUAL(boost::connected_components(g, components), 1U); // verify the connectedness assumption - BOOST_AUTO(distances, (boost::make_shared_array_property_map(num_vertices(g), weight_type(0), get(boost::vertex_index, g)))); + boost::shared_array_property_map::const_type> distances = boost::make_shared_array_property_map(num_vertices(g), weight_type(0), get(boost::vertex_index, g)); typedef std::vector::size_type index_in_heap_type; - BOOST_AUTO(indicesInHeap, (boost::make_shared_array_property_map(num_vertices(g), index_in_heap_type(-1), get(boost::vertex_index, g)))); + boost::shared_array_property_map::const_type> indicesInHeap = boost::make_shared_array_property_map(num_vertices(g), index_in_heap_type(-1), get(boost::vertex_index, g)); boost::d_ary_heap_indirect > pq(distances, indicesInHeap); int w = boost::stoer_wagner_min_cut(g, get(boost::edge_weight, g), boost::max_priority_queue(pq)); From efd4b992cca5eaee9ae7c8ad46c132baaaf93956 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Wed, 11 Apr 2012 20:52:32 +0000 Subject: [PATCH 164/333] Clarified and corrected documentation [SVN r77924] --- doc/prim_minimum_spanning_tree.html | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/doc/prim_minimum_spanning_tree.html b/doc/prim_minimum_spanning_tree.html index 324f41962..cf373c70b 100644 --- a/doc/prim_minimum_spanning_tree.html +++ b/doc/prim_minimum_spanning_tree.html @@ -172,7 +172,9 @@

      Named Parameters

      Readable Property Map. The edge descriptor type of the graph needs to be usable as the key type for the weight map. The value type for the map must be - Addable with the value type of the distance map.
      + the same as the value type of the distance map, and that type must be Less Than + Comparable.
      Default: get(edge_weight, g)
      Python: Must be an edge_double_map for the graph.
      Python default: graph.get_edge_double_map("weight") @@ -190,7 +192,7 @@

      Named Parameters

      Default: get(vertex_index, g) Note: if you use this default, make sure your graph has an internal vertex_index property. For example, - adjacenty_list with VertexList=listS does + adjacency_list with VertexList=listS does not have an internal vertex_index property.
      Python: Unsupported parameter. @@ -204,10 +206,9 @@

      Named Parameters

      The type DistanceMap must be a model of Read/Write Property Map. The vertex descriptor type of the - graph needs to be usable as the key type of the distance map. The - value type of the distance map must be Less Than - Comparable.
      + graph needs to be usable as the key type of the distance map, and the value + type needs to be the same as the value type of the weight_map + argument.
      Default: iterator_property_map created from a std::vector of the WeightMap's value type of size From 0aaf3858a0608a23fc9b812c2c46f9ed03353a4b Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Mon, 16 Apr 2012 17:35:15 +0000 Subject: [PATCH 165/333] Reverted r77731 because it complicated the code and did not fix BGL compilation on any compilers [SVN r78020] --- include/boost/graph/graphviz.hpp | 36 ++------------------------------ 1 file changed, 2 insertions(+), 34 deletions(-) diff --git a/include/boost/graph/graphviz.hpp b/include/boost/graph/graphviz.hpp index 50ee5d9b2..aedce5553 100644 --- a/include/boost/graph/graphviz.hpp +++ b/include/boost/graph/graphviz.hpp @@ -15,7 +15,6 @@ #include #include #include -#include #include // for FILE #include #include @@ -32,9 +31,7 @@ #include #include #include -#if 0 #include -#endif #include namespace boost { @@ -68,39 +65,10 @@ namespace boost { template inline std::string escape_dot_string(const T& obj) { - std::string s(boost::lexical_cast(obj)); -#if 0 using namespace boost::xpressive; static sregex valid_unquoted_id = (((alpha | '_') >> *_w) | (!as_xpr('-') >> (('.' >> *_d) | (+_d >> !('.' >> *_d))))); - bool ok = regex_match(s, valid_unquoted_id); -#else - bool ok; - using std::isdigit; using std::isalpha; - if (s.empty()) { - ok = false; - } else if (isdigit(s[0]) || s[0] == '-' || s[0] == '.') { // Number - size_t startpos = (s[0] == '-' ? 1 : 0); - size_t dot_maybe = s.find('.', startpos); - if (dot_maybe != std::string::npos && s.find('.', dot_maybe + 1) != std::string::npos) { - ok = false; // Has two decimal points - } else { - for (size_t i = startpos; i < s.size(); ++i) { - if (!(isdigit(s[i]) || s[i] == '.')) {ok = false; break;} - } - } - } else if (isalpha(s[0]) || s[0] == '_') { // Identifier - ok = true; - for (size_t i = 1; i < s.size(); ++i) { - if (!(isalpha(s[i]) || isdigit(s[i]) || s[i] == '_')) { - ok = false; - break; - } - } - } else { - ok = false; - } -#endif - if (ok) { + std::string s(boost::lexical_cast(obj)); + if (regex_match(s, valid_unquoted_id)) { return s; } else { boost::algorithm::replace_all(s, "\"", "\\\""); From 01832f76c2bbee8373108d65c5681272ffb3c836 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Mon, 16 Apr 2012 17:46:15 +0000 Subject: [PATCH 166/333] Fixed SCC example and added it to Jamfile; fixes #6647 [SVN r78022] --- example/Jamfile.v2 | 2 ++ example/strong_components.cpp | 15 ++++++++------- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/example/Jamfile.v2 b/example/Jamfile.v2 index b33b4f9df..2ab225009 100644 --- a/example/Jamfile.v2 +++ b/example/Jamfile.v2 @@ -39,3 +39,5 @@ exe undirected_adjacency_list : undirected_adjacency_list.cpp ; exe directed_graph : directed_graph.cpp ; exe undirected_graph : undirected_graph.cpp ; exe two_graphs_common_spanning_trees : two_graphs_common_spanning_trees.cpp ; +exe strong_components : strong_components.cpp ../build//boost_graph ; +exe strong-components : strong-components.cpp ; diff --git a/example/strong_components.cpp b/example/strong_components.cpp index 4b01f8862..089e3ef92 100644 --- a/example/strong_components.cpp +++ b/example/strong_components.cpp @@ -46,22 +46,23 @@ int main(int, char*[]) using namespace boost; const char* name = "abcdefghij"; - GraphvizDigraph G; - read_graphviz("scc.dot", G); + adjacency_list G; + dynamic_properties dp; + read_graphviz("scc.dot", G, dp); std::cout << "A directed graph:" << std::endl; print_graph(G, name); std::cout << std::endl; - typedef graph_traits::vertex_descriptor Vertex; + typedef graph_traits >::vertex_descriptor Vertex; std::vector component(num_vertices(G)), discover_time(num_vertices(G)); std::vector color(num_vertices(G)); std::vector root(num_vertices(G)); - int num = strong_components(G, &component[0], - root_map(&root[0]). - color_map(&color[0]). - discover_time_map(&discover_time[0])); + int num = strong_components(G, make_iterator_property_map(component.begin(), get(vertex_index, G)), + root_map(make_iterator_property_map(root.begin(), get(vertex_index, G))). + color_map(make_iterator_property_map(color.begin(), get(vertex_index, G))). + discover_time_map(make_iterator_property_map(discover_time.begin(), get(vertex_index, G)))); std::cout << "Total number of components: " << num << std::endl; std::vector::size_type i; From 97bea429fc9340a0f03b1670097e88b8a902e527 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Mon, 16 Apr 2012 17:55:07 +0000 Subject: [PATCH 167/333] Added new code from #6242; fixes #6242 [SVN r78023] --- include/boost/graph/isomorphism.hpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/include/boost/graph/isomorphism.hpp b/include/boost/graph/isomorphism.hpp index c4950ccb0..31fc0c326 100644 --- a/include/boost/graph/isomorphism.hpp +++ b/include/boost/graph/isomorphism.hpp @@ -136,6 +136,10 @@ namespace boost { bool test_isomorphism() { + // reset isomapping + BGL_FORALL_VERTICES_T(v, G1, Graph1) + f[v] = graph_traits::null_vertex(); + { std::vector invar1_array; BGL_FORALL_VERTICES_T(v, G1, Graph1) From ebdec45c4b7e271cc946900efd9648743b6ceb60 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Mon, 16 Apr 2012 18:44:36 +0000 Subject: [PATCH 168/333] Added test for Boost.Parameter version of isomorphism; fixed bugs that found [SVN r78024] --- include/boost/graph/breadth_first_search.hpp | 3 +- include/boost/graph/depth_first_search.hpp | 3 +- include/boost/graph/isomorphism.hpp | 3 +- include/boost/graph/named_function_params.hpp | 42 ++++++++++++++----- test/isomorphism.cpp | 10 +++-- 5 files changed, 43 insertions(+), 18 deletions(-) diff --git a/include/boost/graph/breadth_first_search.hpp b/include/boost/graph/breadth_first_search.hpp index 80683204e..703f6c353 100644 --- a/include/boost/graph/breadth_first_search.hpp +++ b/include/boost/graph/breadth_first_search.hpp @@ -373,9 +373,10 @@ namespace boost { namespace graph { namespace detail { - template + template struct breadth_first_search_impl { typedef void result_type; + template void operator()(const Graph& g, const Source& source, const ArgPack& arg_pack) { using namespace boost::graph::keywords; typename boost::graph_traits::vertex_descriptor sources[1] = {source}; diff --git a/include/boost/graph/depth_first_search.hpp b/include/boost/graph/depth_first_search.hpp index c5ce5053c..e8f21b4e1 100644 --- a/include/boost/graph/depth_first_search.hpp +++ b/include/boost/graph/depth_first_search.hpp @@ -286,9 +286,10 @@ namespace boost { // Boost.Parameter named parameter variant namespace graph { namespace detail { - template + template struct depth_first_search_impl { typedef void result_type; + template void operator()(const Graph& g, const ArgPack& arg_pack) const { using namespace boost::graph::keywords; boost::depth_first_search(g, diff --git a/include/boost/graph/isomorphism.hpp b/include/boost/graph/isomorphism.hpp index 31fc0c326..1aa415fd6 100644 --- a/include/boost/graph/isomorphism.hpp +++ b/include/boost/graph/isomorphism.hpp @@ -491,9 +491,10 @@ fi_adj_loop_k:++fi_adj.first; namespace graph { namespace detail { - template + template struct isomorphism_impl { typedef bool result_type; + template bool operator()(const Graph1& g1, const Graph2& g2, const ArgPack& arg_pack) const { using namespace boost::graph::keywords; typedef typename boost::detail::override_const_property_result::type index1_map_type; diff --git a/include/boost/graph/named_function_params.hpp b/include/boost/graph/named_function_params.hpp index 2eda0e873..e19ffef16 100644 --- a/include/boost/graph/named_function_params.hpp +++ b/include/boost/graph/named_function_params.hpp @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -464,12 +465,34 @@ BOOST_BGL_DECLARE_NAMED_PARAMS >()(g, ap[t | 0]); } + template struct make_arg_pack_type; + template <> struct make_arg_pack_type {typedef boost::parameter::aux::empty_arg_list type;}; + template + struct make_arg_pack_type { + typedef boost::parameter::aux::tagged_argument type; + }; + +#define BOOST_GRAPH_OPENING_PART_OF_PAIR(z, i, n) boost::parameter::aux::arg_list, +#define BOOST_GRAPH_MAKE_PAIR_PARAM(z, i, _) const boost::parameter::aux::tagged_argument& BOOST_PP_CAT(kw, i) + +#define BOOST_GRAPH_MAKE_AP_TYPE_SPECIALIZATION(z, i, _) \ + template \ + struct make_arg_pack_type { \ + typedef \ + BOOST_PP_REPEAT(i, BOOST_GRAPH_OPENING_PART_OF_PAIR, BOOST_PP_DEC(i)) boost::parameter::aux::empty_arg_list BOOST_PP_REPEAT(i, > BOOST_PP_TUPLE_EAT(3), ~) \ + type; \ + }; + BOOST_PP_REPEAT_FROM_TO(2, 11, BOOST_GRAPH_MAKE_AP_TYPE_SPECIALIZATION, ~) +#undef BOOST_GRAPH_MAKE_AP_TYPE_SPECIALIZATION + #define BOOST_GRAPH_MAKE_FORWARDING_FUNCTION(name, nfixed, nnamed_max) \ /* Entry point for conversion from BGL-style named parameters */ \ template \ - typename detail::BOOST_PP_CAT(name, _impl)::result_type \ + typename boost::result_of< \ + detail::BOOST_PP_CAT(name, _impl)(BOOST_PP_ENUM_PARAMS(nfixed, Param) BOOST_PP_COMMA_IF(nfixed) const ArgPack&) \ + >::type \ BOOST_PP_CAT(name, _with_named_params)(BOOST_PP_ENUM_BINARY_PARAMS(nfixed, const Param, & param) BOOST_PP_COMMA_IF(nfixed) const ArgPack& arg_pack) { \ - return detail::BOOST_PP_CAT(name, _impl)()(BOOST_PP_ENUM_PARAMS(nfixed, param) BOOST_PP_COMMA_IF(nfixed) arg_pack); \ + return detail::BOOST_PP_CAT(name, _impl)()(BOOST_PP_ENUM_PARAMS(nfixed, param) BOOST_PP_COMMA_IF(nfixed) arg_pack); \ } \ /* Individual functions taking Boost.Parameter-style keyword arguments */ \ BOOST_PP_REPEAT(BOOST_PP_INC(nnamed_max), BOOST_GRAPH_MAKE_FORWARDING_FUNCTION_ONE, (name)(nfixed)) @@ -479,21 +502,18 @@ BOOST_BGL_DECLARE_NAMED_PARAMS #define BOOST_GRAPH_MAKE_FORWARDING_FUNCTION_ONEX(z, nnamed, name, nfixed) \ template \ - typename detail::BOOST_PP_CAT(name, _impl)::result_type \ + typename boost::result_of< \ + detail::BOOST_PP_CAT(name, _impl) \ + (BOOST_PP_ENUM_PARAMS(nfixed, Param) BOOST_PP_COMMA_IF(nfixed) \ + const typename boost::detail::make_arg_pack_type::type&) \ + >::type \ name(BOOST_PP_ENUM_BINARY_PARAMS(nfixed, const Param, & param) \ BOOST_PP_ENUM_TRAILING(nnamed, BOOST_GRAPH_MAKE_PAIR_PARAM, ~)) { \ - return detail::BOOST_PP_CAT(name, _impl)() \ + return detail::BOOST_PP_CAT(name, _impl)() \ (BOOST_PP_ENUM_PARAMS(nfixed, param), \ (boost::parameter::aux::empty_arg_list() BOOST_PP_ENUM_TRAILING_PARAMS(nnamed, kw))); \ } -#define BOOST_GRAPH_TEMPLATE_ARGS_FOR_IMPL(nnamed, nfixed) \ - BOOST_PP_ENUM_PARAMS(nfixed, Param), \ - BOOST_PP_REPEAT(nnamed, BOOST_GRAPH_OPENING_PART_OF_PAIR, BOOST_PP_DEC(nnamed)) boost::parameter::aux::empty_arg_list BOOST_PP_REPEAT(nnamed, > BOOST_PP_TUPLE_EAT(3), ~) - -#define BOOST_GRAPH_OPENING_PART_OF_PAIR(z, i, n) boost::parameter::aux::arg_list, -#define BOOST_GRAPH_MAKE_PAIR_PARAM(z, i, _) const boost::parameter::aux::tagged_argument& BOOST_PP_CAT(kw, i) - } namespace detail { diff --git a/test/isomorphism.cpp b/test/isomorphism.cpp index a151cca1d..fee22a21d 100644 --- a/test/isomorphism.cpp +++ b/test/isomorphism.cpp @@ -95,6 +95,7 @@ void generate_random_digraph(Graph& g, double edge_probability) void test_isomorphism2() { + using namespace boost::graph::keywords; typedef adjacency_list graph1; typedef adjacency_list > graph2; @@ -115,8 +116,8 @@ void test_isomorphism2() bool isomorphism_correct; clock_t start = clock(); - BOOST_CHECK(isomorphism_correct = isomorphism - (g1, g2, isomorphism_map(make_assoc_property_map(mapping)))); + BOOST_CHECK(isomorphism_correct = boost::graph::isomorphism + (g1, g2, _isomorphism_map = make_assoc_property_map(mapping))); clock_t end = clock(); std::cout << "Elapsed time (clock cycles): " << (end - start) << std::endl; @@ -152,6 +153,7 @@ void test_isomorphism2() void test_isomorphism(int n, double edge_probability) { + using namespace boost::graph::keywords; typedef adjacency_list graph1; typedef adjacency_list > graph2; @@ -171,8 +173,8 @@ void test_isomorphism(int n, double edge_probability) bool isomorphism_correct; clock_t start = clock(); - BOOST_CHECK(isomorphism_correct = isomorphism - (g1, g2, isomorphism_map(make_assoc_property_map(mapping)))); + BOOST_CHECK(isomorphism_correct = boost::graph::isomorphism + (g1, g2, _isomorphism_map = make_assoc_property_map(mapping))); clock_t end = clock(); std::cout << "Elapsed time (clock cycles): " << (end - start) << std::endl; From 2a4350905b26bf13d74c3351eb73a737967fab68 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Mon, 16 Apr 2012 19:07:20 +0000 Subject: [PATCH 169/333] Added generator to make old-style named parameter wrappers [SVN r78026] --- include/boost/graph/isomorphism.hpp | 18 +-------------- include/boost/graph/named_function_params.hpp | 23 +++++++++++++++++++ 2 files changed, 24 insertions(+), 17 deletions(-) diff --git a/include/boost/graph/isomorphism.hpp b/include/boost/graph/isomorphism.hpp index 1aa415fd6..995c91318 100644 --- a/include/boost/graph/isomorphism.hpp +++ b/include/boost/graph/isomorphism.hpp @@ -532,23 +532,7 @@ fi_adj_loop_k:++fi_adj.first; } // Named parameter interface - template - bool isomorphism(const Graph1& g1, - const Graph2& g2, - const bgl_named_params& params) - { - typedef bgl_named_params params_type; - BOOST_GRAPH_DECLARE_CONVERTED_PARAMETERS(params_type, params) - return boost::graph::isomorphism_with_named_params(g1, g2, arg_pack); - } - - template - bool isomorphism(const Graph1& g1, - const Graph2& g2) - { - BOOST_GRAPH_DECLARE_CONVERTED_PARAMETERS(no_named_parameters, no_named_parameters()) - return boost::graph::isomorphism_with_named_params(g1, g2, arg_pack); - } + BOOST_GRAPH_MAKE_OLD_STYLE_PARAMETER_FUNCTION(isomorphism, 2) // Verify that the given mapping iso_map from the vertices of g1 to the // vertices of g2 describes an isomorphism. diff --git a/include/boost/graph/named_function_params.hpp b/include/boost/graph/named_function_params.hpp index e19ffef16..ed8736534 100644 --- a/include/boost/graph/named_function_params.hpp +++ b/include/boost/graph/named_function_params.hpp @@ -514,6 +514,29 @@ BOOST_BGL_DECLARE_NAMED_PARAMS (boost::parameter::aux::empty_arg_list() BOOST_PP_ENUM_TRAILING_PARAMS(nnamed, kw))); \ } +#define BOOST_GRAPH_MAKE_OLD_STYLE_PARAMETER_FUNCTION(name, nfixed) \ + template \ + typename boost::result_of< \ + ::boost::graph::detail::BOOST_PP_CAT(name, _impl) BOOST_PP_EXPR_IF(nfixed, <) BOOST_PP_ENUM_PARAMS(nfixed, Param) BOOST_PP_EXPR_IF(nfixed, >) \ + (BOOST_PP_ENUM_PARAMS(nfixed, Param) BOOST_PP_COMMA_IF(nfixed) \ + const typename boost::detail::convert_bgl_params_to_boost_parameter >::type &) \ + >::type \ + name(BOOST_PP_ENUM_BINARY_PARAMS(nfixed, const Param, & param) BOOST_PP_COMMA_IF(nfixed) const boost::bgl_named_params& old_style_params) { \ + typedef boost::bgl_named_params old_style_params_type; \ + BOOST_GRAPH_DECLARE_CONVERTED_PARAMETERS(old_style_params_type, old_style_params) \ + return ::boost::graph::BOOST_PP_CAT(name, _with_named_params)(BOOST_PP_ENUM_PARAMS(nfixed, param) BOOST_PP_COMMA_IF(nfixed) arg_pack); \ + } \ + \ + BOOST_PP_EXPR_IF(nfixed, template <) BOOST_PP_ENUM_PARAMS(nfixed, typename Param) BOOST_PP_EXPR_IF(nfixed, >) \ + BOOST_PP_EXPR_IF(nfixed, typename) boost::result_of< \ + ::boost::graph::detail::BOOST_PP_CAT(name, _impl) BOOST_PP_EXPR_IF(nfixed, <) BOOST_PP_ENUM_PARAMS(nfixed, Param) BOOST_PP_EXPR_IF(nfixed, >) \ + (BOOST_PP_ENUM_PARAMS(nfixed, Param) BOOST_PP_COMMA_IF(nfixed) const boost::parameter::aux::empty_arg_list &) \ + >::type \ + name(BOOST_PP_ENUM_BINARY_PARAMS(nfixed, const Param, & param)) { \ + BOOST_GRAPH_DECLARE_CONVERTED_PARAMETERS(boost::no_named_parameters, boost::no_named_parameters()) \ + return ::boost::graph::BOOST_PP_CAT(name, _with_named_params)(BOOST_PP_ENUM_PARAMS(nfixed, param) BOOST_PP_COMMA_IF(nfixed) arg_pack); \ + } + } namespace detail { From a64981a98392c31384cab2c17fecc151676d7e45 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Mon, 16 Apr 2012 19:17:04 +0000 Subject: [PATCH 170/333] Changed to old-style named parameter wrapper generator [SVN r78027] --- include/boost/graph/breadth_first_search.hpp | 20 +------------------- include/boost/graph/depth_first_search.hpp | 19 +------------------ 2 files changed, 2 insertions(+), 37 deletions(-) diff --git a/include/boost/graph/breadth_first_search.hpp b/include/boost/graph/breadth_first_search.hpp index 703f6c353..18bc24f5c 100644 --- a/include/boost/graph/breadth_first_search.hpp +++ b/include/boost/graph/breadth_first_search.hpp @@ -395,25 +395,7 @@ namespace boost { #if 0 // Named Parameter Variant - template - void - breadth_first_search(const VertexListGraph& g, - typename graph_traits::vertex_descriptor s, - const bgl_named_params& params) - { - typedef bgl_named_params params_type; - BOOST_GRAPH_DECLARE_CONVERTED_PARAMETERS(params_type, params) - boost::graph::breadth_first_search_with_named_params(g, s, arg_pack); - } - - template - void - breadth_first_search(const VertexListGraph& g, - typename graph_traits::vertex_descriptor s) - { - BOOST_GRAPH_DECLARE_CONVERTED_PARAMETERS(no_named_parameters, no_named_parameters()) - boost::graph::breadth_first_search_with_named_params(g, s, arg_pack); - } + BOOST_GRAPH_MAKE_OLD_STYLE_PARAMETER_FUNCTION(breadth_first_search, 2) #endif } // namespace boost diff --git a/include/boost/graph/depth_first_search.hpp b/include/boost/graph/depth_first_search.hpp index e8f21b4e1..34d73a2fd 100644 --- a/include/boost/graph/depth_first_search.hpp +++ b/include/boost/graph/depth_first_search.hpp @@ -302,24 +302,7 @@ namespace boost { BOOST_GRAPH_MAKE_FORWARDING_FUNCTION(depth_first_search, 1, 4) } - // Named Parameter Variant - template - void - depth_first_search(const VertexListGraph& g, - const bgl_named_params& params) - { - typedef bgl_named_params params_type; - BOOST_GRAPH_DECLARE_CONVERTED_PARAMETERS(params_type, params) - boost::graph::depth_first_search_with_named_params(g, arg_pack); - } - - template - void - depth_first_search(const VertexListGraph& g) - { - BOOST_GRAPH_DECLARE_CONVERTED_PARAMETERS(no_named_parameters, no_named_parameters()) - boost::graph::depth_first_search_with_named_params(g, arg_pack); - } + BOOST_GRAPH_MAKE_OLD_STYLE_PARAMETER_FUNCTION(depth_first_search, 1) template void depth_first_visit From 6ea899f7edca4c2985a5a1b74da7ec2ce92c7b70 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Mon, 16 Apr 2012 23:12:50 +0000 Subject: [PATCH 171/333] Added code and docs from #5269 (some code heavily rewritten) and removed old workarounds; fixes #5269 [SVN r78030] --- doc/DFSVisitor.html | 9 + doc/depth_first_search.html | 6 + doc/undirected_dfs.html | 8 +- example/dfs.cpp | 12 ++ example/dfs.expected | 6 + include/boost/graph/depth_first_search.hpp | 66 +++++--- include/boost/graph/undirected_dfs.hpp | 18 +- include/boost/graph/visitors.hpp | 3 +- test/Jamfile.v2 | 1 + test/dfs.cpp | 6 + test/undirected_dfs.cpp | 187 +++++++++++++++++++++ 11 files changed, 294 insertions(+), 28 deletions(-) create mode 100644 test/undirected_dfs.cpp diff --git a/doc/DFSVisitor.html b/doc/DFSVisitor.html index f81f616fb..a018257b2 100644 --- a/doc/DFSVisitor.html +++ b/doc/DFSVisitor.html @@ -150,6 +150,15 @@

      Valid Expressions

      +Finish Edge +vis.finish_edge(e, g) +void + +This is invoked on each non-tree edge as well as on each tree edge after +finish_vertex has been called on its target vertex. + + + Finish Vertex vis.finish_vertex(u, g) void diff --git a/doc/depth_first_search.html b/doc/depth_first_search.html index e217972ae..b0057f7d7 100644 --- a/doc/depth_first_search.html +++ b/doc/depth_first_search.html @@ -107,6 +107,7 @@

      (Python
       <i>...</i>
     <b>else if</b> (<i>color[v] =</i> BLACK) 
       <i>...</i>
+    <i>...</i>
   <b>end for</b>
   <i>color[u] :=</i> BLACK
   <i>f_time[u] := time := time + 1</i> 
@@ -140,6 +141,8 @@ <H1><A NAME=(Python
 -
 <i>(u,v)</i> is a cross or forward edge
 -
+finish edge <i>(u,v)</i>
+-
 finish vertex <i>u</i>
 -
 </pre>
@@ -266,6 +269,9 @@ <h3>Visitor Event Points</h3>
 <li><b><tt>vis.forward_or_cross_edge(e, g)</tt></b> is invoked on
   forward or cross edges in the graph. In an undirected graph this
   method is never called.
+
+<li><b><tt>vis.finish_edge(e, g)</tt></b> is invoked on the non-tree edges in 
+  the graph as well as on each tree edge after its target vertex is finished. 
   
 <li><b><tt>vis.finish_vertex(u, g)</tt></b> is invoked on a vertex after
   all of its out edges have been added to the search tree and all of
diff --git a/doc/undirected_dfs.html b/doc/undirected_dfs.html
index ffbefa286..78def89b0 100644
--- a/doc/undirected_dfs.html
+++ b/doc/undirected_dfs.html
@@ -7,7 +7,7 @@
      http://www.boost.org/LICENSE_1_0.txt)
   -->
 <Head>
-<Title>Boost Graph Library: Depth-First Search</Title>
+<Title>Boost Graph Library: Undirected Depth-First Search</Title>
 <BODY BGCOLOR= call DFS-VISIT(G, v) else if (vcolor[v] = GRAY and ec = WHITE) ... + ... end for vcolor[u] := BLACK f_time[u] := time := time + 1 @@ -152,6 +153,8 @@

      (u,v) is a back edge - - +finish edge (u,v) +- finish vertex u - @@ -291,6 +294,9 @@

      Visitor Event Points

    2. vis.back_edge(e, g) is invoked on the back edges in the graph. +
    3. vis.finish_edge(e, g) is invoked on the back edges in + the graph as well as on each tree edge after its target vertex is finished. +
    4. vis.finish_vertex(u, g) is invoked on a vertex after all of its out edges have been added to the search tree and all of the adjacent vertices have been discovered (but before their diff --git a/example/dfs.cpp b/example/dfs.cpp index 9dd13da8c..e68ba39af 100644 --- a/example/dfs.cpp +++ b/example/dfs.cpp @@ -27,12 +27,18 @@ Tree edge: 0 --> 2 Tree edge: 2 --> 1 Back edge: 1 --> 1 + Finish edge: 1 --> 1 Tree edge: 1 --> 3 Back edge: 3 --> 1 + Finish edge: 3 --> 1 Tree edge: 3 --> 4 Back edge: 4 --> 0 + Finish edge: 4 --> 0 Back edge: 4 --> 1 + Finish edge: 4 --> 1 Forward or cross edge: 2 --> 3 + Finish edge: 2 --> 3 + Finish edge: 0 --> 2 1 10 3 8 2 9 @@ -69,6 +75,12 @@ struct edge_categorizer : public dfs_visitor { << " --> " << target(e, G) << endl; Base::forward_or_cross_edge(e, G); } + template + void finish_edge(Edge e, Graph& G) { + cout << "Finish edge: " << source(e, G) << + " --> " << target(e, G) << endl; + Base::finish_edge(e, G); + } }; template edge_categorizer diff --git a/example/dfs.expected b/example/dfs.expected index 84aa0c456..b0da6de42 100644 --- a/example/dfs.expected +++ b/example/dfs.expected @@ -1,12 +1,18 @@ Tree edge: 0 --> 2 Tree edge: 2 --> 1 Back edge: 1 --> 1 +Finish edge: 1 --> 1 Tree edge: 1 --> 3 Back edge: 3 --> 1 +Finish edge: 3 --> 1 Tree edge: 3 --> 4 Back edge: 4 --> 0 +Finish edge: 4 --> 0 Back edge: 4 --> 1 +Finish edge: 4 --> 1 Forward or cross edge: 2 --> 3 +Finish edge: 2 --> 3 +Finish edge: 0 --> 2 1 10 3 8 2 9 diff --git a/include/boost/graph/depth_first_search.hpp b/include/boost/graph/depth_first_search.hpp index 34d73a2fd..b002d3674 100644 --- a/include/boost/graph/depth_first_search.hpp +++ b/include/boost/graph/depth_first_search.hpp @@ -21,8 +21,10 @@ #include #include #include +#include #include #include +#include #include #include @@ -41,6 +43,7 @@ namespace boost { vis.tree_edge(e, g); vis.back_edge(e, g); vis.forward_or_cross_edge(e, g); + // vis.finish_edge(e, g); // Optional for user vis.finish_vertex(u, g); } private: @@ -57,6 +60,25 @@ namespace boost { bool operator()(const T&, const T2&) const { return false; } }; + BOOST_TTI_HAS_MEMBER_FUNCTION(finish_edge) + + template struct do_call_finish_edge { + template + static void call_finish_edge(Vis& vis, const E& e, const G& g) { + vis.finish_edge(e, g); + } + }; + + template <> struct do_call_finish_edge { + template + static void call_finish_edge(Vis&, const E&, const G&) {} + }; + + template + void call_finish_edge(Vis& vis, const E& e, const G& g) { // Only call if method exists + do_call_finish_edge::value>::call_finish_edge(vis, e, g); + } + // Define BOOST_RECURSIVE_DFS to use older, recursive version. // It is retained for a while in order to perform performance @@ -85,36 +107,35 @@ namespace boost { BOOST_CONCEPT_ASSERT(( IncidenceGraphConcept )); BOOST_CONCEPT_ASSERT(( DFSVisitorConcept )); typedef typename graph_traits::vertex_descriptor Vertex; + typedef typename graph_traits::edge_descriptor Edge; BOOST_CONCEPT_ASSERT(( ReadWritePropertyMapConcept )); typedef typename property_traits::value_type ColorValue; BOOST_CONCEPT_ASSERT(( ColorValueConcept )); typedef color_traits Color; typedef typename graph_traits::out_edge_iterator Iter; - typedef std::pair > VertexInfo; + typedef std::pair, std::pair > > VertexInfo; + boost::optional src_e; Iter ei, ei_end; std::vector stack; // Possible optimization for vector //stack.reserve(num_vertices(g)); - typedef typename unwrap_reference::type TF; - put(color, u, Color::gray()); vis.discover_vertex(u, g); boost::tie(ei, ei_end) = out_edges(u, g); - // Variable is needed to workaround a borland bug. - TF& fn = static_cast(func); - if (fn(u, g)) { + if (func(u, g)) { // If this vertex terminates the search, we push empty range - stack.push_back(std::make_pair(u, std::make_pair(ei_end, ei_end))); + stack.push_back(std::make_pair(u, std::make_pair(boost::optional(), std::make_pair(ei_end, ei_end)))); } else { - stack.push_back(std::make_pair(u, std::make_pair(ei, ei_end))); + stack.push_back(std::make_pair(u, std::make_pair(boost::optional(), std::make_pair(ei, ei_end)))); } while (!stack.empty()) { VertexInfo& back = stack.back(); u = back.first; - boost::tie(ei, ei_end) = back.second; + src_e = back.second.first; + boost::tie(ei, ei_end) = back.second.second; stack.pop_back(); while (ei != ei_end) { Vertex v = target(*ei, g); @@ -122,24 +143,28 @@ namespace boost { ColorValue v_color = get(color, v); if (v_color == Color::white()) { vis.tree_edge(*ei, g); - stack.push_back(std::make_pair(u, std::make_pair(++ei, ei_end))); + src_e = *ei; + stack.push_back(std::make_pair(u, std::make_pair(src_e, std::make_pair(++ei, ei_end)))); u = v; put(color, u, Color::gray()); vis.discover_vertex(u, g); boost::tie(ei, ei_end) = out_edges(u, g); - if (fn(u, g)) { + if (func(u, g)) { ei = ei_end; } - } else if (v_color == Color::gray()) { - vis.back_edge(*ei, g); - ++ei; } else { - vis.forward_or_cross_edge(*ei, g); + if (v_color == Color::gray()) { + vis.back_edge(*ei, g); + } else { + vis.forward_or_cross_edge(*ei, g); + } + call_finish_edge(vis, *ei, g); ++ei; } } put(color, u, Color::black()); vis.finish_vertex(u, g); + if (src_e) call_finish_edge(vis, src_e.get(), g); } } @@ -164,10 +189,7 @@ namespace boost { put(color, u, Color::gray()); vis.discover_vertex(u, g); - typedef typename unwrap_reference::type TF; - // Variable is needed to workaround a borland bug. - TF& fn = static_cast(func); - if (!fn(u, g)) + if (!func(u, g)) for (boost::tie(ei, ei_end) = out_edges(u, g); ei != ei_end; ++ei) { Vertex v = target(*ei, g); vis.examine_edge(*ei, g); ColorValue v_color = get(color, v); @@ -175,6 +197,7 @@ namespace boost { depth_first_visit_impl(g, v, vis, color, func); } else if (v_color == Color::gray()) vis.back_edge(*ei, g); else vis.forward_or_cross_edge(*ei, g); + call_finish_edge(vis, *ei, g); } put(color, u, Color::black()); vis.finish_vertex(u, g); } @@ -259,6 +282,10 @@ namespace boost { void forward_or_cross_edge(Edge u, const Graph& g) { invoke_visitors(m_vis, u, g, ::boost::on_forward_or_cross_edge()); } + template + void finish_edge(Edge u, const Graph& g) { + invoke_visitors(m_vis, u, g, ::boost::on_finish_edge()); + } template void finish_vertex(Vertex u, const Graph& g) { invoke_visitors(m_vis, u, g, ::boost::on_finish_vertex()); @@ -271,6 +298,7 @@ namespace boost { BOOST_GRAPH_EVENT_STUB(on_tree_edge,dfs) BOOST_GRAPH_EVENT_STUB(on_back_edge,dfs) BOOST_GRAPH_EVENT_STUB(on_forward_or_cross_edge,dfs) + BOOST_GRAPH_EVENT_STUB(on_finish_edge,dfs) BOOST_GRAPH_EVENT_STUB(on_finish_vertex,dfs) protected: diff --git a/include/boost/graph/undirected_dfs.hpp b/include/boost/graph/undirected_dfs.hpp index 0dcc9c284..89cb10f28 100644 --- a/include/boost/graph/undirected_dfs.hpp +++ b/include/boost/graph/undirected_dfs.hpp @@ -46,18 +46,18 @@ namespace boost { typedef color_traits Color; typedef color_traits EColor; typedef typename graph_traits::out_edge_iterator Iter; - typedef std::pair > VertexInfo; + typedef std::pair, std::pair > > VertexInfo; std::vector stack; put(vertex_color, u, Color::gray()); vis.discover_vertex(u, g); - stack.push_back(std::make_pair(u, out_edges(u, g))); + stack.push_back(std::make_pair(u, std::make_pair(boost::optional(), out_edges(u, g)))); while (!stack.empty()) { VertexInfo& back = stack.back(); u = back.first; - Iter ei, ei_end; - boost::tie(ei, ei_end) = back.second; + boost::optional src_e = back.second.first; + Iter ei = back.second.second.first, ei_end = back.second.second.second; stack.pop_back(); while (ei != ei_end) { Vertex v = target(*ei, g); @@ -67,20 +67,24 @@ namespace boost { put(edge_color, *ei, EColor::black()); if (v_color == Color::white()) { vis.tree_edge(*ei, g); - stack.push_back(std::make_pair(u, std::make_pair(++ei, ei_end))); + src_e = *ei; + stack.push_back(std::make_pair(u, std::make_pair(src_e, std::make_pair(++ei, ei_end)))); u = v; put(vertex_color, u, Color::gray()); vis.discover_vertex(u, g); boost::tie(ei, ei_end) = out_edges(u, g); } else if (v_color == Color::gray()) { if (uv_color == EColor::white()) vis.back_edge(*ei, g); + call_finish_edge(vis, *ei, g); ++ei; } else { // if (v_color == Color::black()) + call_finish_edge(vis, *ei, g); ++ei; } } put(vertex_color, u, Color::black()); vis.finish_vertex(u, g); + if (src_e) call_finish_edge(vis, src_e.get(), g); } } @@ -119,6 +123,7 @@ namespace boost { undir_dfv_impl(g, v, vis, vertex_color, edge_color); } else if (v_color == Color::gray() && uv_color == EColor::white()) vis.back_edge(*ei, g); + call_finish_edge(vis, *ei, g); } put(vertex_color, u, Color::black()); vis.finish_vertex(u, g); } @@ -219,8 +224,7 @@ namespace boost { undirected_dfs(const Graph& g, const bgl_named_params& params) { - typedef typename get_param_type< bgl_named_params, - vertex_color_t>::type C; + typedef typename get_param_type< vertex_color_t, bgl_named_params >::type C; detail::udfs_dispatch::apply (g, choose_param(get_param(params, graph_visitor), diff --git a/include/boost/graph/visitors.hpp b/include/boost/graph/visitors.hpp index f986c96ce..39314f5a5 100644 --- a/include/boost/graph/visitors.hpp +++ b/include/boost/graph/visitors.hpp @@ -44,7 +44,7 @@ namespace boost { on_discover_vertex_num, on_finish_vertex_num, on_examine_vertex_num, on_examine_edge_num, on_tree_edge_num, on_non_tree_edge_num, on_gray_target_num, on_black_target_num, - on_forward_or_cross_edge_num, on_back_edge_num, + on_forward_or_cross_edge_num, on_back_edge_num, on_finish_edge_num, on_edge_relaxed_num, on_edge_not_relaxed_num, on_edge_minimized_num, on_edge_not_minimized_num }; @@ -75,6 +75,7 @@ namespace boost { struct on_forward_or_cross_edge { enum { num = detail::on_forward_or_cross_edge_num }; }; struct on_back_edge { enum { num = detail::on_back_edge_num }; }; + struct on_finish_edge { enum { num = detail::on_finish_edge_num }; }; struct on_edge_relaxed { enum { num = detail::on_edge_relaxed_num }; }; struct on_edge_not_relaxed { diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index fd6e967cd..a2612d885 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -43,6 +43,7 @@ test-suite graph_test : [ run csr_graph_test.cpp : : : : : release ] [ run dag_longest_paths.cpp ] [ run dfs.cpp ../../test/build//boost_test_exec_monitor ] + [ run undirected_dfs.cpp ../../test/build//boost_test_exec_monitor ] [ compile dfs_cc.cpp ] [ compile dijkstra_cc.cpp ] [ run dijkstra_heap_performance.cpp : 10000 ] diff --git a/test/dfs.cpp b/test/dfs.cpp index fdffd4ef1..7f458e0a8 100644 --- a/test/dfs.cpp +++ b/test/dfs.cpp @@ -68,6 +68,12 @@ class dfs_test_visitor { using namespace boost; BOOST_CHECK( get(m_color, target(e, g)) == Color::black() ); } + template + void finish_edge(Edge e, Graph& g) { + using namespace boost; + BOOST_CHECK( get(m_color, target(e, g)) == Color::gray() || + get(m_color, target(e, g)) == Color::black() ); + } template void finish_vertex(Vertex u, Graph&) { using namespace boost; diff --git a/test/undirected_dfs.cpp b/test/undirected_dfs.cpp new file mode 100644 index 000000000..b9d4285ff --- /dev/null +++ b/test/undirected_dfs.cpp @@ -0,0 +1,187 @@ +//======================================================================= +// Copyright 2001 University of Notre Dame. +// Author: Jeremy G. Siek +// +// 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) +//======================================================================= + +#include +#include +#include + +#include +#include +#include +#include +#include + +#include + +template +class dfs_test_visitor { + typedef typename boost::property_traits::value_type ColorValue; + typedef typename boost::color_traits Color; +public: + dfs_test_visitor(ColorMap color, ParentMap p, DiscoverTimeMap d, + FinishTimeMap f) + : m_color(color), m_parent(p), + m_discover_time(d), m_finish_time(f), m_time(0) { } + + template + void initialize_vertex(Vertex u, Graph&) { + BOOST_CHECK( boost::get(m_color, u) == Color::white() ); + } + template + void start_vertex(Vertex u, Graph&) { + BOOST_CHECK( boost::get(m_color, u) == Color::white() ); + } + template + void discover_vertex(Vertex u, Graph&) { + using namespace boost; + BOOST_CHECK( get(m_color, u) == Color::gray() ); + BOOST_CHECK( get(m_color, get(m_parent, u)) == Color::gray() ); + + put(m_discover_time, u, m_time++); + } + template + void examine_edge(Edge e, Graph& g) { + using namespace boost; + BOOST_CHECK( get(m_color, source(e, g)) == Color::gray() ); + } + template + void tree_edge(Edge e, Graph& g) { + using namespace boost; + BOOST_CHECK( get(m_color, target(e, g)) == Color::white() ); + + put(m_parent, target(e, g), source(e, g)); + } + template + void back_edge(Edge e, Graph& g) { + using namespace boost; + BOOST_CHECK( get(m_color, target(e, g)) == Color::gray() ); + } + template + void forward_or_cross_edge(Edge e, Graph& g) { + using namespace boost; + BOOST_CHECK( get(m_color, target(e, g)) == Color::black() ); + } + template + void finish_edge(Edge e, Graph& g) { + using namespace boost; + BOOST_CHECK( + (get(m_color, target(e, g)) == Color::gray()) + || (get(m_color, target(e, g)) == Color::black()) + ); + } + template + void finish_vertex(Vertex u, Graph&) { + using namespace boost; + BOOST_CHECK( get(m_color, u) == Color::black() ); + + put(m_finish_time, u, m_time++); + } +private: + ColorMap m_color; + ParentMap m_parent; + DiscoverTimeMap m_discover_time; + FinishTimeMap m_finish_time; + typename boost::property_traits::value_type m_time; +}; + +template +struct dfs_test +{ + typedef boost::graph_traits Traits; + typedef typename Traits::vertices_size_type + vertices_size_type; + + static void go(vertices_size_type max_V) { + using namespace boost; + typedef typename Traits::vertex_descriptor vertex_descriptor; + typedef typename boost::property_map::type ColorMap; + typedef typename boost::property_traits::value_type ColorValue; + typedef typename boost::color_traits Color; + typedef typename boost::property_map::type EColorMap; + typedef typename boost::property_traits::value_type EColorValue; + typedef typename boost::color_traits EColor; + + vertices_size_type i, k; + typename Traits::edges_size_type j; + typename Traits::vertex_iterator vi, vi_end, ui, ui_end; + typename Traits::edge_iterator ei, ei_end; + + boost::mt19937 gen; + + for (i = 0; i < max_V; ++i) + for (j = 0; j < i*i; ++j) { + Graph g; + generate_random_graph(g, i, j, gen); + + ColorMap color = get(boost::vertex_color, g); + EColorMap e_color = get(boost::edge_color, g); + std::vector parent(num_vertices(g)); + for (k = 0; k < num_vertices(g); ++k) + parent[k] = k; + std::vector discover_time(num_vertices(g)), + finish_time(num_vertices(g)); + + dfs_test_visitor vis(color, &parent[0], + &discover_time[0], &finish_time[0]); + + boost::undirected_dfs(g, visitor(vis).color_map(color) + .edge_color_map(e_color)); + + // all vertices should be black + for (boost::tie(vi, vi_end) = vertices(g); vi != vi_end; ++vi) + BOOST_CHECK(get(color, *vi) == Color::black()); + + // all edges should be black + for (boost::tie(ei, ei_end) = edges(g); ei != ei_end; ++ei) + BOOST_CHECK(get(e_color, *ei) == EColor::black()); + + // check parenthesis structure of discover/finish times + // See CLR p.480 + for (boost::tie(ui, ui_end) = vertices(g); ui != ui_end; ++ui) + for (boost::tie(vi, vi_end) = vertices(g); vi != vi_end; ++vi) { + vertex_descriptor u = *ui, v = *vi; + if (u != v) { + BOOST_CHECK( finish_time[u] < discover_time[v] + || finish_time[v] < discover_time[u] + || (discover_time[v] < discover_time[u] + && finish_time[u] < finish_time[v] + && boost::is_descendant(u, v, &parent[0])) + || (discover_time[u] < discover_time[v] + && finish_time[v] < finish_time[u] + && boost::is_descendant(v, u, &parent[0])) + ); + } + } + } + + } +}; + + +// usage: undirected_dfs.exe [max-vertices=15] + +int test_main(int argc, char* argv[]) +{ + int max_V = 7; + if (argc > 1) + max_V = atoi(argv[1]); + + // Test undirected graphs. + dfs_test< boost::adjacency_list, + boost::property > + >::go(max_V); + + return 0; +} + From 117689a3f99d75cd674f9b172fd6428b209811b3 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Mon, 16 Apr 2012 23:17:12 +0000 Subject: [PATCH 172/333] Fixed argument order to get_param_type [SVN r78031] --- include/boost/graph/biconnected_components.hpp | 15 +++++---------- include/boost/graph/edmonds_karp_max_flow.hpp | 6 +++--- include/boost/graph/fruchterman_reingold.hpp | 3 +-- include/boost/graph/neighbor_bfs.hpp | 3 +-- 4 files changed, 10 insertions(+), 17 deletions(-) diff --git a/include/boost/graph/biconnected_components.hpp b/include/boost/graph/biconnected_components.hpp index f31b24a1d..efe96aeca 100644 --- a/include/boost/graph/biconnected_components.hpp +++ b/include/boost/graph/biconnected_components.hpp @@ -243,8 +243,7 @@ namespace boost DiscoverTimeMap dtm, const bgl_named_params& params, LowPointMap lowpt) { - typedef typename get_param_type< bgl_named_params, - vertex_predecessor_t>::type dispatch_type; + typedef typename get_param_type< vertex_predecessor_t, bgl_named_params >::type dispatch_type; return bicomp_dispatch3::apply (g, comp, out, index_map, dtm, lowpt, params, @@ -269,8 +268,7 @@ namespace boost std::vector lowpt(num_vertices(g)); vertices_size_type vst(0); - typedef typename get_param_type< bgl_named_params, - vertex_predecessor_t>::type dispatch_type; + typedef typename get_param_type< vertex_predecessor_t, bgl_named_params >::type dispatch_type; return bicomp_dispatch3::apply (g, comp, out, index_map, dtm, @@ -288,8 +286,7 @@ namespace boost ComponentMap comp, OutputIterator out, VertexIndexMap index_map, const bgl_named_params& params, DiscoverTimeMap dtm) { - typedef typename get_param_type< bgl_named_params, - vertex_lowpoint_t>::type dispatch_type; + typedef typename get_param_type< vertex_lowpoint_t, bgl_named_params >::type dispatch_type; return bicomp_dispatch2::apply (g, comp, out, index_map, dtm, params, @@ -311,8 +308,7 @@ namespace boost std::vector discover_time(num_vertices(g)); vertices_size_type vst(0); - typedef typename get_param_type< bgl_named_params, - vertex_lowpoint_t>::type dispatch_type; + typedef typename get_param_type< vertex_lowpoint_t, bgl_named_params >::type dispatch_type; return bicomp_dispatch2::apply (g, comp, out, index_map, @@ -345,8 +341,7 @@ namespace boost biconnected_components(const Graph& g, ComponentMap comp, OutputIterator out, const bgl_named_params& params) { - typedef typename get_param_type< bgl_named_params, - vertex_discover_time_t>::type dispatch_type; + typedef typename get_param_type< vertex_discover_time_t, bgl_named_params >::type dispatch_type; return detail::bicomp_dispatch1::apply(g, comp, out, choose_const_pmap(get_param(params, vertex_index), g, vertex_index), diff --git a/include/boost/graph/edmonds_karp_max_flow.hpp b/include/boost/graph/edmonds_karp_max_flow.hpp index 62d1271c4..8f86fb202 100644 --- a/include/boost/graph/edmonds_karp_max_flow.hpp +++ b/include/boost/graph/edmonds_karp_max_flow.hpp @@ -183,7 +183,7 @@ namespace boost { const bgl_named_params& params, PredMap pred) { - typedef typename get_param_type< bgl_named_params, vertex_color_t>::type C; + typedef typename get_param_type< vertex_color_t, bgl_named_params >::type C; return edmonds_karp_dispatch2::apply (g, src, sink, pred, params, get_param(params, vertex_color)); } @@ -206,7 +206,7 @@ namespace boost { num_vertices(g) : 1; std::vector pred_vec(n); - typedef typename get_param_type< bgl_named_params, vertex_color_t>::type C; + typedef typename get_param_type< vertex_color_t, bgl_named_params >::type C; return edmonds_karp_dispatch2::apply (g, src, sink, make_iterator_property_map(pred_vec.begin(), choose_const_pmap @@ -227,7 +227,7 @@ namespace boost { typename graph_traits::vertex_descriptor sink, const bgl_named_params& params) { - typedef typename get_param_type< bgl_named_params, vertex_predecessor_t>::type Pred; + typedef typename get_param_type< vertex_predecessor_t, bgl_named_params >::type Pred; return detail::edmonds_karp_dispatch1::apply (g, src, sink, params, get_param(params, vertex_predecessor)); } diff --git a/include/boost/graph/fruchterman_reingold.hpp b/include/boost/graph/fruchterman_reingold.hpp index b10ced643..bab353f33 100644 --- a/include/boost/graph/fruchterman_reingold.hpp +++ b/include/boost/graph/fruchterman_reingold.hpp @@ -404,8 +404,7 @@ fruchterman_reingold_force_directed_layout const Topology& topology, const bgl_named_params& params) { - typedef typename get_param_type, - vertex_displacement_t>::type D; + typedef typename get_param_type >::type D; detail::fr_force_directed_layout::run (g, position, topology, diff --git a/include/boost/graph/neighbor_bfs.hpp b/include/boost/graph/neighbor_bfs.hpp index edfcbbb45..4830dcc4e 100644 --- a/include/boost/graph/neighbor_bfs.hpp +++ b/include/boost/graph/neighbor_bfs.hpp @@ -288,8 +288,7 @@ namespace boost { // graph is not really const since we may write to property maps // of the graph. VertexListGraph& ng = const_cast(g); - typedef typename get_param_type< bgl_named_params, - vertex_color_t>::type C; + typedef typename get_param_type< vertex_color_t, bgl_named_params >::type C; detail::neighbor_bfs_dispatch::apply(ng, s, params, get_param(params, vertex_color)); } From bec6cb4dda0eb1248918e6f72a8c4f6bdae73f0c Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Tue, 17 Apr 2012 19:53:26 +0000 Subject: [PATCH 173/333] Disabled build on Sun; waiting to disable in regression test output until results show that library is not built [SVN r78053] --- build/Jamfile.v2 | 1 + 1 file changed, 1 insertion(+) diff --git a/build/Jamfile.v2 b/build/Jamfile.v2 index 19cb65f19..6bf7f5bde 100644 --- a/build/Jamfile.v2 +++ b/build/Jamfile.v2 @@ -21,6 +21,7 @@ lib boost_graph # Without these flags, MSVC 7.1 and 8.0 crash # User reports that VC++ 8.0 does not fail anymore, so that is removed msvc-7.1:-GR- + sun:no : : ; From d42d54b54eef7c2fd053e706628eb1b38cd775b5 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Thu, 19 Apr 2012 03:30:59 +0000 Subject: [PATCH 174/333] Removed #error for lack of bundled properties [SVN r78076] --- include/boost/graph/compressed_sparse_row_graph.hpp | 5 ----- 1 file changed, 5 deletions(-) diff --git a/include/boost/graph/compressed_sparse_row_graph.hpp b/include/boost/graph/compressed_sparse_row_graph.hpp index a26fd977e..d5b472b4c 100644 --- a/include/boost/graph/compressed_sparse_row_graph.hpp +++ b/include/boost/graph/compressed_sparse_row_graph.hpp @@ -44,11 +44,6 @@ #include #include -#ifdef BOOST_GRAPH_NO_BUNDLED_PROPERTIES -# error The Compressed Sparse Row graph only supports bundled properties. -# error You will need a compiler that conforms better to the C++ standard. -#endif - namespace boost { // A tag type indicating that the graph in question is a compressed From 0586ac290f1520999e935072999dee6c55b123df Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Thu, 3 May 2012 16:20:58 +0000 Subject: [PATCH 175/333] Edited reverse_graph to fix test case; fixes #6858 [SVN r78315] --- include/boost/graph/reverse_graph.hpp | 37 +++++++++++++++------------ 1 file changed, 21 insertions(+), 16 deletions(-) diff --git a/include/boost/graph/reverse_graph.hpp b/include/boost/graph/reverse_graph.hpp index 84509a330..c4c35bbb0 100644 --- a/include/boost/graph/reverse_graph.hpp +++ b/include/boost/graph/reverse_graph.hpp @@ -105,6 +105,7 @@ class reverse_graph { typedef graph_traits Traits; public: typedef BidirectionalGraph base_type; + typedef GraphRef base_ref_type; // Constructor reverse_graph(GraphRef g) : m_g(g) {} @@ -446,36 +447,40 @@ struct property_map, edge_underlying_t> { typedef detail::underlying_edge_desc_map_type const_type; }; -template -detail::underlying_edge_desc_map_type::edge_descriptor> +template struct is_reverse_graph: boost::mpl::false_ {}; +template struct is_reverse_graph >: boost::mpl::true_ {}; + +template +typename enable_if, + detail::underlying_edge_desc_map_type::edge_descriptor> >::type get(edge_underlying_t, - reverse_graph& g) + G& g) { - return detail::underlying_edge_desc_map_type::edge_descriptor>(); + return detail::underlying_edge_desc_map_type::edge_descriptor>(); } -template -typename graph_traits::edge_descriptor +template +typename enable_if, typename graph_traits::edge_descriptor>::type get(edge_underlying_t, - reverse_graph& g, - const typename graph_traits >::edge_descriptor& k) + G& g, + const typename graph_traits::edge_descriptor& k) { return k.underlying_descx; } -template -detail::underlying_edge_desc_map_type::edge_descriptor> +template +typename enable_if, detail::underlying_edge_desc_map_type::edge_descriptor> >::type get(edge_underlying_t, - const reverse_graph& g) + const G& g) { - return detail::underlying_edge_desc_map_type::edge_descriptor>(); + return detail::underlying_edge_desc_map_type::edge_descriptor>(); } -template -typename graph_traits::edge_descriptor +template +typename enable_if, typename graph_traits::edge_descriptor>::type get(edge_underlying_t, - const reverse_graph& g, - const typename graph_traits >::edge_descriptor& k) + const G& g, + const typename graph_traits::edge_descriptor& k) { return k.underlying_descx; } From 429112df7c7614ca3cf9d7a93ed42bef2ac805e6 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Sat, 5 May 2012 02:50:55 +0000 Subject: [PATCH 176/333] Fixed ambiguous call [SVN r78327] --- include/boost/graph/reverse_graph.hpp | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/include/boost/graph/reverse_graph.hpp b/include/boost/graph/reverse_graph.hpp index c4c35bbb0..96fc32d3a 100644 --- a/include/boost/graph/reverse_graph.hpp +++ b/include/boost/graph/reverse_graph.hpp @@ -379,14 +379,18 @@ struct property_map, Property> { }; template -typename property_map, Property>::type +typename disable_if< + is_same, + typename property_map, Property>::type>::type get(Property p, reverse_graph& g) { return typename property_map, Property>::type(get(p, g.m_g)); } template -typename property_map, Property>::const_type +typename disable_if< + is_same, + typename property_map, Property>::const_type>::type get(Property p, const reverse_graph& g) { const BidirGraph& gref = g.m_g; // in case GRef is non-const @@ -394,9 +398,11 @@ get(Property p, const reverse_graph& g) } template -typename property_traits< - typename property_map, Property>::const_type ->::value_type +typename disable_if< + is_same, + typename property_traits< + typename property_map, Property>::const_type + >::value_type>::type get(Property p, const reverse_graph& g, const Key& k) { return get(get(p, g), k); From 8e40b350e3af90b1e9093e98f552b419f5d48a7c Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Sat, 5 May 2012 02:52:41 +0000 Subject: [PATCH 177/333] Qualified calls to tie [SVN r78328] --- .../boost/graph/two_graphs_common_spanning_trees.hpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/include/boost/graph/two_graphs_common_spanning_trees.hpp b/include/boost/graph/two_graphs_common_spanning_trees.hpp index 8a62a367f..9bd5acb0c 100644 --- a/include/boost/graph/two_graphs_common_spanning_trees.hpp +++ b/include/boost/graph/two_graphs_common_spanning_trees.hpp @@ -635,11 +635,11 @@ two_graphs_common_spanning_trees vG_bimap.insert(bimap_value(i, vG_map[i])); edge_iterator current, last; - tie(current, last) = edges(iG); + boost::tuples::tie(current, last) = edges(iG); for(; current != last; ++current) if(iG_bimap.right.find(*current) == iG_bimap.right.end()) return; - tie(current, last) = edges(vG); + boost::tuples::tie(current, last) = edges(vG); for(; current != last; ++current) if(vG_bimap.right.find(*current) == vG_bimap.right.end()) return; @@ -749,10 +749,10 @@ two_graphs_common_spanning_trees associative_property_map< std::map > diG(iG_deleted); associative_property_map< std::map > dvG(vG_deleted); - tie(current, last) = edges(iG); + boost::tuples::tie(current, last) = edges(iG); for(; current != last; ++current) put(diG, *current, false); - tie(current, last) = edges(vG); + boost::tuples::tie(current, last) = edges(vG); for(; current != last; ++current) put(dvG, *current, false); @@ -852,11 +852,11 @@ two_graphs_common_spanning_trees std::vector iGO, vGO; edge_iterator curr, last; - tie(curr, last) = edges(iG); + boost::tuples::tie(curr, last) = edges(iG); for(; curr != last; ++curr) iGO.push_back(*curr); - tie(curr, last) = edges(vG); + boost::tuples::tie(curr, last) = edges(vG); for(; curr != last; ++curr) vGO.push_back(*curr); From 1441c152558525920a02a50988c6cf27d4f5e32d Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Sat, 5 May 2012 03:07:40 +0000 Subject: [PATCH 178/333] Removed use of Boost.Typeof to enhance portability; using Boost.ResultOf instead [SVN r78329] --- include/boost/graph/named_function_params.hpp | 10 ++++++++-- include/boost/graph/stoer_wagner_min_cut.hpp | 6 ++++-- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/include/boost/graph/named_function_params.hpp b/include/boost/graph/named_function_params.hpp index ed8736534..32dd58023 100644 --- a/include/boost/graph/named_function_params.hpp +++ b/include/boost/graph/named_function_params.hpp @@ -17,9 +17,8 @@ #include #include #include -#include +#include #include -#include #include #include #include @@ -686,6 +685,13 @@ BOOST_BGL_DECLARE_NAMED_PARAMS make_priority_queue_from_arg_pack_gen(KeyT defaultKey_) : defaultKey(defaultKey_) { } + template + struct result { + typedef typename remove_const::arg1_type>::type>::type graph_type; + typedef typename remove_const::arg2_type>::type>::type arg_pack_type; + typedef typename priority_queue_maker::priority_queue_type type; + }; + template typename priority_queue_maker::priority_queue_type operator()(const Graph& g, const ArgPack& ap) const { diff --git a/include/boost/graph/stoer_wagner_min_cut.hpp b/include/boost/graph/stoer_wagner_min_cut.hpp index 814eae0ce..060f51b4a 100644 --- a/include/boost/graph/stoer_wagner_min_cut.hpp +++ b/include/boost/graph/stoer_wagner_min_cut.hpp @@ -20,7 +20,7 @@ #include #include #include -#include +#include namespace boost { @@ -218,7 +218,9 @@ namespace boost { typedef boost::bgl_named_params params_type; BOOST_GRAPH_DECLARE_CONVERTED_PARAMETERS(params_type, params) - BOOST_AUTO(pq, (boost::detail::make_priority_queue_from_arg_pack_gen >(choose_param(get_param(params, boost::distance_zero_t()), weight_type(0)))(g, arg_pack))); + typedef boost::detail::make_priority_queue_from_arg_pack_gen > gen_type; + gen_type gen(choose_param(get_param(params, boost::distance_zero_t()), weight_type(0))); + typename boost::result_of::type pq = gen(g, arg_pack); return boost::detail::stoer_wagner_min_cut(g, weights, From 1eb950d63084e4378de1d65780c08d28ae51187d Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Sat, 5 May 2012 03:08:49 +0000 Subject: [PATCH 179/333] Removed use of Boost.Typeof to enhance portability; using Boost.ResultOf instead [SVN r78330] --- test/stoer_wagner_test.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/test/stoer_wagner_test.cpp b/test/stoer_wagner_test.cpp index 8f9fc819f..034d5498f 100644 --- a/test/stoer_wagner_test.cpp +++ b/test/stoer_wagner_test.cpp @@ -206,10 +206,12 @@ BOOST_AUTO_TEST_CASE(test_prgen_20_70_2) boost::associative_property_map > components(component); BOOST_CHECK_EQUAL(boost::connected_components(g, components), 1U); // verify the connectedness assumption - boost::shared_array_property_map::const_type> distances = boost::make_shared_array_property_map(num_vertices(g), weight_type(0), get(boost::vertex_index, g)); + typedef boost::shared_array_property_map::const_type> distances_type; + distances_type distances = boost::make_shared_array_property_map(num_vertices(g), weight_type(0), get(boost::vertex_index, g)); typedef std::vector::size_type index_in_heap_type; - boost::shared_array_property_map::const_type> indicesInHeap = boost::make_shared_array_property_map(num_vertices(g), index_in_heap_type(-1), get(boost::vertex_index, g)); - boost::d_ary_heap_indirect > pq(distances, indicesInHeap); + typedef boost::shared_array_property_map::const_type> indicesInHeap_type; + indicesInHeap_type indicesInHeap = boost::make_shared_array_property_map(num_vertices(g), index_in_heap_type(-1), get(boost::vertex_index, g)); + boost::d_ary_heap_indirect > pq(distances, indicesInHeap); int w = boost::stoer_wagner_min_cut(g, get(boost::edge_weight, g), boost::max_priority_queue(pq)); BOOST_CHECK_EQUAL(w, 3407); From 2d70ac725481b9556f345f50103d494ec3f4bb96 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Fri, 11 May 2012 19:37:54 +0000 Subject: [PATCH 180/333] Fixed handling of self-loops; fixes #4622 [SVN r78425] --- include/boost/graph/detail/adjacency_list.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/boost/graph/detail/adjacency_list.hpp b/include/boost/graph/detail/adjacency_list.hpp index cab4cecbc..2cf4677af 100644 --- a/include/boost/graph/detail/adjacency_list.hpp +++ b/include/boost/graph/detail/adjacency_list.hpp @@ -988,15 +988,15 @@ namespace boost { bool is_self_loop = (*ei).get_target() == u; // Don't erase from our own incidence list in the case of a self-loop // since we're clearing it anyway. + typename Config::OutEdgeList::iterator ei_copy = ei; if (!is_self_loop) { detail::erase_from_incidence_list (g.out_edge_list((*ei).get_target()), u, Cat()); - typename Config::OutEdgeList::iterator ei_copy = ei; ++ei; - if (!is_self_loop) g.m_edges.erase((*ei_copy).get_iter()); } else { ++ei; } + g.m_edges.erase((*ei_copy).get_iter()); } g.out_edge_list(u).clear(); } From 4e5382d828bdb518ca3dde0da261236fa05a6276 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Fri, 11 May 2012 21:03:19 +0000 Subject: [PATCH 181/333] Trying to fix undirected clear_vertex() again; refs #4622 [SVN r78428] --- include/boost/graph/detail/adjacency_list.hpp | 35 +++++++++++-------- 1 file changed, 20 insertions(+), 15 deletions(-) diff --git a/include/boost/graph/detail/adjacency_list.hpp b/include/boost/graph/detail/adjacency_list.hpp index 2cf4677af..4525dce57 100644 --- a/include/boost/graph/detail/adjacency_list.hpp +++ b/include/boost/graph/detail/adjacency_list.hpp @@ -981,22 +981,27 @@ namespace boost { typedef typename Config::graph_type graph_type; typedef typename Config::edge_parallel_category Cat; graph_type& g = static_cast(g_); - typename Config::OutEdgeList& el = g.out_edge_list(u); - typename Config::OutEdgeList::iterator - ei = el.begin(), ei_end = el.end(); - for (; ei != ei_end; /* Increment below */ ) { - bool is_self_loop = (*ei).get_target() == u; - // Don't erase from our own incidence list in the case of a self-loop - // since we're clearing it anyway. - typename Config::OutEdgeList::iterator ei_copy = ei; - if (!is_self_loop) { - detail::erase_from_incidence_list - (g.out_edge_list((*ei).get_target()), u, Cat()); - ++ei; - } else { - ++ei; + { + typename Config::OutEdgeList& el = g.out_edge_list(u); + typename Config::OutEdgeList::iterator + ei = el.begin(), ei_end = el.end(); + for (; ei != ei_end; ++ei) { + bool is_self_loop = (*ei).get_target() == u; + // Don't erase from our own incidence list in the case of a self-loop + // since we're clearing it anyway. + if (!is_self_loop) { + detail::erase_from_incidence_list + (g.out_edge_list((*ei).get_target()), u, Cat()); + } + } + } + { + typename Config::OutEdgeList& el = g.out_edge_list(u); + typename Config::OutEdgeList::iterator + ei = el.begin(), ei_end = el.end(); + for (; ei != ei_end; ++ei) { + g.m_edges.erase((*ei).get_iter()); } - g.m_edges.erase((*ei_copy).get_iter()); } g.out_edge_list(u).clear(); } From 48860d938cc3c573fef4562439daaa14be09288c Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Sat, 12 May 2012 18:46:34 +0000 Subject: [PATCH 182/333] Removed unnecessary concept requirement; fixes #6892 [SVN r78438] --- include/boost/graph/bron_kerbosch_all_cliques.hpp | 1 - 1 file changed, 1 deletion(-) diff --git a/include/boost/graph/bron_kerbosch_all_cliques.hpp b/include/boost/graph/bron_kerbosch_all_cliques.hpp index 91960936e..b663cf95f 100644 --- a/include/boost/graph/bron_kerbosch_all_cliques.hpp +++ b/include/boost/graph/bron_kerbosch_all_cliques.hpp @@ -270,7 +270,6 @@ bron_kerbosch_all_cliques(const Graph& g, Visitor vis, std::size_t min) { BOOST_CONCEPT_ASSERT(( IncidenceGraphConcept )); BOOST_CONCEPT_ASSERT(( VertexListGraphConcept )); - BOOST_CONCEPT_ASSERT(( VertexIndexGraphConcept )); BOOST_CONCEPT_ASSERT(( AdjacencyMatrixConcept )); // Structural requirement only typedef typename graph_traits::vertex_descriptor Vertex; typedef typename graph_traits::vertex_iterator VertexIterator; From 856e0fb3ab7b6257c951ef800fb20da476a16301 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Sat, 12 May 2012 20:10:11 +0000 Subject: [PATCH 183/333] Fixed bugs in remove_edge and clear_vertex for undirected graphs; refs #4622 [SVN r78439] --- include/boost/graph/detail/adjacency_list.hpp | 40 +++++++------------ 1 file changed, 14 insertions(+), 26 deletions(-) diff --git a/include/boost/graph/detail/adjacency_list.hpp b/include/boost/graph/detail/adjacency_list.hpp index 4525dce57..fa3989890 100644 --- a/include/boost/graph/detail/adjacency_list.hpp +++ b/include/boost/graph/detail/adjacency_list.hpp @@ -717,8 +717,10 @@ namespace boost { typename Config::OutEdgeList& out_el = g.out_edge_list(source(e, g)); typename Config::OutEdgeList::iterator out_i = out_el.begin(); + typename Config::EdgeIter edge_iter_to_erase; for (; out_i != out_el.end(); ++out_i) if (&(*out_i).get_property() == &p) { + edge_iter_to_erase = (*out_i).get_iter(); out_el.erase(out_i); break; } @@ -726,10 +728,10 @@ namespace boost { typename Config::OutEdgeList::iterator in_i = in_el.begin(); for (; in_i != in_el.end(); ++in_i) if (&(*in_i).get_property() == &p) { - g.m_edges.erase((*in_i).get_iter()); in_el.erase(in_i); - return; + break; } + g.m_edges.erase(edge_iter_to_erase); } }; @@ -750,8 +752,10 @@ namespace boost { no_property* p = (no_property*)e.get_property(); typename Config::OutEdgeList& out_el = g.out_edge_list(source(e, g)); typename Config::OutEdgeList::iterator out_i = out_el.begin(); + typename Config::EdgeIter edge_iter_to_erase; for (; out_i != out_el.end(); ++out_i) if (&(*out_i).get_property() == p) { + edge_iter_to_erase = (*out_i).get_iter(); out_el.erase(out_i); break; } @@ -759,10 +763,10 @@ namespace boost { typename Config::OutEdgeList::iterator in_i = in_el.begin(); for (; in_i != in_el.end(); ++in_i) if (&(*in_i).get_property() == p) { - g.m_edges.erase((*in_i).get_iter()); in_el.erase(in_i); - return; + break; } + g.m_edges.erase(edge_iter_to_erase); } }; @@ -801,6 +805,7 @@ namespace boost { typedef typename EdgeList::value_type StoredEdge; typename EdgeList::iterator i = el.find(StoredEdge(v)), end = el.end(); + BOOST_ASSERT ((i != end)); if (i != end) { g.m_edges.erase((*i).get_iter()); el.erase(i); @@ -981,29 +986,12 @@ namespace boost { typedef typename Config::graph_type graph_type; typedef typename Config::edge_parallel_category Cat; graph_type& g = static_cast(g_); - { - typename Config::OutEdgeList& el = g.out_edge_list(u); - typename Config::OutEdgeList::iterator - ei = el.begin(), ei_end = el.end(); - for (; ei != ei_end; ++ei) { - bool is_self_loop = (*ei).get_target() == u; - // Don't erase from our own incidence list in the case of a self-loop - // since we're clearing it anyway. - if (!is_self_loop) { - detail::erase_from_incidence_list - (g.out_edge_list((*ei).get_target()), u, Cat()); - } - } + while (true) { + typename Config::out_edge_iterator ei, ei_end; + boost::tie(ei, ei_end) = out_edges(u, g); + if (ei == ei_end) break; + remove_edge(*ei, g); } - { - typename Config::OutEdgeList& el = g.out_edge_list(u); - typename Config::OutEdgeList::iterator - ei = el.begin(), ei_end = el.end(); - for (; ei != ei_end; ++ei) { - g.m_edges.erase((*ei).get_iter()); - } - } - g.out_edge_list(u).clear(); } // O(1) for allow_parallel_edge_tag // O(log(E/V)) for disallow_parallel_edge_tag From 34ba5d36d77564c96d55c1df1036174e9f8132af Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Sat, 12 May 2012 20:36:02 +0000 Subject: [PATCH 184/333] Fixed uses of std::min [SVN r78441] --- include/boost/graph/two_graphs_common_spanning_trees.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/boost/graph/two_graphs_common_spanning_trees.hpp b/include/boost/graph/two_graphs_common_spanning_trees.hpp index 9bd5acb0c..2578b14ec 100644 --- a/include/boost/graph/two_graphs_common_spanning_trees.hpp +++ b/include/boost/graph/two_graphs_common_spanning_trees.hpp @@ -78,7 +78,7 @@ namespace detail { void back_edge(const Edge& e, const Graph& g) { put(mLow, source(e, g), - std::min(get(mLow, source(e, g)), get(mDist, target(e, g)))); + (std::min)(get(mLow, source(e, g)), get(mDist, target(e, g)))); } template @@ -88,7 +88,7 @@ namespace detail { if(get(mLow, u) > get(mDist, parent)) mBuffer.push(get(mTree, u)); put(mLow, parent, - std::min(get(mLow, parent), get(mLow, u))); + (std::min)(get(mLow, parent), get(mLow, u))); } TreeMap mTree; From b37570381b1e3ab3f69e0bd963b8f5e6a33466c5 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Sat, 12 May 2012 20:46:47 +0000 Subject: [PATCH 185/333] Fixed inspect warnings and typos [SVN r78442] --- doc/directed_graph.html | 103 +----------------- example/two_graphs_common_spanning_trees.cpp | 2 +- .../boost/graph/biconnected_components.hpp | 7 +- include/boost/graph/detail/histogram_sort.hpp | 10 +- .../two_graphs_common_spanning_trees.hpp | 2 +- .../two_graphs_common_spanning_trees_test.cpp | 2 +- 6 files changed, 16 insertions(+), 110 deletions(-) diff --git a/doc/directed_graph.html b/doc/directed_graph.html index d17038c40..227a3fa30 100644 --- a/doc/directed_graph.html +++ b/doc/directed_graph.html @@ -23,7 +23,7 @@

      -The directed_graph class template is is a simplified version +The directed_graph class template is a simplified version of the BGL adjacency list. This class is provided for ease of use, but may not perform as well as custom-defined adjacency list classes. Instances of this template model the BidirectionalGraph, VertexIndexGraph, and @@ -36,105 +36,10 @@

      Example

      -  typedef boost::directed_graph<> Graph;
      +  typedef boost::directed_graph<> Graph;
         Graph g;
      -  boost::graph_traits::vertex_descriptor v0 = g.add_vertex();
      -  boost::graph_traits::vertex_descriptor v1 = g.add_vertex();
      -
      -  g.add_edge(v0, v1);
      -
      - -

      Template Parameters

      - -

      - - - - - - - - - - - - - - - - - - - - - -
      ParameterDescriptionDefault
      VertexPropA property map for the graph vertices. 
      EdgePropA property map for the graph edges. 
      GraphPropA property map for the graph itself.
      -

      - -

      Where Defined

      - -

      -boost/graph/directed_graph.hpp - -

      - -
      -


      - - -
      Copyright © 2000-2001 -Jeremy Siek, -Indiana University (jsiek@osl.iu.edu)
      -Lie-Quan Lee, Indiana University (llee@cs.indiana.edu)
      -Andrew Lumsdaine, -Indiana University (lums@osl.iu.edu) -
      - - - - - - -Boost Graph Library: Directed Graph - -C++ Boost - -
      - -

      -
      -directed_graph<VertexProp, EdgeProp, GraphProp>
      -
      -

      - - -

      -The directed_graph class template is is a simplified version -of the BGL adjacency list. This class is provided for ease of use, but -may not perform as well as custom-defined adjacency list classes. Instances -of this template model the BidirectionalGraph, VertexIndexGraph, and -EdgeIndexGraph concepts. - -

      Example

      - -

      - - -

      -  typedef boost::directed_graph<> Graph;
      -  Graph g;
      -  Graph::vertex_descriptor v0 = g.add_vertex();
      -  Graph::vertex_descriptor v1 = g.add_vertex();
      +  boost::graph_traits<Graph>::vertex_descriptor v0 = g.add_vertex();
      +  boost::graph_traits<Graph>::vertex_descriptor v1 = g.add_vertex();
       
         g.add_edge(v0, v1);
       
      diff --git a/example/two_graphs_common_spanning_trees.cpp b/example/two_graphs_common_spanning_trees.cpp index 5835aad5e..2fa851798 100644 --- a/example/two_graphs_common_spanning_trees.cpp +++ b/example/two_graphs_common_spanning_trees.cpp @@ -6,7 +6,7 @@ // Two Graphs Common Spanning Trees Algorithm // Based on academic article of Mint, Read and Tarjan // Efficient Algorithm for Common Spanning Tree Problem -// Electron. Lett., 28 April 1983, Volume 19, Issue 9, p.346–347 +// Electron. Lett., 28 April 1983, Volume 19, Issue 9, p.346-347 #include diff --git a/include/boost/graph/biconnected_components.hpp b/include/boost/graph/biconnected_components.hpp index efe96aeca..1669f6952 100644 --- a/include/boost/graph/biconnected_components.hpp +++ b/include/boost/graph/biconnected_components.hpp @@ -21,6 +21,7 @@ #include #include #include +#include namespace boost { @@ -127,8 +128,8 @@ namespace boost put(comp, S.top(), c); S.pop(); } - assert (source(S.top(), g) == parent); - assert (target(S.top(), g) == u); + BOOST_ASSERT (source(S.top(), g) == parent); + BOOST_ASSERT (target(S.top(), g) == u); put(comp, S.top(), c); S.pop(); ++c; @@ -177,7 +178,7 @@ namespace boost std::size_t children_of_root; std::size_t dfs_time = 0; std::stack S; - std::vector is_articulation_point(num_vertices(g)); + std::vector is_articulation_point(num_vertices(g)); biconnected_components_visitor, diff --git a/include/boost/graph/detail/histogram_sort.hpp b/include/boost/graph/detail/histogram_sort.hpp index e8fbadb83..ca6266a52 100644 --- a/include/boost/graph/detail/histogram_sort.hpp +++ b/include/boost/graph/detail/histogram_sort.hpp @@ -60,7 +60,7 @@ count_starts // Put the degree of each vertex v into m_rowstart[v + 1] for (KeyIterator i = begin; i != end; ++i) { if (key_filter(*i)) { - assert (key_transform(*i) < numkeys); + BOOST_ASSERT (key_transform(*i) < numkeys); ++starts[key_transform(*i) + 1]; } } @@ -100,7 +100,7 @@ histogram_sort(KeyIterator key_begin, KeyIterator key_end, for (KeyIterator i = key_begin; i != key_end; ++i, ++v1i) { if (key_filter(*i)) { vertices_size_type source = key_transform(*i); - assert (source < numkeys); + BOOST_ASSERT (source < numkeys); EdgeIndex insert_pos = current_insert_positions[source]; ++current_insert_positions[source]; values1_out[insert_pos] = *v1i; @@ -139,7 +139,7 @@ histogram_sort(KeyIterator key_begin, KeyIterator key_end, for (KeyIterator i = key_begin; i != key_end; ++i, ++v1i, ++v2i) { if (key_filter(*i)) { vertices_size_type source = key_transform(*i); - assert (source < numkeys); + BOOST_ASSERT (source < numkeys); EdgeIndex insert_pos = current_insert_positions[source]; ++current_insert_positions[source]; values1_out[insert_pos] = *v1i; @@ -166,7 +166,7 @@ histogram_sort_inplace(KeyIterator key_begin, std::vector insert_positions(rowstart, rowstart + numkeys); // 2. Swap the sources and targets into place for (size_t i = 0; i < rowstart[numkeys]; ++i) { - assert (key_transform(key_begin[i]) < numkeys); + BOOST_ASSERT (key_transform(key_begin[i]) < numkeys); // While edge i is not in the right bucket: while (!(i >= rowstart[key_transform(key_begin[i])] && i < insert_positions[key_transform(key_begin[i])])) { // Add a slot in the right bucket @@ -201,7 +201,7 @@ histogram_sort_inplace(KeyIterator key_begin, std::vector insert_positions(rowstart, rowstart + numkeys); // 2. Swap the sources and targets into place for (size_t i = 0; i < rowstart[numkeys]; ++i) { - assert (key_transform(key_begin[i]) < numkeys); + BOOST_ASSERT (key_transform(key_begin[i]) < numkeys); // While edge i is not in the right bucket: while (!(i >= rowstart[key_transform(key_begin[i])] && i < insert_positions[key_transform(key_begin[i])])) { // Add a slot in the right bucket diff --git a/include/boost/graph/two_graphs_common_spanning_trees.hpp b/include/boost/graph/two_graphs_common_spanning_trees.hpp index 2578b14ec..86d57ece0 100644 --- a/include/boost/graph/two_graphs_common_spanning_trees.hpp +++ b/include/boost/graph/two_graphs_common_spanning_trees.hpp @@ -6,7 +6,7 @@ // Two Graphs Common Spanning Trees Algorithm // Based on academic article of Mint, Read and Tarjan // Efficient Algorithm for Common Spanning Tree Problem -// Electron. Lett., 28 April 1983, Volume 19, Issue 9, p.346–347 +// Electron. Lett., 28 April 1983, Volume 19, Issue 9, p.346-347 #ifndef BOOST_GRAPH_TWO_GRAPHS_COMMON_SPANNING_TREES_HPP diff --git a/test/two_graphs_common_spanning_trees_test.cpp b/test/two_graphs_common_spanning_trees_test.cpp index e8cb3ad19..741845a39 100644 --- a/test/two_graphs_common_spanning_trees_test.cpp +++ b/test/two_graphs_common_spanning_trees_test.cpp @@ -6,7 +6,7 @@ // Two Graphs Common Spanning Trees Algorithm // Based on academic article of Mint, Read and Tarjan // Efficient Algorithm for Common Spanning Tree Problem -// Electron. Lett., 28 April 1983, Volume 19, Issue 9, p.346–347 +// Electron. Lett., 28 April 1983, Volume 19, Issue 9, p.346-347 #include From 8ff9b6c510255ca6dcf1c9bc8a29425549a6c426 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Fri, 18 May 2012 04:44:04 +0000 Subject: [PATCH 186/333] Replace all uses of boost/utility.hpp with more-granular includes. Solves modularization dependency nightmare. [SVN r78502] --- include/boost/graph/chrobak_payne_drawing.hpp | 1 - include/boost/graph/clustering_coefficient.hpp | 2 +- include/boost/graph/compressed_sparse_row_graph.hpp | 2 +- include/boost/graph/detail/compressed_sparse_row_struct.hpp | 1 - include/boost/graph/directed_graph.hpp | 1 - include/boost/graph/eccentricity.hpp | 2 +- include/boost/graph/is_kuratowski_subgraph.hpp | 1 - include/boost/graph/is_straight_line_drawing.hpp | 2 +- include/boost/graph/isomorphism.hpp | 1 - include/boost/graph/make_connected.hpp | 2 +- include/boost/graph/matrix_as_graph.hpp | 2 +- include/boost/graph/max_cardinality_matching.hpp | 1 - include/boost/graph/planar_canonical_ordering.hpp | 2 +- include/boost/graph/planar_detail/boyer_myrvold_impl.hpp | 2 +- include/boost/graph/planar_face_traversal.hpp | 5 ++++- include/boost/graph/undirected_graph.hpp | 1 - 16 files changed, 12 insertions(+), 16 deletions(-) diff --git a/include/boost/graph/chrobak_payne_drawing.hpp b/include/boost/graph/chrobak_payne_drawing.hpp index ef6ae5c9c..4d026986c 100644 --- a/include/boost/graph/chrobak_payne_drawing.hpp +++ b/include/boost/graph/chrobak_payne_drawing.hpp @@ -13,7 +13,6 @@ #include #include #include -#include //for next and prior #include #include diff --git a/include/boost/graph/clustering_coefficient.hpp b/include/boost/graph/clustering_coefficient.hpp index dad4695a7..5345ed999 100644 --- a/include/boost/graph/clustering_coefficient.hpp +++ b/include/boost/graph/clustering_coefficient.hpp @@ -7,7 +7,7 @@ #ifndef BOOST_GRAPH_CLUSTERING_COEFFICIENT_HPP #define BOOST_GRAPH_CLUSTERING_COEFFICIENT_HPP -#include +#include #include #include #include diff --git a/include/boost/graph/compressed_sparse_row_graph.hpp b/include/boost/graph/compressed_sparse_row_graph.hpp index d5b472b4c..50b2a335d 100644 --- a/include/boost/graph/compressed_sparse_row_graph.hpp +++ b/include/boost/graph/compressed_sparse_row_graph.hpp @@ -41,7 +41,7 @@ #include #include #include -#include +#include #include namespace boost { diff --git a/include/boost/graph/detail/compressed_sparse_row_struct.hpp b/include/boost/graph/detail/compressed_sparse_row_struct.hpp index 75ac96204..56495f343 100644 --- a/include/boost/graph/detail/compressed_sparse_row_struct.hpp +++ b/include/boost/graph/detail/compressed_sparse_row_struct.hpp @@ -44,7 +44,6 @@ #include #include #include -#include namespace boost { diff --git a/include/boost/graph/directed_graph.hpp b/include/boost/graph/directed_graph.hpp index a20539ff5..250d0b63d 100644 --- a/include/boost/graph/directed_graph.hpp +++ b/include/boost/graph/directed_graph.hpp @@ -7,7 +7,6 @@ #ifndef BOOST_GRAPH_DIRECTED_GRAPH_HPP #define BOOST_GRAPH_DIRECTED_GRAPH_HPP -#include #include #include diff --git a/include/boost/graph/eccentricity.hpp b/include/boost/graph/eccentricity.hpp index a8b3e4854..63797a830 100644 --- a/include/boost/graph/eccentricity.hpp +++ b/include/boost/graph/eccentricity.hpp @@ -7,7 +7,7 @@ #ifndef BOOST_GRAPH_ECCENTRICITY_HPP #define BOOST_GRAPH_ECCENTRICITY_HPP -#include +#include #include #include #include diff --git a/include/boost/graph/is_kuratowski_subgraph.hpp b/include/boost/graph/is_kuratowski_subgraph.hpp index 668043ab4..1dd314d31 100644 --- a/include/boost/graph/is_kuratowski_subgraph.hpp +++ b/include/boost/graph/is_kuratowski_subgraph.hpp @@ -9,7 +9,6 @@ #define __IS_KURATOWSKI_SUBGRAPH_HPP__ #include -#include //for next/prior #include //for tie #include #include diff --git a/include/boost/graph/is_straight_line_drawing.hpp b/include/boost/graph/is_straight_line_drawing.hpp index 161da4d12..c471cde8b 100644 --- a/include/boost/graph/is_straight_line_drawing.hpp +++ b/include/boost/graph/is_straight_line_drawing.hpp @@ -9,7 +9,7 @@ #define __IS_STRAIGHT_LINE_DRAWING_HPP__ #include -#include //for next and prior +#include #include #include #include diff --git a/include/boost/graph/isomorphism.hpp b/include/boost/graph/isomorphism.hpp index 995c91318..99055f35c 100644 --- a/include/boost/graph/isomorphism.hpp +++ b/include/boost/graph/isomorphism.hpp @@ -14,7 +14,6 @@ #include #include #include -#include #include #include // for make_indirect_pmap #include diff --git a/include/boost/graph/make_connected.hpp b/include/boost/graph/make_connected.hpp index de6c861dd..a2f8b1ee4 100644 --- a/include/boost/graph/make_connected.hpp +++ b/include/boost/graph/make_connected.hpp @@ -9,7 +9,7 @@ #define __MAKE_CONNECTED_HPP__ #include -#include //for next +#include #include //for tie #include #include diff --git a/include/boost/graph/matrix_as_graph.hpp b/include/boost/graph/matrix_as_graph.hpp index b39d126a2..fb727940d 100644 --- a/include/boost/graph/matrix_as_graph.hpp +++ b/include/boost/graph/matrix_as_graph.hpp @@ -14,7 +14,7 @@ #include #include #include -#include +#include #include namespace boost { diff --git a/include/boost/graph/max_cardinality_matching.hpp b/include/boost/graph/max_cardinality_matching.hpp index 043f70147..5516bebc4 100644 --- a/include/boost/graph/max_cardinality_matching.hpp +++ b/include/boost/graph/max_cardinality_matching.hpp @@ -16,7 +16,6 @@ #include // for std::sort and std::stable_sort #include // for std::pair #include -#include // for boost::tie #include #include #include diff --git a/include/boost/graph/planar_canonical_ordering.hpp b/include/boost/graph/planar_canonical_ordering.hpp index 6cb7bdb82..86203aaf3 100644 --- a/include/boost/graph/planar_canonical_ordering.hpp +++ b/include/boost/graph/planar_canonical_ordering.hpp @@ -12,7 +12,7 @@ #include #include #include -#include //for next and prior +#include #include #include diff --git a/include/boost/graph/planar_detail/boyer_myrvold_impl.hpp b/include/boost/graph/planar_detail/boyer_myrvold_impl.hpp index 71607fcbc..41ba2bc57 100644 --- a/include/boost/graph/planar_detail/boyer_myrvold_impl.hpp +++ b/include/boost/graph/planar_detail/boyer_myrvold_impl.hpp @@ -10,7 +10,7 @@ #include #include -#include //for boost::next +#include #include //for std::min macros #include #include diff --git a/include/boost/graph/planar_face_traversal.hpp b/include/boost/graph/planar_face_traversal.hpp index bcd565528..6befa43ba 100644 --- a/include/boost/graph/planar_face_traversal.hpp +++ b/include/boost/graph/planar_face_traversal.hpp @@ -10,8 +10,11 @@ #define __PLANAR_FACE_TRAVERSAL_HPP__ #include -#include //for next and prior +#include +#include +#include #include +#include namespace boost diff --git a/include/boost/graph/undirected_graph.hpp b/include/boost/graph/undirected_graph.hpp index b22fb9597..adcc86e51 100644 --- a/include/boost/graph/undirected_graph.hpp +++ b/include/boost/graph/undirected_graph.hpp @@ -7,7 +7,6 @@ #ifndef BOOST_GRAPH_UNDIRECTED_GRAPH_HPP #define BOOST_GRAPH_UNDIRECTED_GRAPH_HPP -#include #include #include From 38ad939f373300bc31a31a40c0dceb6a64939c9a Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Sat, 26 May 2012 19:30:47 +0000 Subject: [PATCH 187/333] Fixed warnings [SVN r78651] --- example/implicit_graph.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/example/implicit_graph.cpp b/example/implicit_graph.cpp index b93bc8b7d..4df80764e 100644 --- a/example/implicit_graph.cpp +++ b/example/implicit_graph.cpp @@ -460,7 +460,6 @@ int main (int argc, char const *argv[]) { // Create a small ring graph. ring_graph g(n); - const_edge_weight_map m = get(edge_weight, g); // Print the outgoing edges of all the vertices. For n=5 this will print: // From 30dd4d8f691411dc645f028b628f94634680d3c7 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Tue, 19 Jun 2012 19:14:46 +0000 Subject: [PATCH 188/333] Fixed property name as per #6993; fixes #6993 [SVN r79010] --- doc/bundles.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/bundles.html b/doc/bundles.html index 340b94830..4b789b0a5 100644 --- a/doc/bundles.html +++ b/doc/bundles.html @@ -93,7 +93,7 @@

      Example: Route planning

      boost::property<zipcodes_t, std::vector<int> > > >, // Edge properties boost::property<boost::edge_name_t, std::string, - boost::property<boost::edge_length_t, double, + boost::property<boost::edge_weight_t, double, boost::property<edge_speed_limit_t, int, boost::property<edge_lanes_t, int, boost::property<edge_divided, bool> > > > > > From 5cab2dcf6116eee02a53b28e87b1bd77f070dd32 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Wed, 20 Jun 2012 16:37:50 +0000 Subject: [PATCH 189/333] Changed grid_graph_index_map to use raw pointer to graph based on suggestion by Sergey Mitsyn [SVN r79017] --- include/boost/graph/grid_graph.hpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/include/boost/graph/grid_graph.hpp b/include/boost/graph/grid_graph.hpp index f63f3d01e..7bb373242 100644 --- a/include/boost/graph/grid_graph.hpp +++ b/include/boost/graph/grid_graph.hpp @@ -17,7 +17,6 @@ #include #include #include -#include #include #include #include @@ -63,14 +62,14 @@ namespace boost { grid_graph_index_map() { } grid_graph_index_map(const Graph& graph) : - m_graph(make_shared(graph)) { } + m_graph(&graph) { } value_type operator[](key_type key) const { return (m_graph->index_of(key)); } protected: - shared_ptr m_graph; + const Graph* m_graph; }; template From 215359117ae7b0e697ce4d6df21b4b944439d36d Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Fri, 29 Jun 2012 19:40:29 +0000 Subject: [PATCH 190/333] Applied patch from #7023; fixes #7023 [SVN r79177] --- src/graphml.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/graphml.cpp b/src/graphml.cpp index 3571b06fe..4a17fcaae 100644 --- a/src/graphml.cpp +++ b/src/graphml.cpp @@ -21,6 +21,8 @@ using namespace boost; +namespace { + class graphml_reader { public: @@ -202,6 +204,8 @@ class graphml_reader std::vector m_edge; }; +} + namespace boost { void BOOST_GRAPH_DECL From 849d1538ed46ad94cd53d23b65ced413be48084e Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Fri, 29 Jun 2012 20:26:26 +0000 Subject: [PATCH 191/333] Fixed construction and assignment of bidirectional CSR graphs from other graphs; removed add_edges* functions (which were broken and not documented) from bidirectional CSR; fixes #7002 [SVN r79179] --- .../graph/compressed_sparse_row_graph.hpp | 122 +----------------- 1 file changed, 3 insertions(+), 119 deletions(-) diff --git a/include/boost/graph/compressed_sparse_row_graph.hpp b/include/boost/graph/compressed_sparse_row_graph.hpp index 50b2a335d..1a1cd674e 100644 --- a/include/boost/graph/compressed_sparse_row_graph.hpp +++ b/include/boost/graph/compressed_sparse_row_graph.hpp @@ -929,6 +929,7 @@ class compressed_sparse_row_graph - void - add_edges_sorted_internal( - BidirectionalIteratorOrig first_sorted, - BidirectionalIteratorOrig last_sorted, - EPIterOrig ep_iter_sorted, - const GlobalToLocal& global_to_local) { - m_forward.add_edges_sorted_internal(first_sorted, last_sorted, ep_iter_sorted, global_to_local); - } - - template - void - add_edges_sorted_internal( - BidirectionalIteratorOrig first_sorted, - BidirectionalIteratorOrig last_sorted, - EPIterOrig ep_iter_sorted) { - m_forward.add_edges_sorted_internal(first_sorted, last_sorted, ep_iter_sorted, typed_identity_property_map()); - } - - // Add edges from a sorted (smallest sources first) range of pairs - template - void - add_edges_sorted_internal( - BidirectionalIteratorOrig first_sorted, - BidirectionalIteratorOrig last_sorted) { - m_forward.add_edges_sorted_internal(first_sorted, last_sorted, detail::default_construct_iterator()); - } - - template - void - add_edges_sorted_internal_global( - BidirectionalIteratorOrig first_sorted, - BidirectionalIteratorOrig last_sorted, - const GlobalToLocal& global_to_local) { - m_forward.add_edges_sorted_internal(first_sorted, last_sorted, detail::default_construct_iterator(), global_to_local); - } - - template - void - add_edges_sorted_internal_global( - BidirectionalIteratorOrig first_sorted, - BidirectionalIteratorOrig last_sorted, - EPIterOrig ep_iter_sorted, - const GlobalToLocal& global_to_local) { - m_forward.add_edges_sorted_internal(first_sorted, last_sorted, ep_iter_sorted, global_to_local); - } - - // Add edges from a range of (source, target) pairs that are unsorted - template - inline void - add_edges_internal(InputIterator first, InputIterator last, - const GlobalToLocal& global_to_local) { - typedef compressed_sparse_row_graph Graph; - typedef typename boost::graph_traits::vertex_descriptor vertex_t; - typedef typename boost::graph_traits::vertices_size_type vertex_num; - typedef typename boost::graph_traits::edges_size_type edge_num; - typedef std::vector > edge_vector_t; - edge_vector_t new_edges(first, last); - if (new_edges.empty()) return; - std::sort(new_edges.begin(), new_edges.end()); - this->add_edges_sorted_internal_global(new_edges.begin(), new_edges.end(), global_to_local); - } - - template - inline void - add_edges_internal(InputIterator first, InputIterator last) { - this->add_edges_internal(first, last, typed_identity_property_map()); - } - - // Add edges from a range of (source, target) pairs and edge properties that - // are unsorted - template - inline void - add_edges_internal(InputIterator first, InputIterator last, - EPIterator ep_iter, EPIterator ep_iter_end, - const GlobalToLocal& global_to_local) { - typedef compressed_sparse_row_graph Graph; - typedef typename boost::graph_traits::vertex_descriptor vertex_t; - typedef typename boost::graph_traits::vertices_size_type vertex_num; - typedef typename boost::graph_traits::edges_size_type edge_num; - typedef std::pair vertex_pair; - typedef std::vector< - boost::tuple > - edge_vector_t; - edge_vector_t new_edges - (boost::make_zip_iterator(boost::make_tuple(first, ep_iter)), - boost::make_zip_iterator(boost::make_tuple(last, ep_iter_end))); - if (new_edges.empty()) return; - std::sort(new_edges.begin(), new_edges.end(), - boost::detail::compare_first< - std::less >()); - m_forward.add_edges_sorted_internal - (boost::make_transform_iterator( - new_edges.begin(), - boost::detail::my_tuple_get_class<0, vertex_pair>()), - boost::make_transform_iterator( - new_edges.end(), - boost::detail::my_tuple_get_class<0, vertex_pair>()), - boost::make_transform_iterator( - new_edges.begin(), - boost::detail::my_tuple_get_class - <1, edge_bundled>()), - global_to_local); - } - - // Add edges from a range of (source, target) pairs and edge properties that - // are unsorted - template - inline void - add_edges_internal(InputIterator first, InputIterator last, - EPIterator ep_iter, EPIterator ep_iter_end) { - this->add_edges_internal(first, last, ep_iter, ep_iter_end, typed_identity_property_map()); + set_up_backward_property_links(); } using inherited_vertex_properties::operator[]; From 71f0ab997d30095b6af079c23f96622551cd8bd7 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Mon, 2 Jul 2012 12:53:15 +0000 Subject: [PATCH 192/333] Added default for property_kind to try to work around VC++ issues [SVN r79227] --- include/boost/pending/property.hpp | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/include/boost/pending/property.hpp b/include/boost/pending/property.hpp index 93b3cd84d..93ebffbf3 100644 --- a/include/boost/pending/property.hpp +++ b/include/boost/pending/property.hpp @@ -8,6 +8,7 @@ #include #include +#include #include #include @@ -29,10 +30,19 @@ namespace boost { }; // Kinds of properties + namespace graph_introspect_detail { + BOOST_MPL_HAS_XXX_TRAIT_DEF(kind) + template struct get_kind {typedef void type;}; + template struct get_kind {typedef typename T::kind type;}; + } + + // Having a default is to make this trait work for any type, not just valid + // properties, to work around VC++ <= 10 bugs related to SFINAE in + // compressed_sparse_row_graph's get functions and similar template - struct property_kind { - typedef typename PropertyTag::kind type; - }; + struct property_kind: + graph_introspect_detail::get_kind::value> + {}; // Some standard properties defined independently of Boost.Graph: enum vertex_all_t {vertex_all}; From 20ab0ffec3631a603d0dc8be54593989c1983899 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Mon, 9 Jul 2012 19:48:12 +0000 Subject: [PATCH 193/333] Fixed VC++ issues in examples [SVN r79387] --- example/astar_maze.cpp | 2 +- example/implicit_graph.cpp | 8 +++++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/example/astar_maze.cpp b/example/astar_maze.cpp index 840bce541..fad2c208f 100644 --- a/example/astar_maze.cpp +++ b/example/astar_maze.cpp @@ -139,7 +139,7 @@ class euclidean_heuristic: euclidean_heuristic(vertex_descriptor goal):m_goal(goal) {}; double operator()(vertex_descriptor v) { - return sqrt(pow(m_goal[0] - v[0], 2) + pow(m_goal[1] - v[1], 2)); + return sqrt(pow(double(m_goal[0] - v[0]), 2) + pow(double(m_goal[1] - v[1]), 2)); } private: diff --git a/example/implicit_graph.cpp b/example/implicit_graph.cpp index 4df80764e..5461d3dca 100644 --- a/example/implicit_graph.cpp +++ b/example/implicit_graph.cpp @@ -95,6 +95,12 @@ namespace boost { typedef edge_weight_map type; typedef edge_weight_map const_type; }; + + template<> + struct property_map< const ring_graph, edge_weight_t > { + typedef edge_weight_map type; + typedef edge_weight_map const_type; + }; } // Tag values that specify the traversal type in graph::traversal_category. @@ -374,7 +380,7 @@ edges_size_type num_edges(const ring_graph& g) { // AdjacencyMatrix valid expressions std::pair edge(vertex_descriptor u, vertex_descriptor v, const ring_graph& g) { - if (abs(u-v) == 1 && + if ((u == v + 1 || v == u + 1) && u >= 0 && u < num_vertices(g) && v >= 0 && v < num_vertices(g)) return std::pair(edge_descriptor(u, v), true); else From 408469afcf303a4136222f0dbffc649dc5567af0 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Mon, 9 Jul 2012 19:49:55 +0000 Subject: [PATCH 194/333] Refactored handling of properties (especially bogus property tags) to work around VC++ <=10 issues in graphviz_test; changed graph_all_t to return ref_property_map like is needed for dynamic_properties in I/O functions [SVN r79388] --- .../graph/compressed_sparse_row_graph.hpp | 105 +++++++++++++++--- 1 file changed, 92 insertions(+), 13 deletions(-) diff --git a/include/boost/graph/compressed_sparse_row_graph.hpp b/include/boost/graph/compressed_sparse_row_graph.hpp index 1a1cd674e..59e8bb4ab 100644 --- a/include/boost/graph/compressed_sparse_row_graph.hpp +++ b/include/boost/graph/compressed_sparse_row_graph.hpp @@ -43,6 +43,7 @@ #include #include #include +#include namespace boost { @@ -1284,22 +1285,51 @@ get_property(const BOOST_CSR_GRAPH_TYPE& g, Tag tag) return get_property_value(g.m_property, tag); } +template +struct csr_property_map_helper {}; +// Kind == void for invalid property tags, so we can use that to SFINAE out + +template +struct csr_property_map_helper { + typedef vertex_all_t all_tag; + typedef typename property_traits::type>::key_type key_type; + typedef VertexProperty plist_type; + typedef typename property_map::type all_type; + typedef typename property_map::const_type all_const_type; + typedef transform_value_property_map, all_type> type; + typedef transform_value_property_map, all_const_type> const_type; +}; + +template +struct csr_property_map_helper { + typedef edge_all_t all_tag; + typedef typename property_traits::type>::key_type key_type; + typedef EdgeProperty plist_type; + typedef typename property_map::type all_type; + typedef typename property_map::const_type all_const_type; + typedef transform_value_property_map, all_type> type; + typedef transform_value_property_map, all_const_type> const_type; +}; + template -struct property_map { - typedef typename detail::property_kind_from_graph::type kind; - typedef typename boost::mpl::if_< - boost::is_same, - vertex_all_t, - typename boost::mpl::if_< - boost::is_same, - edge_all_t, - graph_all_t>::type>::type all_tag; - typedef typename property_traits::type>::key_type key_type; - typedef typename property_traits::type>::value_type plist_type; - typedef transform_value_property_map, typename property_map::type> type; - typedef transform_value_property_map, typename property_map::const_type> const_type; +struct csr_property_map_helper { + typedef graph_all_t all_tag; + typedef BOOST_CSR_GRAPH_TYPE* key_type; + typedef GraphProperty plist_type; + typedef typename property_map::type all_type; + typedef typename property_map::const_type all_const_type; + typedef transform_value_property_map, all_type> type; + typedef transform_value_property_map, all_const_type> const_type; }; +template +struct property_map: + csr_property_map_helper< + BOOST_CSR_GRAPH_TYPE, + Tag, + typename detail::property_kind_from_graph + ::type> {}; + template typename property_map::type get(Tag tag, BOOST_CSR_GRAPH_TYPE& g) { @@ -1367,6 +1397,13 @@ struct property_map typedef typename BOOST_CSR_GRAPH_TYPE::forward_type::inherited_edge_properties::const_edge_map_type const_type; }; +template +struct property_map +{ + typedef boost::ref_property_map type; + typedef boost::ref_property_map const_type; +}; + template inline typed_identity_property_map get(vertex_index_t, const BOOST_CSR_GRAPH_TYPE&) @@ -1513,6 +1550,48 @@ put(edge_all_t, put(get(edge_all, g), e, val); } +template +inline typename property_map::type +get(graph_all_t, BOOST_CSR_GRAPH_TYPE& g) +{ + return typename property_map::type(g.m_property); +} + +template +inline typename property_map::const_type +get(graph_all_t, const BOOST_CSR_GRAPH_TYPE& g) +{ + return typename property_map::const_type(g.m_property); +} + +template +inline GraphProperty& +get(graph_all_t, + BOOST_CSR_GRAPH_TYPE& g, + BOOST_CSR_GRAPH_TYPE*) +{ + return g.m_property; +} + +template +inline const GraphProperty& +get(graph_all_t, + const BOOST_CSR_GRAPH_TYPE& g, + BOOST_CSR_GRAPH_TYPE*) +{ + return g.m_property; +} + +template +inline void +put(graph_all_t, + BOOST_CSR_GRAPH_TYPE& g, + BOOST_CSR_GRAPH_TYPE*, + const GraphProperty& val) +{ + g.m_property = val; +} + #undef BOOST_CSR_GRAPH_TYPE #undef BOOST_CSR_GRAPH_TEMPLATE_PARMS #undef BOOST_DIR_CSR_GRAPH_TYPE From df808764752b626a18aba1f5221c284e5f168c55 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Mon, 9 Jul 2012 20:10:02 +0000 Subject: [PATCH 195/333] Fixed uninitialized variable problem [SVN r79391] --- test/cycle_ratio_tests.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/cycle_ratio_tests.cpp b/test/cycle_ratio_tests.cpp index f7ca69218..ac5f208f3 100644 --- a/test/cycle_ratio_tests.cpp +++ b/test/cycle_ratio_tests.cpp @@ -224,7 +224,7 @@ int test_main(int argc, char* argv[]) diGraphInt tg; property_map::type vim = get(vertex_index, tg); property_map::type ew1m = get(edge_weight, tg); - property_map::type ew2m = ew2m; + property_map::type ew2m = get(edge_weight2, tg); From ff872bad11498d230618fd4d0251c27201a16668 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Wed, 1 Aug 2012 15:31:23 +0000 Subject: [PATCH 196/333] Fixed subgraph_properties example and added more examples to Jamfile.v2 [SVN r79833] --- example/Jamfile.v2 | 2 ++ example/subgraph_properties.cpp | 22 +++++++++++----------- 2 files changed, 13 insertions(+), 11 deletions(-) diff --git a/example/Jamfile.v2 b/example/Jamfile.v2 index 2ab225009..5d4dc7f02 100644 --- a/example/Jamfile.v2 +++ b/example/Jamfile.v2 @@ -41,3 +41,5 @@ exe undirected_graph : undirected_graph.cpp ; exe two_graphs_common_spanning_trees : two_graphs_common_spanning_trees.cpp ; exe strong_components : strong_components.cpp ../build//boost_graph ; exe strong-components : strong-components.cpp ; +exe subgraph : subgraph.cpp ; +exe subgraph_properties : subgraph_properties.cpp ; diff --git a/example/subgraph_properties.cpp b/example/subgraph_properties.cpp index 7de21cec9..613d53a3c 100644 --- a/example/subgraph_properties.cpp +++ b/example/subgraph_properties.cpp @@ -69,20 +69,20 @@ int main(int,char*[]) std::cout << std::endl << "After initializing properties for G1:" << std::endl; std::cout << " Global and local properties for vertex G0[C]..." << std::endl; - std::cout << " G0[C]= " << boost::get(vertex_name, G0, C) << std::endl;// prints: "G0[C]= C" - std::cout << " G1[A1]= " << boost::get(vertex_name, G1, A1) << std::endl;// prints: "G1[A1]= A1" + std::cout << " G0[C]= " << boost::get(vertex_name, G0, vertex(C, G0)) << std::endl;// prints: "G0[C]= C" + std::cout << " G1[A1]= " << boost::get(vertex_name, G1, vertex(A1, G1)) << std::endl;// prints: "G1[A1]= A1" name1[B1] = "B1"; std::cout << " Global and local properties for vertex G0[E]..." << std::endl; - std::cout << " G0[E]= " << boost::get(vertex_name, G0, E) << std::endl;// prints: "G0[E]= E" - std::cout << " G1[B1]= " << boost::get(vertex_name, G1, B1) << std::endl;// prints: "G1[B1]= B1" + std::cout << " G0[E]= " << boost::get(vertex_name, G0, vertex(E, G0)) << std::endl;// prints: "G0[E]= E" + std::cout << " G1[B1]= " << boost::get(vertex_name, G1, vertex(B1, G1)) << std::endl;// prints: "G1[B1]= B1" name1[C1] = "C1"; std::cout << " Global and local properties for vertex G0[F]..." << std::endl; - std::cout << " G0[F]= " << boost::get(vertex_name, G0, F) << std::endl;// prints: "G0[F]= F" - std::cout << " G1[C1]= " << boost::get(vertex_name, G1, C1) << std::endl;// prints: "G1[C1]= C1" + std::cout << " G0[F]= " << boost::get(vertex_name, G0, vertex(F, G0)) << std::endl;// prints: "G0[F]= F" + std::cout << " G1[C1]= " << boost::get(vertex_name, G1, vertex(C1, G1)) << std::endl;// prints: "G1[C1]= C1" Graph& G2 = G0.create_subgraph(); enum { A2, B2 }; // for conveniently refering to vertices in G2 @@ -95,15 +95,15 @@ int main(int,char*[]) std::cout << std::endl << std::endl << "After initializing properties for G2:" << std::endl; std::cout << " Global and local properties for vertex G0[A]" << std::endl; - std::cout << " G0[A]= " << boost::get(vertex_name, G0, A) << std::endl;// prints: "G0[A]= A" - std::cout << " G2[A2]= " << boost::get(vertex_name, G2, A2) << std::endl;// prints: "G2[A2]= A2" + std::cout << " G0[A]= " << boost::get(vertex_name, G0, vertex(A, G0)) << std::endl;// prints: "G0[A]= A" + std::cout << " G2[A2]= " << boost::get(vertex_name, G2, vertex(A2, G2)) << std::endl;// prints: "G2[A2]= A2" name2[B2] = "B2"; std::cout << " Global and local properties for vertex G0[C]..." << std::endl; - std::cout << " G0[C]= " << boost::get(vertex_name, G0, C) << std::endl;// prints: "G0[C]= C" - std::cout << " G1[A1]= " << boost::get(vertex_name, G1, A1) << std::endl;// prints: "G1[A1]= A1" - std::cout << " G2[B2]= " << boost::get(vertex_name, G2, B2) << std::endl;// prints: "G2[B2]= B2" + std::cout << " G0[C]= " << boost::get(vertex_name, G0, vertex(C, G0)) << std::endl;// prints: "G0[C]= C" + std::cout << " G1[A1]= " << boost::get(vertex_name, G1, vertex(A1, G1)) << std::endl;// prints: "G1[A1]= A1" + std::cout << " G2[B2]= " << boost::get(vertex_name, G2, vertex(B2, G2)) << std::endl;// prints: "G2[B2]= B2" return 0; } From 48f4d92a385d388a394dc6d6b57b5e3d60c15829 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Thu, 2 Aug 2012 18:05:11 +0000 Subject: [PATCH 197/333] Removed retag_property_list and all uses of it [SVN r79855] --- include/boost/graph/undirected_graph.hpp | 5 --- include/boost/pending/property.hpp | 52 ------------------------ 2 files changed, 57 deletions(-) diff --git a/include/boost/graph/undirected_graph.hpp b/include/boost/graph/undirected_graph.hpp index adcc86e51..738a5c950 100644 --- a/include/boost/graph/undirected_graph.hpp +++ b/include/boost/graph/undirected_graph.hpp @@ -10,11 +10,6 @@ #include #include -// NOTE: The retag_property_list is used to "normalize" a proeprty such that -// any non-property conforming parameter is wrapped in a vertex_bundle -// property. For example (with bad syntax) retag> -> property, -// but retag -> property. - namespace boost { struct undirected_graph_tag { }; diff --git a/include/boost/pending/property.hpp b/include/boost/pending/property.hpp index 93ebffbf3..727478f7c 100644 --- a/include/boost/pending/property.hpp +++ b/include/boost/pending/property.hpp @@ -199,58 +199,6 @@ namespace boost { : mpl::bool_::value> { }; - /** @internal @name Retag Property List - * This metafunction is used internally to normalize a property if it is - * actually modeling a property. Specifically this is used in Boost.Graph - * to map user-provided classes into bundled properties. - */ - //@{ - // One base case of the recursive form (see below). This matches any - // retag request that does not include a property<...> or no_property as - // the FinalType. This is used for generating bundles in Boost.Graph. - template - struct retag_property_list - { - typedef property type; - typedef FinalType retagged; - }; - - // Recursively retag the nested property list. - template - struct retag_property_list > - { - private: - typedef retag_property_list next; - - public: - typedef property type; - typedef typename next::retagged retagged; - }; - - // This base case will correctly deduce the final property type if the - // retagged property is given in property form. This should not hide - // the base case below. - // NOTE: This addresses a problem of layering bundled properties in the BGL - // where multiple retaggings will fail to deduce the correct retagged - // type. - template - struct retag_property_list > - { - public: - typedef property type; - typedef FinalType retagged; - }; - - // A final base case of the retag_property_list, this will terminate a - // properly structured list. - template - struct retag_property_list - { - typedef no_property type; - typedef no_property retagged; - }; - //@} - template class lookup_one_property_f; From 6dc5eb1d6a052837730bb892b7c38367a787307b Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Sat, 25 Aug 2012 03:09:27 +0000 Subject: [PATCH 198/333] Fixed typo [SVN r80188] --- doc/sorted_erdos_renyi_gen.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/sorted_erdos_renyi_gen.html b/doc/sorted_erdos_renyi_gen.html index 55273fa23..8f01e1ce9 100644 --- a/doc/sorted_erdos_renyi_gen.html +++ b/doc/sorted_erdos_renyi_gen.html @@ -63,7 +63,7 @@ href="adjacency_list.html">adjacency_list or other graph structure with iterator-based initialization. An Erdös-Renyi graph G = (n, p) is a graph with n vertices -that. The probability of having an edge (u, v) in G +such that the probability of having an edge (u, v) in G is p for any vertices u and v. Typically, there are no self-loops, but the generator can optionally introduce self-loops with probability p.

      From 4672f4d4306836e3e7392b83eb2ad53e9069165c Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Sat, 25 Aug 2012 03:10:40 +0000 Subject: [PATCH 199/333] Fixed typo [SVN r80189] --- doc/sorted_erdos_renyi_gen.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/sorted_erdos_renyi_gen.html b/doc/sorted_erdos_renyi_gen.html index 8f01e1ce9..b61242a5a 100644 --- a/doc/sorted_erdos_renyi_gen.html +++ b/doc/sorted_erdos_renyi_gen.html @@ -93,7 +93,7 @@

      Constructors

      Constructs an Erdös-Renyi generator iterator that creates a graph with n vertices and a given probability of the total number of edges that a simple graph may have. -probability. Random vertices and edges are selected using the +Random vertices and edges are selected using the random number generator gen. Self-loops are permitted only when allow_self_loops is true. From 88101e0ab0ff419d4ba435adbff12073229f3a47 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Sat, 25 Aug 2012 20:45:29 +0000 Subject: [PATCH 200/333] Fixed default template arguments [SVN r80216] --- doc/compressed_sparse_row.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/compressed_sparse_row.html b/doc/compressed_sparse_row.html index 8850822de..976e76b90 100644 --- a/doc/compressed_sparse_row.html +++ b/doc/compressed_sparse_row.html @@ -101,8 +101,8 @@

      Compressed Sparse Row Graph

       namespace boost {
       
      -template<typename Directed = directedS, typename VertexProperty = void, 
      -         typename EdgeProperty = void, typename GraphProperty = no_property, 
      +template<typename Directed = directedS, typename VertexProperty = no_property, 
      +         typename EdgeProperty = no_property, typename GraphProperty = no_property, 
                typename Vertex = std::size_t, typename EdgeIndex = Vertex>
       class compressed_sparse_row_graph
       {
      
      From d2d880b4e07bd5cc67e6ffb61a4e7389162e51d0 Mon Sep 17 00:00:00 2001
      From: Jeremiah Willcock 
      Date: Mon, 27 Aug 2012 19:05:25 +0000
      Subject: [PATCH 201/333] =?UTF-8?q?Made=20edge=20weight=20a=20reference=20?=
       =?UTF-8?q?based=20on=20a=20suggestion=20by=20Tristram=20Gr=C3=A4bener;=20?=
       =?UTF-8?q?made=20vertex=20distance=20variables=20const=20values?=
      MIME-Version: 1.0
      Content-Type: text/plain; charset=UTF-8
      Content-Transfer-Encoding: 8bit
      
      [SVN r80264]
      ---
       include/boost/graph/relax.hpp | 5 +++--
       1 file changed, 3 insertions(+), 2 deletions(-)
      
      diff --git a/include/boost/graph/relax.hpp b/include/boost/graph/relax.hpp
      index 468579609..9c0d0260c 100644
      --- a/include/boost/graph/relax.hpp
      +++ b/include/boost/graph/relax.hpp
      @@ -49,8 +49,9 @@ namespace boost {
             Vertex u = source(e, g), v = target(e, g);
             typedef typename property_traits::value_type D;
             typedef typename property_traits::value_type W;
      -      D d_u = get(d, u), d_v = get(d, v);
      -      W w_e = get(w, e);
      +      const D d_u = get(d, u);
      +      const D d_v = get(d, v);
      +      const W& w_e = get(w, e);
             
             // The redundant gets in the return statements are to ensure that extra
             // floating-point precision in x87 registers does not lead to relax()
      
      From 9dcbb861d69b7cf9a43ed88b96a95c791c840e95 Mon Sep 17 00:00:00 2001
      From: Jeremiah Willcock 
      Date: Wed, 5 Sep 2012 15:19:59 +0000
      Subject: [PATCH 202/333] Added warning about copying
      
      [SVN r80407]
      ---
       include/boost/graph/detail/d_ary_heap.hpp | 5 +++++
       1 file changed, 5 insertions(+)
      
      diff --git a/include/boost/graph/detail/d_ary_heap.hpp b/include/boost/graph/detail/d_ary_heap.hpp
      index ba58647a3..2d9219266 100644
      --- a/include/boost/graph/detail/d_ary_heap.hpp
      +++ b/include/boost/graph/detail/d_ary_heap.hpp
      @@ -20,6 +20,11 @@
       #include 
       #include 
       
      +// WARNING: it is not safe to copy a d_ary_heap_indirect and then modify one of
      +// the copies.  The class is required to be copyable so it can be passed around
      +// (without move support from C++11), but it deep-copies the heap contents yet
      +// shallow-copies the index_in_heap_map.
      +
       namespace boost {
       
         // Swap two elements in a property map without assuming they model
      
      From b52e49730ba27d3ee7e7da09a72adec8a4a5d668 Mon Sep 17 00:00:00 2001
      From: Jeremiah Willcock 
      Date: Thu, 6 Sep 2012 13:44:21 +0000
      Subject: [PATCH 203/333] Fixed issues with indirect_cmp; fixes #7338
      
      [SVN r80420]
      ---
       include/boost/pending/indirect_cmp.hpp | 5 +++--
       1 file changed, 3 insertions(+), 2 deletions(-)
      
      diff --git a/include/boost/pending/indirect_cmp.hpp b/include/boost/pending/indirect_cmp.hpp
      index 638625cec..14ee5314a 100644
      --- a/include/boost/pending/indirect_cmp.hpp
      +++ b/include/boost/pending/indirect_cmp.hpp
      @@ -33,14 +33,15 @@ namespace boost {
           typedef typename boost::property_traits::key_type K;
           typedef K first_argument_type;
           typedef K second_argument_type;
      -    typedef T result_type;
      +    typedef bool result_type;
           inline indirect_cmp(const ReadablePropertyMap& df, const Compare& c = Compare())
             : d(df), cmp(c) { }
       
           template 
           inline bool 
           operator()(const A& u, const B& v) const {
      -      T du = get(d, u), dv = get(d, v);
      +      const T& du = get(d, u);
      +      const T& dv = get(d, v);
             return cmp(du, dv);
           }
         protected:
      
      From fecccdd81c3e046dde5344e6aa0ce1f85209851d Mon Sep 17 00:00:00 2001
      From: Jeremiah Willcock 
      Date: Thu, 6 Sep 2012 15:31:41 +0000
      Subject: [PATCH 204/333] Changed core_numbers to use d_ary_heap and only
       update queue elements that are in the queue; fixes #7341
      
      [SVN r80421]
      ---
       include/boost/graph/core_numbers.hpp | 17 +++++++++--------
       1 file changed, 9 insertions(+), 8 deletions(-)
      
      diff --git a/include/boost/graph/core_numbers.hpp b/include/boost/graph/core_numbers.hpp
      index 3db59c72b..33764c4f4 100644
      --- a/include/boost/graph/core_numbers.hpp
      +++ b/include/boost/graph/core_numbers.hpp
      @@ -11,8 +11,7 @@
       #ifndef BOOST_GRAPH_CORE_NUMBERS_HPP
       #define BOOST_GRAPH_CORE_NUMBERS_HPP
       
      -#include 
      -#include 
      +#include 
       #include 
       #include 
       #include 
      @@ -159,7 +158,8 @@ namespace boost {
                           if (get(c,u) > v_cn) {
                               // remove the edge
                               put(c,u,get(c,u)-get(wm,*oi));
      -                        Q.update(u);
      +                        if (Q.contains(u))
      +                          Q.update(u);
                           }
                       }
                       vis.finish_vertex(v,g);
      @@ -175,13 +175,14 @@ namespace boost {
               {
                   typedef typename property_traits::value_type D;
                   typedef std::less Cmp;
      -            typedef indirect_cmp IndirectCmp;
      -            IndirectCmp icmp(c, Cmp());
                   // build the mutable queue
                   typedef typename graph_traits::vertex_descriptor vertex;
      -            typedef mutable_queue, IndirectCmp,
      -                IndexMap> MutableQueue;
      -            MutableQueue Q(num_vertices(g), icmp, im);
      +            std::vector index_in_heap_data(num_vertices(g));
      +            typedef iterator_property_map::iterator, IndexMap>
      +              index_in_heap_map_type;
      +            index_in_heap_map_type index_in_heap_map(index_in_heap_data.begin(), im);
      +            typedef d_ary_heap_indirect MutableQueue;
      +            MutableQueue Q(c, index_in_heap_map, Cmp());
                   typename graph_traits::vertex_iterator vi,vi_end;
                   for (boost::tie(vi,vi_end) = vertices(g); vi!=vi_end; ++vi) {
                       Q.push(*vi);
      
      From 58ff2364baefaf345296cc601cb84dbed296787c Mon Sep 17 00:00:00 2001
      From: Jeremiah Willcock 
      Date: Tue, 11 Sep 2012 07:04:18 +0000
      Subject: [PATCH 205/333] Fixed typos
      
      [SVN r80490]
      ---
       doc/gursoy_atun_layout.html | 9 ++++-----
       1 file changed, 4 insertions(+), 5 deletions(-)
      
      diff --git a/doc/gursoy_atun_layout.html b/doc/gursoy_atun_layout.html
      index 52482a36a..db61443e8 100644
      --- a/doc/gursoy_atun_layout.html
      +++ b/doc/gursoy_atun_layout.html
      @@ -161,7 +161,8 @@ 

      Parameters

      IN: VertexIndexMap vertex_index_map
      This maps each vertex to an integer in the range [0, - num_vertices(g)). + num_vertices(g)). This is only necessary when no + displacement map is provided. The type VertexIndexMap must be a model of Readable Property Map. The value type of the map must be an integer type. The @@ -176,9 +177,7 @@

      Parameters

      IN: EdgeWeightMap weight
      - This maps each edge to an weight. - num_vertices(g)). This is only necessary when no - displacement map is provided. + This maps each edge to a weight. The type EdgeWeightMap must be a model of Readable Property Map. The value type of the map must be an floating-point type @@ -221,7 +220,7 @@

      Named Parameters

      Default: get(vertex_index, g) Note: if you use this default, make sure your graph has an internal vertex_index property. For example, - adjacenty_list with VertexList=listS does + adjacency_list with VertexList=listS does not have an internal vertex_index property.
      From 60b5e07027a6c1b60eea598d99d7965258e3ad8b Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Wed, 12 Sep 2012 12:24:04 +0000 Subject: [PATCH 206/333] Allowed pointers-to-base-members to be used to access properties of derived bundled property classes; fixes #7308 [SVN r80505] --- include/boost/graph/properties.hpp | 8 ++++---- include/boost/pending/property.hpp | 11 ++++++----- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/include/boost/graph/properties.hpp b/include/boost/graph/properties.hpp index 6b5ade974..5cc926bc0 100644 --- a/include/boost/graph/properties.hpp +++ b/include/boost/graph/properties.hpp @@ -21,7 +21,7 @@ #include #include -#include +#include #include #include #include @@ -149,13 +149,13 @@ namespace boost { template struct property_kind_from_graph { typedef typename boost::mpl::if_< - boost::is_same::type>, + boost::is_base_of::type>, vertex_property_tag, typename boost::mpl::if_< - boost::is_same::type>, + boost::is_base_of::type>, edge_property_tag, typename boost::mpl::if_< - boost::is_same::type>, + boost::is_base_of::type>, graph_property_tag, void>::type>::type>::type type; }; diff --git a/include/boost/pending/property.hpp b/include/boost/pending/property.hpp index 727478f7c..bf504185c 100644 --- a/include/boost/pending/property.hpp +++ b/include/boost/pending/property.hpp @@ -11,6 +11,7 @@ #include #include #include +#include namespace boost { @@ -53,7 +54,7 @@ namespace boost { enum graph_bundle_t {graph_bundle}; // Code to look up one property in a property list: - template + template struct lookup_one_property_internal {BOOST_STATIC_CONSTANT(bool, found = false);}; // Special-case properties (vertex_all, edge_all, graph_all) @@ -135,12 +136,12 @@ namespace boost { // Pointer-to-member access to bundled properties #ifndef BOOST_GRAPH_NO_BUNDLED_PROPERTIES - template - struct lookup_one_property_internal { + template + struct lookup_one_property_internal >::type> { BOOST_STATIC_CONSTANT(bool, found = true); typedef R type; - static R& lookup(T& x, R T::*ptr) {return x.*ptr;} - static const R& lookup(const T& x, R T::*ptr) {return x.*ptr;} + static R& lookup(T& x, R TMaybeBase::*ptr) {return x.*ptr;} + static const R& lookup(const T& x, R TMaybeBase::*ptr) {return x.*ptr;} }; #endif From 8c83132ef7552fa84df0dde2aea31f023abd71ab Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Thu, 13 Sep 2012 13:18:36 +0000 Subject: [PATCH 207/333] Applied patch from #7327; fixes #7327 [SVN r80511] --- include/boost/graph/filtered_graph.hpp | 2 +- include/boost/graph/labeled_graph.hpp | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/include/boost/graph/filtered_graph.hpp b/include/boost/graph/filtered_graph.hpp index 66cead609..6ac82927e 100644 --- a/include/boost/graph/filtered_graph.hpp +++ b/include/boost/graph/filtered_graph.hpp @@ -210,7 +210,7 @@ namespace boost { static vertex_descriptor null_vertex() { - return Graph::null_vertex(); + return Traits::null_vertex(); } //private: diff --git a/include/boost/graph/labeled_graph.hpp b/include/boost/graph/labeled_graph.hpp index e1a2f7c2d..67505d250 100644 --- a/include/boost/graph/labeled_graph.hpp +++ b/include/boost/graph/labeled_graph.hpp @@ -196,7 +196,7 @@ namespace graph_detail { { // If the element is already occupied, then we probably don't want to // overwrite it. - if(c[l] == Graph::null_vertex()) return false; + if(c[l] == graph_traits::null_vertex()) return false; c[l] = v; return true; } @@ -411,7 +411,7 @@ class labeled_graph /** Return a null descriptor */ static vertex_descriptor null_vertex() - { return graph_type::null_vertex(); } + { return graph_traits::null_vertex(); } private: graph_type _graph; @@ -525,7 +525,7 @@ class labeled_graph #endif static vertex_descriptor null_vertex() - { return graph_type::null_vertex(); } + { return graph_traits::null_vertex(); } private: graph_type* _graph; From adaa84d86101a46c4481bb8dccb745d2d7ed412b Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Fri, 14 Sep 2012 18:04:00 +0000 Subject: [PATCH 208/333] Added void as default value of lookup_one_property_internal::type for "not found"; refs #7378 [SVN r80524] --- include/boost/pending/property.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/boost/pending/property.hpp b/include/boost/pending/property.hpp index bf504185c..f79e74482 100644 --- a/include/boost/pending/property.hpp +++ b/include/boost/pending/property.hpp @@ -55,7 +55,7 @@ namespace boost { // Code to look up one property in a property list: template - struct lookup_one_property_internal {BOOST_STATIC_CONSTANT(bool, found = false);}; + struct lookup_one_property_internal {BOOST_STATIC_CONSTANT(bool, found = false); typedef void type;}; // Special-case properties (vertex_all, edge_all, graph_all) #define BGL_ALL_PROP(tag) \ From 076085fd29f65f548ab1e4b45af249a30f178b2e Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Fri, 14 Sep 2012 21:41:06 +0000 Subject: [PATCH 209/333] Using lazy_enable_if to avoid "reference to void" errors for properties that are not found; fixes #7378 [SVN r80528] --- include/boost/pending/property.hpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/include/boost/pending/property.hpp b/include/boost/pending/property.hpp index f79e74482..0befc7986 100644 --- a/include/boost/pending/property.hpp +++ b/include/boost/pending/property.hpp @@ -123,12 +123,14 @@ namespace boost { typedef lookup_one_property_internal base_type; public: template - static typename enable_if >, typename base_type::type&>::type + static typename lazy_enable_if >, + add_reference >::type lookup(PL& prop, const PropName& tag) { return base_type::lookup(prop.m_base, tag); } template - static typename enable_if >, const typename base_type::type&>::type + static typename lazy_enable_if >, + add_reference >::type lookup(const PL& prop, const PropName& tag) { return base_type::lookup(prop.m_base, tag); } From 9002628f15fb0e91cc18d532b2e08144fa2829a2 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Sat, 15 Sep 2012 13:49:04 +0000 Subject: [PATCH 210/333] Further fixed #7378 issue; refs #7378 [SVN r80532] --- include/boost/pending/property.hpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/include/boost/pending/property.hpp b/include/boost/pending/property.hpp index 0befc7986..3ba9acc36 100644 --- a/include/boost/pending/property.hpp +++ b/include/boost/pending/property.hpp @@ -156,7 +156,8 @@ namespace boost { BOOST_STATIC_CONSTANT(bool, found = (lookup_one_property_internal::found)); typedef const typename lookup_one_property_internal::type type; template - static typename enable_if, const typename lookup_one_property_internal::type&>::type + static typename lazy_enable_if, + add_reference::type> >::type lookup(const U& p, Tag tag) { return lookup_one_property_internal::lookup(p, tag); } From 663127c3b71de31389700b796032bcb6970daefd Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Tue, 18 Sep 2012 03:27:42 +0000 Subject: [PATCH 211/333] Trying to remove unnecessary member accesses (that might not exist) for unused traits [SVN r80569] --- include/boost/graph/filtered_graph.hpp | 20 ++++++-------------- 1 file changed, 6 insertions(+), 14 deletions(-) diff --git a/include/boost/graph/filtered_graph.hpp b/include/boost/graph/filtered_graph.hpp index 6ac82927e..74fea4611 100644 --- a/include/boost/graph/filtered_graph.hpp +++ b/include/boost/graph/filtered_graph.hpp @@ -195,7 +195,6 @@ namespace boost { typedef filtered_graph_tag graph_tag; -#ifndef BOOST_GRAPH_NO_BUNDLED_PROPERTIES // Bundled properties support template typename graph::detail::bundled_result::type& @@ -206,7 +205,6 @@ namespace boost { typename graph::detail::bundled_result::type const& operator[](Descriptor x) const { return this->m_g[x]; } -#endif // BOOST_GRAPH_NO_BUNDLED_PROPERTIES static vertex_descriptor null_vertex() { @@ -222,26 +220,21 @@ namespace boost { template - struct vertex_property_type > { - typedef typename vertex_property_type::type type; - }; + struct vertex_property_type >: + vertex_property_type {}; template - struct edge_property_type > { - typedef typename edge_property_type::type type; - }; + struct edge_property_type >: + edge_property_type {}; template - struct graph_property_type > { - typedef typename graph_property_type::type type; - }; - + struct graph_property_type >: + graph_property_type {}; -#ifndef BOOST_GRAPH_NO_BUNDLED_PROPERTIES template struct vertex_bundle_type > @@ -256,7 +249,6 @@ namespace boost { struct graph_bundle_type > : graph_bundle_type { }; -#endif // BOOST_GRAPH_NO_BUNDLED_PROPERTIES //=========================================================================== // Non-member functions for the Filtered Edge Graph From 58829e019b7e07a43f5c5926fbc7554678781cc4 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Tue, 18 Sep 2012 18:20:15 +0000 Subject: [PATCH 212/333] Added more enable_ifs to try to get code working on VC++ [SVN r80582] --- include/boost/pending/property.hpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/include/boost/pending/property.hpp b/include/boost/pending/property.hpp index 3ba9acc36..3053908d7 100644 --- a/include/boost/pending/property.hpp +++ b/include/boost/pending/property.hpp @@ -94,8 +94,14 @@ namespace boost { private: \ typedef lookup_one_property_internal base_type; \ public: \ - static typename base_type::type& lookup(property& p, BOOST_JOIN(kind, _bundle_t)) {return base_type::lookup(p.m_base, BOOST_JOIN(kind, _bundle_t)());} \ - static const typename base_type::type& lookup(const property& p, BOOST_JOIN(kind, _bundle_t)) {return base_type::lookup(p.m_base, BOOST_JOIN(kind, _bundle_t)());} \ + template \ + static typename lazy_enable_if_c<(base_type::found && (is_same::value)), \ + add_reference >::type \ + lookup(property& p, BundleTag) {return base_type::lookup(p.m_base, BOOST_JOIN(kind, _bundle_t)());} \ + template \ + static typename lazy_enable_if_c<(base_type::found && (is_same::value)), \ + add_reference >::type \ + lookup(const property& p, BundleTag) {return base_type::lookup(p.m_base, BOOST_JOIN(kind, _bundle_t)());} \ }; \ BGL_DO_ONE_BUNDLE_TYPE(vertex) From 3be269ba3566c0dbad964df38f6863839b1d5430 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Sat, 22 Sep 2012 19:21:39 +0000 Subject: [PATCH 213/333] Added wording that infinite-weight edges are not guaranteed to work correctly; fixes #7398 [SVN r80637] --- doc/dijkstra_shortest_paths.html | 4 +++- doc/dijkstra_shortest_paths_no_color_map.html | 14 ++++---------- 2 files changed, 7 insertions(+), 11 deletions(-) diff --git a/doc/dijkstra_shortest_paths.html b/doc/dijkstra_shortest_paths.html index 4ed19711f..369e78a0d 100644 --- a/doc/dijkstra_shortest_paths.html +++ b/doc/dijkstra_shortest_paths.html @@ -330,7 +330,9 @@

      Named Parameters

      The inf object must be the greatest value of any D object. That is, compare(d, inf) == true for any d != inf. - The type D is the value type of the DistanceMap.
      + The type D is the value type of the DistanceMap. Edges + are assumed to have a weight less than (using distance_compare for + comparison) this value.
      Default: std::numeric_limits<D>::max()
      Python: Unsupported parameter. diff --git a/doc/dijkstra_shortest_paths_no_color_map.html b/doc/dijkstra_shortest_paths_no_color_map.html index e1cc1c8ec..b65d333f0 100644 --- a/doc/dijkstra_shortest_paths_no_color_map.html +++ b/doc/dijkstra_shortest_paths_no_color_map.html @@ -69,7 +69,7 @@

      - dijkstra_shortest_paths_no_color_map differs from the original dijkstra_shortest_paths algorithm by not using a color map to identify vertices as discovered or undiscovered. Instead, this is done with the distance map: a vertex u such that distance_compare(distance_map[u], distance_infinity) == false is considered to be undiscovered. + dijkstra_shortest_paths_no_color_map differs from the original dijkstra_shortest_paths algorithm by not using a color map to identify vertices as discovered or undiscovered. Instead, this is done with the distance map: a vertex u such that distance_compare(distance_map[u], distance_infinity) == false is considered to be undiscovered. Note that this means that edges with infinite weight will not work correctly in this algorithm.

      @@ -116,10 +116,6 @@

       DIJKSTRA(G, s, w)
      -  for each vertex u in V (This loop is not run in dijkstra_shortest_paths_no_color_map_no_init)
      -    d[u] := infinity 
      -    p[u] := u 
      -  end for
         d[s] := 0 
         INSERT(Q, s)
         while (Q != Ø)
      @@ -141,10 +137,6 @@ 

       
      -initialize vertex u
      -
      -
      -
       
       discover vertex s
       
      @@ -293,7 +285,9 @@ 

      Named Parameters

      The distance_infinity object must be the greatest value of any D object. That is, distance_compare(d, distance_infinity) == true for any d != distance_infinity. - The type D is the value type of the DistanceMap.
      + The type D is the value type of the DistanceMap. All edges + are assumed to have weight less than (by distance_compare) this + value.
      Default: std::numeric_limits<D>::max()
      From 8afe81608caf57c1fbdea78ea2a3cdb3f0f5da18 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Sat, 22 Sep 2012 19:26:30 +0000 Subject: [PATCH 214/333] Reversed incorrect order of arguments to non-named-parameter call; fixes #7380 [SVN r80638] --- include/boost/graph/astar_search.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/boost/graph/astar_search.hpp b/include/boost/graph/astar_search.hpp index 132dca021..38224a982 100644 --- a/include/boost/graph/astar_search.hpp +++ b/include/boost/graph/astar_search.hpp @@ -370,8 +370,8 @@ namespace boost { detail::make_property_map_from_arg_pack_gen(D())(g, arg_pack), detail::make_property_map_from_arg_pack_gen(D())(g, arg_pack), detail::override_const_property(arg_pack, _weight_map, g, edge_weight), - detail::override_const_property(arg_pack, _vertex_index_map, g, vertex_index), detail::make_color_map_from_arg_pack(g, arg_pack), + detail::override_const_property(arg_pack, _vertex_index_map, g, vertex_index), arg_pack[_distance_compare | std::less()], arg_pack[_distance_combine | closed_plus(inf)], inf, From f16a1b114dc11c85ffbfb73f5d0d78ff2472c5da Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Sat, 22 Sep 2012 19:32:32 +0000 Subject: [PATCH 215/333] Fixed relax logic to not write predecessor map unless distance was actually changed in memory (although this case will never be hit unless registers have extra precision compared to memory); fixes #7226 [SVN r80639] --- include/boost/graph/relax.hpp | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/include/boost/graph/relax.hpp b/include/boost/graph/relax.hpp index 9c0d0260c..e3866df48 100644 --- a/include/boost/graph/relax.hpp +++ b/include/boost/graph/relax.hpp @@ -53,17 +53,26 @@ namespace boost { const D d_v = get(d, v); const W& w_e = get(w, e); - // The redundant gets in the return statements are to ensure that extra - // floating-point precision in x87 registers does not lead to relax() - // returning true when the distance did not actually change. + // The seemingly redundant comparisons after the distance puts are to + // ensure that extra floating-point precision in x87 registers does not + // lead to relax() returning true when the distance did not actually + // change. if ( compare(combine(d_u, w_e), d_v) ) { put(d, v, combine(d_u, w_e)); - put(p, v, u); - return compare(get(d, v), d_v); + if (compare(get(d, v), d_v)) { + put(p, v, u); + return true; + } else { + return false; + } } else if (is_undirected && compare(combine(d_v, w_e), d_u)) { put(d, u, combine(d_v, w_e)); - put(p, u, v); - return compare(get(d, u), d_u); + if (compare(get(d, u), d_u)) { + put(p, u, v); + return true; + } else { + return false; + } } else return false; } From b9e9ed20675412c59afaf5f48100dd53173ef584 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Sat, 22 Sep 2012 20:08:44 +0000 Subject: [PATCH 216/333] Removed invalid templated friend definitions and fixed other bugs [SVN r80640] --- include/boost/graph/grid_graph.hpp | 243 +++++++++++++---------------- 1 file changed, 107 insertions(+), 136 deletions(-) diff --git a/include/boost/graph/grid_graph.hpp b/include/boost/graph/grid_graph.hpp index 7bb373242..9a09fca34 100644 --- a/include/boost/graph/grid_graph.hpp +++ b/include/boost/graph/grid_graph.hpp @@ -30,11 +30,6 @@ #define BOOST_GRID_GRAPH_TYPE \ grid_graph -#define BOOST_GRID_GRAPH_TYPE_MEM typename BOOST_GRID_GRAPH_TYPE:: - -#define BOOST_GRID_GRAPH_TYPE_TD(mem) \ - typedef typename BOOST_GRID_GRAPH_TYPE::mem mem - #define BOOST_GRID_GRAPH_TRAITS_T \ typename graph_traits @@ -68,6 +63,13 @@ namespace boost { return (m_graph->index_of(key)); } + friend inline Index + get(const grid_graph_index_map& index_map, + const typename grid_graph_index_map::key_type& key) + { + return (index_map[key]); + } + protected: const Graph* m_graph; }; @@ -106,6 +108,13 @@ namespace boost { value_type operator[](const key_type& key) const { return (value_type(key.second, key.first)); } + + friend inline Descriptor + get(const grid_graph_reverse_edge_map& rev_map, + const typename grid_graph_reverse_edge_map::key_type& key) + { + return (rev_map[key]); + } }; template @@ -442,7 +451,7 @@ namespace boost { vertex_descriptor vertex_at (vertices_size_type vertex_index) const { - array vertex; + boost::array vertex; vertices_size_type index_divider = 1; for (std::size_t dimension_index = 0; @@ -532,6 +541,8 @@ namespace boost { vertex_descriptor source_vertex = source(edge, *this); vertex_descriptor target_vertex = target(edge, *this); + BOOST_ASSERT (source_vertex != target_vertex); + // Determine the dimension where the source and target vertices // differ (should only be one if this is a valid edge). std::size_t different_dimension_index = 0; @@ -732,13 +743,12 @@ namespace boost { // VertexListGraph //================ - template - friend inline std::pair - vertices(const BOOST_GRID_GRAPH_TYPE& graph) { - BOOST_GRID_GRAPH_TYPE_TD(vertex_iterator); - BOOST_GRID_GRAPH_TYPE_TD(vertex_function); - BOOST_GRID_GRAPH_TYPE_TD(vertex_index_iterator); + friend inline std::pair + vertices(const type& graph) { + typedef typename type::vertex_iterator vertex_iterator; + typedef typename type::vertex_function vertex_function; + typedef typename type::vertex_index_iterator vertex_index_iterator; return (std::make_pair (vertex_iterator(vertex_index_iterator(0), @@ -747,16 +757,14 @@ namespace boost { vertex_function(&graph)))); } - template - friend inline BOOST_GRID_GRAPH_TYPE_MEM vertices_size_type - num_vertices(const BOOST_GRID_GRAPH_TYPE& graph) { + friend inline typename type::vertices_size_type + num_vertices(const type& graph) { return (graph.num_vertices()); } - template - friend inline BOOST_GRID_GRAPH_TYPE_MEM vertex_descriptor - vertex(BOOST_GRID_GRAPH_TYPE_MEM vertices_size_type vertex_index, - const BOOST_GRID_GRAPH_TYPE& graph) { + friend inline typename type::vertex_descriptor + vertex(typename type::vertices_size_type vertex_index, + const type& graph) { return (graph.vertex_at(vertex_index)); } @@ -765,14 +773,13 @@ namespace boost { // IncidenceGraph //=============== - template - friend inline std::pair - out_edges(BOOST_GRID_GRAPH_TYPE_MEM vertex_descriptor vertex, - const BOOST_GRID_GRAPH_TYPE& graph) { - BOOST_GRID_GRAPH_TYPE_TD(degree_iterator); - BOOST_GRID_GRAPH_TYPE_TD(out_edge_function); - BOOST_GRID_GRAPH_TYPE_TD(out_edge_iterator); + friend inline std::pair + out_edges(typename type::vertex_descriptor vertex, + const type& graph) { + typedef typename type::degree_iterator degree_iterator; + typedef typename type::out_edge_function out_edge_function; + typedef typename type::out_edge_iterator out_edge_iterator; return (std::make_pair (out_edge_iterator(degree_iterator(0), @@ -781,19 +788,17 @@ namespace boost { out_edge_function(vertex, &graph)))); } - template - friend inline BOOST_GRID_GRAPH_TYPE_MEM degree_size_type + friend inline typename type::degree_size_type out_degree - (BOOST_GRID_GRAPH_TYPE_MEM vertex_descriptor vertex, - const BOOST_GRID_GRAPH_TYPE& graph) { + (typename type::vertex_descriptor vertex, + const type& graph) { return (graph.out_degree(vertex)); } - template - friend inline BOOST_GRID_GRAPH_TYPE_MEM edge_descriptor - out_edge_at(BOOST_GRID_GRAPH_TYPE_MEM vertex_descriptor vertex, - BOOST_GRID_GRAPH_TYPE_MEM degree_size_type out_edge_index, - const BOOST_GRID_GRAPH_TYPE& graph) { + friend inline typename type::edge_descriptor + out_edge_at(typename type::vertex_descriptor vertex, + typename type::degree_size_type out_edge_index, + const type& graph) { return (graph.out_edge_at(vertex, out_edge_index)); } @@ -801,14 +806,13 @@ namespace boost { // AdjacencyGraph //=============== - template - friend typename std::pair - adjacent_vertices (BOOST_GRID_GRAPH_TYPE_MEM vertex_descriptor vertex, - const BOOST_GRID_GRAPH_TYPE& graph) { - BOOST_GRID_GRAPH_TYPE_TD(degree_iterator); - BOOST_GRID_GRAPH_TYPE_TD(adjacent_vertex_function); - BOOST_GRID_GRAPH_TYPE_TD(adjacency_iterator); + friend typename std::pair + adjacent_vertices (typename type::vertex_descriptor vertex, + const type& graph) { + typedef typename type::degree_iterator degree_iterator; + typedef typename type::adjacent_vertex_function adjacent_vertex_function; + typedef typename type::adjacency_iterator adjacency_iterator; return (std::make_pair (adjacency_iterator(degree_iterator(0), @@ -821,26 +825,23 @@ namespace boost { // EdgeListGraph //============== - template - friend inline BOOST_GRID_GRAPH_TYPE_MEM edges_size_type - num_edges(const BOOST_GRID_GRAPH_TYPE& graph) { + friend inline typename type::edges_size_type + num_edges(const type& graph) { return (graph.num_edges()); } - template - friend inline BOOST_GRID_GRAPH_TYPE_MEM edge_descriptor - edge_at(BOOST_GRID_GRAPH_TYPE_MEM edges_size_type edge_index, - const BOOST_GRID_GRAPH_TYPE& graph) { + friend inline typename type::edge_descriptor + edge_at(typename type::edges_size_type edge_index, + const type& graph) { return (graph.edge_at(edge_index)); } - template - friend inline std::pair - edges(const BOOST_GRID_GRAPH_TYPE& graph) { - BOOST_GRID_GRAPH_TYPE_TD(edge_index_iterator); - BOOST_GRID_GRAPH_TYPE_TD(edge_function); - BOOST_GRID_GRAPH_TYPE_TD(edge_iterator); + friend inline std::pair + edges(const type& graph) { + typedef typename type::edge_index_iterator edge_index_iterator; + typedef typename type::edge_function edge_function; + typedef typename type::edge_iterator edge_iterator; return (std::make_pair (edge_iterator(edge_index_iterator(0), @@ -853,14 +854,13 @@ namespace boost { // BiDirectionalGraph //=================== - template - friend inline std::pair - in_edges(BOOST_GRID_GRAPH_TYPE_MEM vertex_descriptor vertex, - const BOOST_GRID_GRAPH_TYPE& graph) { - BOOST_GRID_GRAPH_TYPE_TD(in_edge_function); - BOOST_GRID_GRAPH_TYPE_TD(degree_iterator); - BOOST_GRID_GRAPH_TYPE_TD(in_edge_iterator); + friend inline std::pair + in_edges(typename type::vertex_descriptor vertex, + const type& graph) { + typedef typename type::in_edge_function in_edge_function; + typedef typename type::degree_iterator degree_iterator; + typedef typename type::in_edge_iterator in_edge_iterator; return (std::make_pair (in_edge_iterator(degree_iterator(0), @@ -869,25 +869,22 @@ namespace boost { in_edge_function(vertex, &graph)))); } - template - friend inline BOOST_GRID_GRAPH_TYPE_MEM degree_size_type - in_degree (BOOST_GRID_GRAPH_TYPE_MEM vertex_descriptor vertex, - const BOOST_GRID_GRAPH_TYPE& graph) { + friend inline typename type::degree_size_type + in_degree (typename type::vertex_descriptor vertex, + const type& graph) { return (graph.in_degree(vertex)); } - template - friend inline BOOST_GRID_GRAPH_TYPE_MEM degree_size_type - degree (BOOST_GRID_GRAPH_TYPE_MEM vertex_descriptor vertex, - const BOOST_GRID_GRAPH_TYPE& graph) { + friend inline typename type::degree_size_type + degree (typename type::vertex_descriptor vertex, + const type& graph) { return (graph.out_degree(vertex) * 2); } - template - friend inline BOOST_GRID_GRAPH_TYPE_MEM edge_descriptor - in_edge_at(BOOST_GRID_GRAPH_TYPE_MEM vertex_descriptor vertex, - BOOST_GRID_GRAPH_TYPE_MEM degree_size_type in_edge_index, - const BOOST_GRID_GRAPH_TYPE& graph) { + friend inline typename type::edge_descriptor + in_edge_at(typename type::vertex_descriptor vertex, + typename type::degree_size_type in_edge_index, + const type& graph) { return (graph.in_edge_at(vertex, in_edge_index)); } @@ -896,21 +893,20 @@ namespace boost { // Adjacency Matrix //================== - template - friend std::pair - edge (BOOST_GRID_GRAPH_TYPE_MEM vertex_descriptor source_vertex, - BOOST_GRID_GRAPH_TYPE_MEM vertex_descriptor destination_vertex, - const BOOST_GRID_GRAPH_TYPE& graph) { + friend std::pair + edge (typename type::vertex_descriptor source_vertex, + typename type::vertex_descriptor destination_vertex, + const type& graph) { - std::pair edge_exists = + std::pair edge_exists = std::make_pair(std::make_pair(source_vertex, destination_vertex), false); for (std::size_t dimension_index = 0; dimension_index < Dimensions; ++dimension_index) { - BOOST_GRID_GRAPH_TYPE_MEM vertices_size_type dim_difference = 0; - BOOST_GRID_GRAPH_TYPE_MEM vertices_size_type + typename type::vertices_size_type dim_difference = 0; + typename type::vertices_size_type source_dim = source_vertex[dimension_index], dest_dim = destination_vertex[dimension_index]; @@ -957,77 +953,54 @@ namespace boost { // Index Property Map Functions //============================= - template - friend inline BOOST_GRID_GRAPH_TYPE_MEM vertices_size_type + friend inline typename type::vertices_size_type get(vertex_index_t, - const BOOST_GRID_GRAPH_TYPE& graph, - BOOST_GRID_GRAPH_TYPE_MEM vertex_descriptor vertex) { + const type& graph, + typename type::vertex_descriptor vertex) { return (graph.index_of(vertex)); } - template - friend inline BOOST_GRID_GRAPH_TYPE_MEM edges_size_type + friend inline typename type::edges_size_type get(edge_index_t, - const BOOST_GRID_GRAPH_TYPE& graph, - BOOST_GRID_GRAPH_TYPE_MEM edge_descriptor edge) { + const type& graph, + typename type::edge_descriptor edge) { return (graph.index_of(edge)); } - template friend inline grid_graph_index_map< - BOOST_GRID_GRAPH_TYPE, - BOOST_GRID_GRAPH_TYPE_MEM vertex_descriptor, - BOOST_GRID_GRAPH_TYPE_MEM vertices_size_type> - get(vertex_index_t, const BOOST_GRID_GRAPH_TYPE& graph) { + type, + typename type::vertex_descriptor, + typename type::vertices_size_type> + get(vertex_index_t, const type& graph) { return (grid_graph_index_map< - BOOST_GRID_GRAPH_TYPE, - BOOST_GRID_GRAPH_TYPE_MEM vertex_descriptor, - BOOST_GRID_GRAPH_TYPE_MEM vertices_size_type>(graph)); + type, + typename type::vertex_descriptor, + typename type::vertices_size_type>(graph)); } - template friend inline grid_graph_index_map< - BOOST_GRID_GRAPH_TYPE, - BOOST_GRID_GRAPH_TYPE_MEM edge_descriptor, - BOOST_GRID_GRAPH_TYPE_MEM edges_size_type> - get(edge_index_t, const BOOST_GRID_GRAPH_TYPE& graph) { + type, + typename type::edge_descriptor, + typename type::edges_size_type> + get(edge_index_t, const type& graph) { return (grid_graph_index_map< - BOOST_GRID_GRAPH_TYPE, - BOOST_GRID_GRAPH_TYPE_MEM edge_descriptor, - BOOST_GRID_GRAPH_TYPE_MEM edges_size_type>(graph)); + type, + typename type::edge_descriptor, + typename type::edges_size_type>(graph)); } - template friend inline grid_graph_reverse_edge_map< - BOOST_GRID_GRAPH_TYPE_MEM edge_descriptor> - get(edge_reverse_t, const BOOST_GRID_GRAPH_TYPE& graph) { + typename type::edge_descriptor> + get(edge_reverse_t, const type& graph) { return (grid_graph_reverse_edge_map< - BOOST_GRID_GRAPH_TYPE_MEM edge_descriptor>()); + typename type::edge_descriptor>()); } - template - friend inline Index - get(const grid_graph_index_map& index_map, - const typename grid_graph_index_map::key_type& key) - { - return (index_map[key]); - } - template friend struct grid_graph_index_map; - template - friend inline Descriptor - get(const grid_graph_reverse_edge_map& rev_map, - const typename grid_graph_reverse_edge_map::key_type& key) - { - return (rev_map[key]); - } - template friend struct grid_graph_reverse_edge_map; @@ -1036,8 +1009,6 @@ namespace boost { } // namespace boost #undef BOOST_GRID_GRAPH_TYPE -#undef BOOST_GRID_GRAPH_TYPE_TD -#undef BOOST_GRID_GRAPH_TYPE_MEM #undef BOOST_GRID_GRAPH_TEMPLATE_PARAMS #undef BOOST_GRID_GRAPH_TRAITS_T From 3009b2303c0712f99b4f14833bf4e2178af2ad22 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Sat, 22 Sep 2012 20:09:08 +0000 Subject: [PATCH 217/333] Checking multiple dimensionalities of graphs [SVN r80641] --- test/grid_graph_cc.cpp | 19 ++++++++---- test/grid_graph_test.cpp | 63 ++++++++++++++++++++++------------------ 2 files changed, 48 insertions(+), 34 deletions(-) diff --git a/test/grid_graph_cc.cpp b/test/grid_graph_cc.cpp index a9e1c808f..d49de7c35 100644 --- a/test/grid_graph_cc.cpp +++ b/test/grid_graph_cc.cpp @@ -12,14 +12,13 @@ #include #include -#define DIMENSIONS 3 using namespace boost; -int main (int, char*[]) { - - typedef grid_graph Graph; - typedef graph_traits::vertex_descriptor Vertex; - typedef graph_traits::edge_descriptor Edge; +template +void check() { + typedef grid_graph Graph; + typedef typename graph_traits::vertex_descriptor Vertex; + typedef typename graph_traits::edge_descriptor Edge; BOOST_CONCEPT_ASSERT((BidirectionalGraphConcept )); BOOST_CONCEPT_ASSERT((VertexListGraphConcept )); @@ -29,6 +28,14 @@ int main (int, char*[]) { BOOST_CONCEPT_ASSERT((AdjacencyMatrixConcept )); BOOST_CONCEPT_ASSERT((ReadablePropertyGraphConcept )); BOOST_CONCEPT_ASSERT((ReadablePropertyGraphConcept )); +} + +int main (int, char*[]) { + check<0>(); + check<1>(); + check<2>(); + check<3>(); + check<4>(); return (0); } diff --git a/test/grid_graph_test.cpp b/test/grid_graph_test.cpp index 3cd665bdf..d88e68d2e 100644 --- a/test/grid_graph_test.cpp +++ b/test/grid_graph_test.cpp @@ -17,8 +17,6 @@ #include #include -#define DIMENSIONS 3 - using namespace boost; // Function that prints a vertex to std::cout @@ -28,11 +26,11 @@ void print_vertex(Vertex vertex_to_print) { std::cout << "("; for (std::size_t dimension_index = 0; - dimension_index < DIMENSIONS; + dimension_index < vertex_to_print.size(); ++dimension_index) { std::cout << vertex_to_print[dimension_index]; - if (dimension_index != (DIMENSIONS - 1)) { + if (dimension_index != (vertex_to_print.size() - 1)) { std::cout << ", "; } } @@ -40,31 +38,23 @@ void print_vertex(Vertex vertex_to_print) { std::cout << ")"; } -int test_main(int argc, char* argv[]) { - - std::size_t random_seed = time(0); - - if (argc > 1) { - random_seed = lexical_cast(argv[1]); - } - - minstd_rand generator(random_seed); - - typedef grid_graph Graph; - typedef graph_traits::vertices_size_type vertices_size_type; - typedef graph_traits::edges_size_type edges_size_type; +template +void do_test(minstd_rand& generator) { + typedef grid_graph Graph; + typedef typename graph_traits::vertices_size_type vertices_size_type; + typedef typename graph_traits::edges_size_type edges_size_type; - typedef graph_traits::vertex_descriptor vertex_descriptor; - typedef graph_traits::edge_descriptor edge_descriptor; + typedef typename graph_traits::vertex_descriptor vertex_descriptor; + typedef typename graph_traits::edge_descriptor edge_descriptor; - std::cout << "Dimensions: " << DIMENSIONS << ", lengths: "; + std::cout << "Dimensions: " << Dims << ", lengths: "; // Randomly generate the dimension lengths (3-10) and wrapping - array lengths; - array wrapped; + boost::array lengths; + boost::array wrapped; - for (int dimension_index = 0; - dimension_index < DIMENSIONS; + for (unsigned int dimension_index = 0; + dimension_index < Dims; ++dimension_index) { lengths[dimension_index] = 3 + (generator() % 8); wrapped[dimension_index] = ((generator() % 2) == 0); @@ -78,8 +68,8 @@ int test_main(int argc, char* argv[]) { Graph graph(lengths, wrapped); // Verify dimension lengths and wrapping - for (int dimension_index = 0; - dimension_index < DIMENSIONS; + for (unsigned int dimension_index = 0; + dimension_index < Dims; ++dimension_index) { BOOST_REQUIRE(graph.length(dimension_index) == lengths[dimension_index]); BOOST_REQUIRE(graph.wrapped(dimension_index) == wrapped[dimension_index]); @@ -107,8 +97,8 @@ int test_main(int argc, char* argv[]) { vertices_size_type current_index = get(boost::vertex_index, graph, current_vertex); - for (int dimension_index = 0; - dimension_index < DIMENSIONS; + for (unsigned int dimension_index = 0; + dimension_index < Dims; ++dimension_index) { BOOST_REQUIRE(/*(current_vertex[dimension_index] >= 0) && */ // Always true (current_vertex[dimension_index] < lengths[dimension_index])); @@ -205,6 +195,23 @@ int test_main(int argc, char* argv[]) { } BOOST_REQUIRE(edge_count == num_edges(graph)); +} + +int test_main(int argc, char* argv[]) { + + std::size_t random_seed = time(0); + + if (argc > 1) { + random_seed = lexical_cast(argv[1]); + } + + minstd_rand generator(random_seed); + + do_test<0>(generator); + do_test<1>(generator); + do_test<2>(generator); + do_test<3>(generator); + do_test<4>(generator); return (0); } From ddf8a5e07ea1a1368c769f81d4e3eb2cee72d6ae Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Sat, 22 Sep 2012 20:09:44 +0000 Subject: [PATCH 218/333] Removed incorrect note about restrictions on graph dimensionality and fixed other typos; fixes #6950 [SVN r80642] --- doc/grid_graph.html | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/grid_graph.html b/doc/grid_graph.html index 100c97ecc..0a2fea5dd 100644 --- a/doc/grid_graph.html +++ b/doc/grid_graph.html @@ -81,13 +81,13 @@

      Template Parameters

      • - Dimensions - Number of dimensions in the graph, must be greater than 2 + Dimensions - Number of dimensions in the graph
      • - VertexIndex - Type used for vertex indices, defaults to std::size_t + VertexIndex - Type used for vertex indices, defaults to std::size_t
      • - EdgeIndex - Type used for edge indices, defaults to the same type as VertexIndex + EdgeIndex - Type used for edge indices, defaults to the same type as VertexIndex
      From f95abaa83c1746441bf40fc7d5d21dfee13f8682 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Thu, 27 Sep 2012 17:43:07 +0000 Subject: [PATCH 219/333] Applied patch from #7428; fixes #7428 [SVN r80725] --- include/boost/graph/compressed_sparse_row_graph.hpp | 2 +- include/boost/graph/detail/indexed_properties.hpp | 4 ++-- include/boost/graph/detail/set_adaptor.hpp | 2 +- include/boost/graph/named_function_params.hpp | 10 +++++----- include/boost/graph/named_graph.hpp | 2 +- include/boost/graph/reverse_graph.hpp | 8 ++++---- include/boost/graph/visitors.hpp | 4 ++-- 7 files changed, 16 insertions(+), 16 deletions(-) diff --git a/include/boost/graph/compressed_sparse_row_graph.hpp b/include/boost/graph/compressed_sparse_row_graph.hpp index 59e8bb4ab..42e2419aa 100644 --- a/include/boost/graph/compressed_sparse_row_graph.hpp +++ b/include/boost/graph/compressed_sparse_row_graph.hpp @@ -136,7 +136,7 @@ namespace detail { typedef boost::iterator_facade, T, std::random_access_iterator_tag, const T&> base_type; T saved_value; const T& dereference() const {return saved_value;} - bool equal(default_construct_iterator i) const {return true;} + bool equal(default_construct_iterator /*i*/) const {return true;} void increment() {} void decrement() {} void advance(typename base_type::difference_type) {} diff --git a/include/boost/graph/detail/indexed_properties.hpp b/include/boost/graph/detail/indexed_properties.hpp index e1f874b2c..4494625c6 100644 --- a/include/boost/graph/detail/indexed_properties.hpp +++ b/include/boost/graph/detail/indexed_properties.hpp @@ -253,7 +253,7 @@ class indexed_edge_properties typedef secret const_edge_map_type; secret operator[](secret) { return secret(); } - void write_by_index(std::size_t idx, const no_property& prop) {} + void write_by_index(std::size_t /*idx*/, const no_property& /*prop*/) {} edge_map_type get_edge_bundle(const IndexMap& = IndexMap()) const { return edge_map_type(); @@ -270,7 +270,7 @@ class indexed_edge_properties public: void push_back(const edge_push_back_type&) { } - void move_range(std::size_t src_begin, std::size_t src_end, std::size_t dest_begin) {} + void move_range(std::size_t /*src_begin*/, std::size_t /*src_end*/, std::size_t /*dest_begin*/) {} typedef dummy_no_property_iterator iterator; iterator begin() {return dummy_no_property_iterator();} diff --git a/include/boost/graph/detail/set_adaptor.hpp b/include/boost/graph/detail/set_adaptor.hpp index 90a64a2cd..33acc07e3 100644 --- a/include/boost/graph/detail/set_adaptor.hpp +++ b/include/boost/graph/detail/set_adaptor.hpp @@ -111,7 +111,7 @@ namespace boost { // Shit, can't implement this without knowing the size of the // universe. template - void set_compliment(const std::set& x, + void set_compliment(const std::set& /*x*/, std::set& z) { z.clear(); diff --git a/include/boost/graph/named_function_params.hpp b/include/boost/graph/named_function_params.hpp index 32dd58023..94314a692 100644 --- a/include/boost/graph/named_function_params.hpp +++ b/include/boost/graph/named_function_params.hpp @@ -432,13 +432,13 @@ BOOST_BGL_DECLARE_NAMED_PARAMS template struct override_property_t { typedef ArgType result_type; - result_type operator()(const Graph& g, const typename boost::add_reference::type a) const {return a;} + result_type operator()(const Graph&, const typename boost::add_reference::type a) const {return a;} }; template struct override_property_t { typedef typename boost::property_map::type result_type; - result_type operator()(const Graph& g, const ArgType& a) const {return get(Prop(), g);} + result_type operator()(const Graph& g, const ArgType&) const {return get(Prop(), g);} }; template @@ -455,7 +455,7 @@ BOOST_BGL_DECLARE_NAMED_PARAMS template typename override_property_result::type - override_property(const ArgPack& ap, const boost::parameter::keyword& t, const Graph& g, Prop prop) { + override_property(const ArgPack& ap, const boost::parameter::keyword& t, const Graph& g, Prop) { return override_property_t< typename boost::parameter::value_type::type, Prop, @@ -633,7 +633,7 @@ BOOST_BGL_DECLARE_NAMED_PARAMS typedef Q priority_queue_type; static priority_queue_type - make_queue(const Graph& g, const ArgPack& ap, KeyT defaultKey, const Q& q) { + make_queue(const Graph&, const ArgPack&, KeyT, const Q& q) { return q; } }; @@ -645,7 +645,7 @@ BOOST_BGL_DECLARE_NAMED_PARAMS typedef boost::d_ary_heap_indirect::helper::map_type, Compare> priority_queue_type; static priority_queue_type - make_queue(const Graph& g, const ArgPack& ap, KeyT defaultKey, const Q& q) { + make_queue(const Graph& g, const ArgPack& ap, KeyT defaultKey, const Q&) { return priority_queue_type( map_maker::make_map(g, ap, defaultKey), map_maker::make_map(g, ap, typename boost::property_traits::value_type(-1)) diff --git a/include/boost/graph/named_graph.hpp b/include/boost/graph/named_graph.hpp index f49c09707..77e1a22f6 100644 --- a/include/boost/graph/named_graph.hpp +++ b/include/boost/graph/named_graph.hpp @@ -105,7 +105,7 @@ struct cannot_add_vertex typedef vertex_name_type argument_type; typedef VertexProperty result_type; - VertexProperty operator()(const vertex_name_type& name) + VertexProperty operator()(const vertex_name_type&) { boost::throw_exception(std::runtime_error("add_vertex: " "unable to create a vertex from its name")); diff --git a/include/boost/graph/reverse_graph.hpp b/include/boost/graph/reverse_graph.hpp index 96fc32d3a..bea975ab9 100644 --- a/include/boost/graph/reverse_graph.hpp +++ b/include/boost/graph/reverse_graph.hpp @@ -460,7 +460,7 @@ template typename enable_if, detail::underlying_edge_desc_map_type::edge_descriptor> >::type get(edge_underlying_t, - G& g) + G&) { return detail::underlying_edge_desc_map_type::edge_descriptor>(); } @@ -468,7 +468,7 @@ get(edge_underlying_t, template typename enable_if, typename graph_traits::edge_descriptor>::type get(edge_underlying_t, - G& g, + G&, const typename graph_traits::edge_descriptor& k) { return k.underlying_descx; @@ -477,7 +477,7 @@ get(edge_underlying_t, template typename enable_if, detail::underlying_edge_desc_map_type::edge_descriptor> >::type get(edge_underlying_t, - const G& g) + const G&) { return detail::underlying_edge_desc_map_type::edge_descriptor>(); } @@ -485,7 +485,7 @@ get(edge_underlying_t, template typename enable_if, typename graph_traits::edge_descriptor>::type get(edge_underlying_t, - const G& g, + const G&, const typename graph_traits::edge_descriptor& k) { return k.underlying_descx; diff --git a/include/boost/graph/visitors.hpp b/include/boost/graph/visitors.hpp index 39314f5a5..e4a614f35 100644 --- a/include/boost/graph/visitors.hpp +++ b/include/boost/graph/visitors.hpp @@ -270,7 +270,7 @@ namespace boost { {} template - void operator() (VertexOrEdge v, const Graph& g) + void operator() (VertexOrEdge v, const Graph&) { put (property_map_, v, value_); } @@ -293,7 +293,7 @@ namespace boost { inline property_put put_property (PropertyMap property_map, typename property_traits ::value_type value, - EventTag tag) + EventTag) { return property_put (property_map, value); } From b214ef2f4db5b0925fb7e8f729ddf9d3584368c3 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Mon, 1 Oct 2012 18:31:15 +0000 Subject: [PATCH 220/333] Changed classes to structs to get public inheritance; thanks to Shaun Jackman for the bug report [SVN r80811] --- include/boost/graph/properties.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/boost/graph/properties.hpp b/include/boost/graph/properties.hpp index 5cc926bc0..31257ca2f 100644 --- a/include/boost/graph/properties.hpp +++ b/include/boost/graph/properties.hpp @@ -248,8 +248,8 @@ namespace boost { >::type type; }; - template class vertex_property: vertex_property_type {}; - template class edge_property: edge_property_type {}; + template struct vertex_property: vertex_property_type {}; + template struct edge_property: edge_property_type {}; template class degree_property_map From c964747407a7283d235107a607194bb2300fd615 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Tue, 2 Oct 2012 03:05:22 +0000 Subject: [PATCH 221/333] Applied patch from #7457; fixes #7457 [SVN r80814] --- include/boost/graph/kamada_kawai_spring_layout.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/boost/graph/kamada_kawai_spring_layout.hpp b/include/boost/graph/kamada_kawai_spring_layout.hpp index f8a210cab..63355c946 100644 --- a/include/boost/graph/kamada_kawai_spring_layout.hpp +++ b/include/boost/graph/kamada_kawai_spring_layout.hpp @@ -475,12 +475,12 @@ namespace boost { * from every vertex to every other vertex, which is computed in the * first stages of the algorithm. This value's type must be a model * of BasicMatrix with value type equal to the value type of the - * weight map. The default is a a vector of vectors. + * weight map. The default is a vector of vectors. * * \param spring_strength (UTIL/OUT) will be used to store the * strength of the spring between every pair of vertices. This * value's type must be a model of BasicMatrix with value type equal - * to the value type of the weight map. The default is a a vector of + * to the value type of the weight map. The default is a vector of * vectors. * * \param partial_derivatives (UTIL) will be used to store the From 34ddb83a49ee390e790d75b6376db187526538b1 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Thu, 4 Oct 2012 14:49:26 +0000 Subject: [PATCH 222/333] Removed extra semicolon; fixes #7467 [SVN r80842] --- include/boost/graph/reverse_graph.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/boost/graph/reverse_graph.hpp b/include/boost/graph/reverse_graph.hpp index bea975ab9..7985e97f0 100644 --- a/include/boost/graph/reverse_graph.hpp +++ b/include/boost/graph/reverse_graph.hpp @@ -433,7 +433,7 @@ namespace detail { { return m[k]; } -}; +} template struct property_traits > { From 8f37c21e998b0575931d2de3c934351f677dfb18 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Fri, 5 Oct 2012 22:40:22 +0000 Subject: [PATCH 223/333] Fixed return type of vertex_by_label [SVN r80879] --- include/boost/graph/labeled_graph.hpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/include/boost/graph/labeled_graph.hpp b/include/boost/graph/labeled_graph.hpp index 67505d250..9c06f8fcf 100644 --- a/include/boost/graph/labeled_graph.hpp +++ b/include/boost/graph/labeled_graph.hpp @@ -544,8 +544,9 @@ inline bool label_vertex(typename LABELED_GRAPH::vertex_descriptor v, { return g.label_vertex(v, l); } template -inline bool vertex_by_label(typename LABELED_GRAPH::label_type const l, - LABELED_GRAPH& g) +inline typename LABELED_GRAPH::vertex_descriptor +vertex_by_label(typename LABELED_GRAPH::label_type const l, + LABELED_GRAPH& g) { return g.vertex(l); } //@} From 0d1769a27c57b8a254a35cdc65f605a26e6c7422 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Mon, 8 Oct 2012 20:04:48 +0000 Subject: [PATCH 224/333] Added attempt at workaround for VC++ const graph type bug [SVN r80908] --- include/boost/graph/named_function_params.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/boost/graph/named_function_params.hpp b/include/boost/graph/named_function_params.hpp index 94314a692..2bc53a61f 100644 --- a/include/boost/graph/named_function_params.hpp +++ b/include/boost/graph/named_function_params.hpp @@ -278,7 +278,7 @@ BOOST_BGL_DECLARE_NAMED_PARAMS template <> struct choose_impl_helper { template - static typename property_map::const_type + static typename property_map::type, PropertyTag>::const_type f(boost::mpl::true_, const Graph& g, const Param&, PropertyTag tag) { return get(tag, g); } From 8c4d0b33cda288820f9c1cb0ac8c523e475f5bad Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Wed, 10 Oct 2012 17:27:44 +0000 Subject: [PATCH 225/333] Added another remove_const to work around VC++ 9 issues [SVN r80939] --- include/boost/graph/named_function_params.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/boost/graph/named_function_params.hpp b/include/boost/graph/named_function_params.hpp index 2bc53a61f..3dd1a1367 100644 --- a/include/boost/graph/named_function_params.hpp +++ b/include/boost/graph/named_function_params.hpp @@ -284,7 +284,7 @@ BOOST_BGL_DECLARE_NAMED_PARAMS } template - static typename property_map::type + static typename property_map::type, PropertyTag>::type f(boost::mpl::false_, Graph& g, const Param&, PropertyTag tag) { return get(tag, g); } From b4e1fe7a66ee624332562c56065b3858312d2884 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Thu, 11 Oct 2012 16:45:33 +0000 Subject: [PATCH 226/333] Added test from Juergen Hunold [SVN r80957] --- test/Jamfile.v2 | 1 + test/filtered_graph_properties_dijkstra.cpp | 111 ++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 test/filtered_graph_properties_dijkstra.cpp diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index a2612d885..32eec8fed 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -124,6 +124,7 @@ test-suite graph_test : [ run random_spanning_tree_test.cpp ../build//boost_graph ] [ run graphml_test.cpp ../build//boost_graph : : "graphml_test.xml" ] [ run stoer_wagner_test.cpp ../../test/build//boost_unit_test_framework/static : $(TEST_DIR) ] + [ compile filtered_graph_properties_dijkstra.cpp ] ; # Run SDB tests only when -sSDB= is set. diff --git a/test/filtered_graph_properties_dijkstra.cpp b/test/filtered_graph_properties_dijkstra.cpp new file mode 100644 index 000000000..54b8c4cbd --- /dev/null +++ b/test/filtered_graph_properties_dijkstra.cpp @@ -0,0 +1,111 @@ +// (c) Copyright Juergen Hunold 2012 +// Use, modification and distribution is subject to 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) + +#include +#include +#include + +namespace boost { + + enum edge_info_t { edge_info = 114 }; + + BOOST_INSTALL_PROPERTY( edge, info ); +} + +template< typename EdgeInfo, + typename Directed > +class Graph +{ +public: + typedef boost::property< boost::edge_info_t, EdgeInfo > tEdge_property; + + typedef boost::adjacency_list< boost::setS, + boost::vecS, + Directed, + boost::no_property, + tEdge_property > tGraph; + + typedef typename boost::graph_traits< tGraph >::vertex_descriptor tNode; + typedef typename boost::graph_traits< tGraph >::edge_descriptor tEdge; + +protected: + + tGraph m_Graph; +}; + +class DataEdge; + +class UndirectedGraph + : public Graph< DataEdge*, + boost::undirectedS > +{ +public: + + template< class Evaluator, class Filter > + void dijkstra( Evaluator const&, + Filter const& ) const; +}; + +template< typename Graph, typename Derived > +struct Evaluator : public boost::put_get_helper< int, Derived > +{ + typedef int value_type; + typedef typename Graph::tEdge key_type; + typedef int reference; + typedef boost::readable_property_map_tag category; + + explicit Evaluator( Graph const* pGraph ); +}; + + +template< typename Graph > +struct LengthEvaluator : public Evaluator< Graph, LengthEvaluator > +{ + explicit LengthEvaluator( Graph const* pGraph ); + + typedef typename Evaluator >::reference reference; + typedef typename Evaluator >::key_type key_type; + + virtual reference operator[] ( key_type const& edge ) const; +}; + +template< class Graph > +struct EdgeFilter +{ + typedef typename Graph::tEdge key_type; + + EdgeFilter(); + + explicit EdgeFilter( Graph const*); + + bool operator()( key_type const& ) const; + +private: + const Graph* m_pGraph; +}; + + +template< class Evaluator, class Filter > +void +UndirectedGraph::dijkstra( Evaluator const& rEvaluator, + Filter const& rFilter ) const +{ + tNode nodeSource = vertex(0, m_Graph); + + std::vector< tNode > predecessors( num_vertices(m_Graph) ); + + boost::filtered_graph< tGraph, Filter > filteredGraph( m_Graph, rFilter ); + + boost::dijkstra_shortest_paths( filteredGraph, + nodeSource, + boost::predecessor_map( &predecessors[0] ) + .weight_map( rEvaluator ) ); +} + +// explicit instantiation +template void UndirectedGraph::dijkstra( LengthEvaluator const&, + EdgeFilter const& ) const; + +int main(int, char**) {return 0;} // Tests above will fail to compile if anything is broken From 0a990db1c50575f0080a2f26b877434a198ad9b8 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Thu, 11 Oct 2012 20:09:23 +0000 Subject: [PATCH 227/333] Fixed for starting vertices other than 0; thanks to Morten Strandberg for the bug report [SVN r80961] --- include/boost/graph/metric_tsp_approx.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/boost/graph/metric_tsp_approx.hpp b/include/boost/graph/metric_tsp_approx.hpp index ff81b9f0d..dd0ff1d67 100644 --- a/include/boost/graph/metric_tsp_approx.hpp +++ b/include/boost/graph/metric_tsp_approx.hpp @@ -216,7 +216,7 @@ namespace boost // Create tour using a preorder traversal of the mst vector tour; PreorderTraverser tvis(tour); - traverse_tree(0, t, tvis); + traverse_tree(indexmap[start], t, tvis); pair g_verts(vertices(g)); for(PreorderTraverser::const_iterator curr(tvis.begin()); @@ -228,7 +228,7 @@ namespace boost } // Connect back to the start of the tour - vis.visit_vertex(*g_verts.first, g); + vis.visit_vertex(start, g); } // Default tsp tour visitor that puts the tour in an OutputIterator From 2275b3019bd05d48584d8a10ccbd9eeabb7e2dba Mon Sep 17 00:00:00 2001 From: Marshall Clow Date: Tue, 16 Oct 2012 03:35:39 +0000 Subject: [PATCH 228/333] Fix typo; Refs #7511 [SVN r80997] --- include/boost/graph/is_kuratowski_subgraph.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/boost/graph/is_kuratowski_subgraph.hpp b/include/boost/graph/is_kuratowski_subgraph.hpp index 1dd314d31..d0a2aede9 100644 --- a/include/boost/graph/is_kuratowski_subgraph.hpp +++ b/include/boost/graph/is_kuratowski_subgraph.hpp @@ -175,7 +175,7 @@ namespace boost while (neighbors[v].size() > 0 && neighbors[v].size() < max_size) { - // Find one of v's neighbors u such that that v and u + // Find one of v's neighbors u such that v and u // have no neighbors in common. We'll look for such a // neighbor with a naive cubic-time algorithm since the // max size of any of the neighbor sets we'll consider From 0df58240042d020b8acd6aaafbf6a468c39ba5ef Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Mon, 22 Oct 2012 20:12:34 +0000 Subject: [PATCH 229/333] Trying to fix issue reported by Jan Hudec [SVN r81049] --- .../graph/dijkstra_shortest_paths_no_color_map.hpp | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/include/boost/graph/dijkstra_shortest_paths_no_color_map.hpp b/include/boost/graph/dijkstra_shortest_paths_no_color_map.hpp index ca2a1ebd8..c5ce6b6d4 100644 --- a/include/boost/graph/dijkstra_shortest_paths_no_color_map.hpp +++ b/include/boost/graph/dijkstra_shortest_paths_no_color_map.hpp @@ -113,16 +113,17 @@ namespace boost { distance_weight_combine, distance_compare); if (was_edge_relaxed) { - vertex_queue.update(neighbor_vertex); visitor.edge_relaxed(current_edge, graph); + if (is_neighbor_undiscovered) { + visitor.discover_vertex(neighbor_vertex, graph); + vertex_queue.push(neighbor_vertex); + } else { + vertex_queue.update(neighbor_vertex); + } } else { visitor.edge_not_relaxed(current_edge, graph); } - if (is_neighbor_undiscovered) { - visitor.discover_vertex(neighbor_vertex, graph); - vertex_queue.push(neighbor_vertex); - } } // end out edge iteration visitor.finish_vertex(min_vertex, graph); From f95e102060d847ef38aa3bb7da7187c5ed530560 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Mon, 29 Oct 2012 18:16:22 +0000 Subject: [PATCH 230/333] Applied patch from #7600; fixes #7600 [SVN r81099] --- include/boost/graph/named_graph.hpp | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/include/boost/graph/named_graph.hpp b/include/boost/graph/named_graph.hpp index 77e1a22f6..1150e4363 100644 --- a/include/boost/graph/named_graph.hpp +++ b/include/boost/graph/named_graph.hpp @@ -11,6 +11,7 @@ #define BOOST_GRAPH_NAMED_GRAPH_HPP #include +#include #include #include #include @@ -18,6 +19,7 @@ #include #include #include +#include #include // for std::runtime_error namespace boost { namespace graph { @@ -352,8 +354,15 @@ find_vertex(typename BGL_NAMED_GRAPH::vertex_name_type const& name, /// Retrieve the vertex associated with the given name, or add a new /// vertex with that name if no such vertex is available. +/// Note: This is enabled only when the vertex property type is different +/// from the vertex name to avoid ambiguous overload problems with +/// the add_vertex() function that takes a vertex property. template -Vertex + typename disable_if, +Vertex>::type add_vertex(typename BGL_NAMED_GRAPH::vertex_name_type const& name, BGL_NAMED_GRAPH& g) { From 1bb17dab63777136eb503b4f6c8ca104fa9e78a3 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Tue, 6 Nov 2012 13:23:03 +0000 Subject: [PATCH 231/333] Applied patch from #7648; fixes #7648 [SVN r81218] --- include/boost/graph/detail/labeled_graph_traits.hpp | 4 ++-- include/boost/graph/labeled_graph.hpp | 10 +++++----- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/include/boost/graph/detail/labeled_graph_traits.hpp b/include/boost/graph/detail/labeled_graph_traits.hpp index 6eb106093..a0c0973f9 100644 --- a/include/boost/graph/detail/labeled_graph_traits.hpp +++ b/include/boost/graph/detail/labeled_graph_traits.hpp @@ -218,9 +218,9 @@ namespace graph_detail { #define LABELED_GRAPH_PARAMS typename G, typename L, typename S #define LABELED_GRAPH labeled_graph -// Specialize mutability traits for for the labeled graph. +// Specialize mutability traits for the labeled graph. // This specialization depends on the mutability of the underlying graph type. -// If the underlying graph is fully mutable, this this is also fully mutable. +// If the underlying graph is fully mutable, this is also fully mutable. // Otherwise, it's different. template struct graph_mutability_traits< LABELED_GRAPH > { diff --git a/include/boost/graph/labeled_graph.hpp b/include/boost/graph/labeled_graph.hpp index 9c06f8fcf..2ff7830e3 100644 --- a/include/boost/graph/labeled_graph.hpp +++ b/include/boost/graph/labeled_graph.hpp @@ -21,7 +21,7 @@ #include // This file implements a utility for creating mappings from arbitrary -// identifers to the vertices of a graph. +// identifiers to the vertices of a graph. namespace boost { @@ -104,7 +104,7 @@ namespace graph_detail { // Tag dispatch on random access containers (i.e., vectors). This function // basically requires a) that Container is vector

      @@ -125,7 +175,8 @@

      the entire graph. Implicit searches can be performed with this implementation of A* by creating special visitors that generate neighbors of newly-expanded vertices. Please note that -astar_search_no_init() must be used for implicit graphs; the basic +astar_search_no_init() or astar_search_no_init_tree() must be +used for implicit graphs; the basic astar_search() function requires a graph that models the Vertex List Graph concept. Both versions @@ -134,8 +185,9 @@

      -This implementation of A* is based on an OPEN/CLOSED list formulation -of the algorithm. Vertices on the OPEN list have been ``discovered'' +For the non-tree versions of the algorithm, +this implementation of A* is based on an OPEN/CLOSED list formulation. +Vertices on the OPEN list have been ``discovered'' by the algorithm, but not ``expanded'' (we have not discovered their adjacent vertices). Vertices on the CLOSED list have been completely examined by our search (we have expanded them and added their children @@ -146,7 +198,11 @@

      trapped by loops in the graph. The OPEN/CLOSED lists are implemented using BGL's vertex coloring mechanisms. Vertices in OPEN are colored gray, vertices in CLOSED are colored black, and undiscovered vertices -are colored white. +are colored white. For the versions of the algorithm whose names end in +_tree, all vertices are assumed to always be white, leading to +checking for repeated vertices being done using the distance map. If a dummy +value is used for the distance map and the graph contains cycles, the algorithm +will probably enter an infinite loop.

      @@ -292,7 +348,8 @@

      Named Parameters

      IN: vertex_index_map(VertexIndexMap i_map)
      This maps each vertex to an integer in the range [0, - num_vertices(g)). This is necessary for efficient updates of + num_vertices(g)). This is necessary in non-tree versions of the + algorithm for efficient updates of the heap data structure when an edge is relaxed. The type VertexIndexMap must be a model of Readable @@ -338,7 +395,10 @@

      Named Parameters

      combine function object and the zero object for the identity element. Also the distance value type must have a
      StrictWeakOrdering - provided by the compare function object.
      + provided by the compare function object. A + constant_writable_property_map returning the infinity value can be + used for this parameter in tree versions of the algorithm when the graph does + not contain a directed cycle.
      Default: shared_array_property_map with the same value type as the @@ -355,7 +415,10 @@

      Named Parameters

      h) from the vertex to a goal. The type CostMap must be a model of Read/Write - Property Map. The vertex descriptor type of the graph + Property Map
      in non-tree versions of the algorithm, and Writable Property + Map in tree versions of the algorithm. The vertex descriptor type + of the graph needs to be usable as the key type of the distance map. The value type of the distance map is the element type of a Monoid formed with the @@ -364,7 +427,8 @@

      Named Parameters

      href="http://www.sgi.com/tech/stl/StrictWeakOrdering.html">StrictWeakOrdering provided by the compare function object. The value type for this map must be the same as the value type for the distance - map.
      + map. In tree versions of the algorithm, null_property_map can be + used for this parameter.
      Default: shared_array_property_map with the same value type as the @@ -375,7 +439,8 @@

      Named Parameters

      UTIL/OUT: color_map(ColorMap c_map)
      - This is used during the execution of the algorithm to mark the + This is used during the execution of non-tree versions of the algorithm to + mark the vertices, indicating whether they are on the OPEN or CLOSED lists. The vertices start out white and become gray when they are inserted into the OPEN list. They then turn black when they are examined and diff --git a/example/astar-cities.cpp b/example/astar-cities.cpp index d5affd110..c594afa7d 100644 --- a/example/astar-cities.cpp +++ b/example/astar-cities.cpp @@ -192,7 +192,7 @@ int main(int argc, char **argv) vector d(num_vertices(g)); try { // call astar named parameter interface - astar_search + astar_search_tree (g, start, distance_heuristic (locations, goal), diff --git a/include/boost/graph/astar_search.hpp b/include/boost/graph/astar_search.hpp index 38224a982..855a7e5f6 100644 --- a/include/boost/graph/astar_search.hpp +++ b/include/boost/graph/astar_search.hpp @@ -22,9 +22,12 @@ #include #include #include +#include #include +#include #include #include +#include #include namespace boost { @@ -159,8 +162,9 @@ namespace boost { template void tree_edge(Edge e, const Graph& g) { using boost::get; - m_decreased = relax(e, g, m_weight, m_predecessor, m_distance, - m_combine, m_compare); + bool m_decreased = + relax(e, g, m_weight, m_predecessor, m_distance, + m_combine, m_compare); if(m_decreased) { m_vis.edge_relaxed(e, g); @@ -175,8 +179,9 @@ namespace boost { template void gray_target(Edge e, const Graph& g) { using boost::get; - m_decreased = relax(e, g, m_weight, m_predecessor, m_distance, - m_combine, m_compare); + bool m_decreased = + relax(e, g, m_weight, m_predecessor, m_distance, + m_combine, m_compare); if(m_decreased) { put(m_cost, target(e, g), @@ -192,8 +197,9 @@ namespace boost { template void black_target(Edge e, const Graph& g) { using boost::get; - m_decreased = relax(e, g, m_weight, m_predecessor, m_distance, - m_combine, m_compare); + bool m_decreased = + relax(e, g, m_weight, m_predecessor, m_distance, + m_combine, m_compare); if(m_decreased) { m_vis.edge_relaxed(e, g); @@ -219,11 +225,112 @@ namespace boost { ColorMap m_color; BinaryFunction m_combine; BinaryPredicate m_compare; - bool m_decreased; C m_zero; }; + template + struct astar_tree_bfs_visitor + { + + typedef typename property_traits::value_type C; + typedef typename property_traits::value_type distance_type; + + astar_tree_bfs_visitor(AStarHeuristic h, UniformCostVisitor vis, + UpdatableQueue& Q, PredecessorMap p, + CostMap c, DistanceMap d, WeightMap w, + BinaryFunction combine, + BinaryPredicate compare, C zero) + : m_h(h), m_vis(vis), m_Q(Q), m_predecessor(p), m_cost(c), + m_distance(d), m_weight(w), + m_combine(combine), m_compare(compare), m_zero(zero) {} + + + template + void initialize_vertex(Vertex u, const Graph& g) { + m_vis.initialize_vertex(u, g); + } + template + void discover_vertex(Vertex u, const Graph& g) { + m_vis.discover_vertex(u, g); + } + template + void examine_vertex(Vertex u, const Graph& g) { + m_vis.examine_vertex(u, g); + } + template + void finish_vertex(Vertex u, const Graph& g) { + m_vis.finish_vertex(u, g); + } + template + void examine_edge(Edge e, const Graph& g) { + if (m_compare(get(m_weight, e), m_zero)) + BOOST_THROW_EXCEPTION(negative_edge()); + m_vis.examine_edge(e, g); + } + template + void non_tree_edge(Edge, const Graph&) {} + + + + template + void tree_edge(Edge e, const Graph& g) { + using boost::get; + bool m_decreased = + relax(e, g, m_weight, m_predecessor, m_distance, m_combine, m_compare); + + if(m_decreased) { + m_vis.edge_relaxed(e, g); + put(m_cost, target(e, g), + m_combine(get(m_distance, target(e, g)), + m_h(target(e, g)))); + } else + m_vis.edge_not_relaxed(e, g); + } + + + template + void gray_target(Edge e, const Graph& g) { + abort(); // Should not get here in tree case + } + + + template + void black_target(Edge e, const Graph& g) { + abort(); // Should not get here in tree case + } + + + + AStarHeuristic m_h; + UniformCostVisitor m_vis; + UpdatableQueue& m_Q; + PredecessorMap m_predecessor; + CostMap m_cost; + DistanceMap m_distance; + WeightMap m_weight; + BinaryFunction m_combine; + BinaryPredicate m_compare; + C m_zero; + + }; + + template + struct astar_search_tree_queue_wrapper: public UnderlyingQ { + astar_search_tree_queue_wrapper(const UnderlyingQ& uq, CostMap cost): UnderlyingQ(uq), m_cost(cost) {} + + typedef typename boost::property_traits::key_type key_type; + void push(const key_type& k) {UnderlyingQ::push(std::make_pair(k, get(m_cost, k)));} + key_type top() const {return UnderlyingQ::top().first;} + + private: + CostMap m_cost; + }; + } // namespace detail @@ -263,6 +370,77 @@ namespace boost { breadth_first_visit(g, s, Q, bfs_vis, color); } + namespace graph_detail { + template + struct select1st { + typedef std::pair argument_type; + typedef A result_type; + A operator()(const std::pair& p) const {return p.first;} + }; + } + + template + inline void + astar_search_no_init_tree + (const VertexListGraph &g, + typename graph_traits::vertex_descriptor s, + AStarHeuristic h, AStarVisitor vis, + PredecessorMap predecessor, CostMap cost, + DistanceMap distance, WeightMap weight, + CompareFunction compare, CombineFunction combine, + CostInf /*inf*/, CostZero zero) + { + typedef typename graph_traits::vertex_descriptor + Vertex; + typedef typename property_traits::value_type Distance; + typedef d_ary_heap_indirect< + std::pair, + 4, + null_property_map, std::size_t>, + function_property_map, std::pair >, + CompareFunction> + MutableQueue; + MutableQueue Q( + make_function_property_map >(graph_detail::select1st()), + null_property_map, std::size_t>(), + compare); + + vis.discover_vertex(s, g); + Q.push(std::make_pair(get(cost, s), s)); + while (!Q.empty()) { + Vertex v; + Distance v_rank; + boost::tie(v_rank, v) = Q.top(); + Q.pop(); + vis.examine_vertex(v, g); + BGL_FORALL_OUTEDGES_T(v, e, g, VertexListGraph) { + Vertex w = target(e, g); + vis.examine_edge(e, g); + Distance e_weight = get(weight, e); + if (compare(e_weight, zero)) + BOOST_THROW_EXCEPTION(negative_edge()); + bool decreased = + relax(e, g, weight, predecessor, distance, + combine, compare); + Distance w_d = combine(get(distance, v), e_weight); + if (decreased) { + vis.edge_relaxed(e, g); + Distance w_rank = combine(get(distance, w), h(w)); + put(cost, w, w_rank); + vis.discover_vertex(w, g); + Q.push(std::make_pair(w_rank, w)); + } else { + vis.edge_not_relaxed(e, g); + } + } + vis.finish_vertex(v, g); + } + } // Non-named parameter interface template + inline void + astar_search_tree + (const VertexListGraph &g, + typename graph_traits::vertex_descriptor s, + AStarHeuristic h, AStarVisitor vis, + PredecessorMap predecessor, CostMap cost, + DistanceMap distance, WeightMap weight, + CompareFunction compare, CombineFunction combine, + CostInf inf, CostZero zero) + { + + typename graph_traits::vertex_iterator ui, ui_end; + for (boost::tie(ui, ui_end) = vertices(g); ui != ui_end; ++ui) { + put(distance, *ui, inf); + put(cost, *ui, inf); + put(predecessor, *ui, *ui); + vis.initialize_vertex(*ui, g); + } + put(distance, s, zero); + put(cost, s, h(s)); + + astar_search_no_init_tree + (g, s, h, vis, predecessor, cost, distance, weight, + compare, combine, inf, zero); + + } + // Named parameter interfaces template + void + astar_search_tree + (const VertexListGraph &g, + typename graph_traits::vertex_descriptor s, + AStarHeuristic h, const bgl_named_params& params) + { + using namespace boost::graph::keywords; + typedef bgl_named_params params_type; + BOOST_GRAPH_DECLARE_CONVERTED_PARAMETERS(params_type, params) + + // Distance type is the value type of the distance map if there is one, + // otherwise the value type of the weight map. + typedef + typename detail::override_const_property_result< + arg_pack_type, tag::weight_map, edge_weight_t, VertexListGraph>::type + weight_map_type; + typedef typename boost::property_traits::value_type W; + typedef + typename detail::map_maker::map_type + distance_map_type; + typedef typename boost::property_traits::value_type D; + const D inf = arg_pack[_distance_inf | (std::numeric_limits::max)()]; + + astar_search_tree + (g, s, h, + arg_pack[_visitor | make_astar_visitor(null_visitor())], + arg_pack[_predecessor_map | dummy_property_map()], + detail::make_property_map_from_arg_pack_gen(D())(g, arg_pack), + detail::make_property_map_from_arg_pack_gen(W())(g, arg_pack), + detail::override_const_property(arg_pack, _weight_map, g, edge_weight), + arg_pack[_distance_compare | std::less()], + arg_pack[_distance_combine | closed_plus(inf)], + inf, + arg_pack[_distance_zero | D()]); + } + template @@ -378,6 +630,37 @@ namespace boost { arg_pack[_distance_zero | D()]); } + template + void + astar_search_no_init_tree + (const VertexListGraph &g, + typename graph_traits::vertex_descriptor s, + AStarHeuristic h, const bgl_named_params& params) + { + using namespace boost::graph::keywords; + typedef bgl_named_params params_type; + BOOST_GRAPH_DECLARE_CONVERTED_PARAMETERS(params_type, params) + typedef + typename detail::override_const_property_result< + arg_pack_type, tag::weight_map, edge_weight_t, VertexListGraph>::type + weight_map_type; + typedef typename boost::property_traits::value_type D; + const D inf = arg_pack[_distance_inf | (std::numeric_limits::max)()]; + astar_search_no_init_tree + (g, s, h, + arg_pack[_visitor | make_astar_visitor(null_visitor())], + arg_pack[_predecessor_map | dummy_property_map()], + detail::make_property_map_from_arg_pack_gen(D())(g, arg_pack), + detail::make_property_map_from_arg_pack_gen(D())(g, arg_pack), + detail::override_const_property(arg_pack, _weight_map, g, edge_weight), + arg_pack[_distance_compare | std::less()], + arg_pack[_distance_combine | closed_plus(inf)], + inf, + arg_pack[_distance_zero | D()]); + } + } // namespace boost #endif // BOOST_GRAPH_ASTAR_SEARCH_HPP From 56223ce7b0355d492ed09f7bb681c4a53f017a9b Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Tue, 27 Nov 2012 22:14:29 +0000 Subject: [PATCH 240/333] Added name A* for astar_search [SVN r81601] --- doc/table_of_contents.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/table_of_contents.html b/doc/table_of_contents.html index 90f2b7546..db17b2ae3 100644 --- a/doc/table_of_contents.html +++ b/doc/table_of_contents.html @@ -172,7 +172,7 @@

      Table of Contents: the Boost Graph Library href="./johnson_all_pairs_shortest.html">johnson_all_pairs_shortest_paths
    5. floyd_warshall_all_pairs_shortest_paths
    6. r_c_shortest_paths - resource-constrained shortest paths
    7. -
    8. astar_search
    9. +
    10. astar_search (A* search algorithm)
  • Minimum Spanning Tree Algorithms
      From 1a9533422df16897f44fba1cda75c6292e6ee70f Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Tue, 27 Nov 2012 22:17:25 +0000 Subject: [PATCH 241/333] Fixed template parameter names; fixes #4386 [SVN r81602] --- doc/astar_search.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/astar_search.html b/doc/astar_search.html index 161c93b00..e1828ff5f 100644 --- a/doc/astar_search.html +++ b/doc/astar_search.html @@ -37,7 +37,7 @@

      typename P, typename T, typename R> void astar_search_no_init - (const VertexListGraph &g, + (const IncidenceGraph &g, typename graph_traits<VertexListGraph>::vertex_descriptor s, AStarHeuristic h, const bgl_named_params<P, T, R>& params); @@ -55,7 +55,7 @@

      typename P, typename T, typename R> void astar_search_no_init_tree - (const VertexListGraph &g, + (const IncidenceGraph &g, typename graph_traits<VertexListGraph>::vertex_descriptor s, AStarHeuristic h, const bgl_named_params<P, T, R>& params); From 6aed0a5a45ef6723ec878ddb0e9dad738b08b4ba Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Tue, 27 Nov 2012 22:25:50 +0000 Subject: [PATCH 242/333] Removed unused code [SVN r81603] --- include/boost/graph/astar_search.hpp | 102 --------------------------- 1 file changed, 102 deletions(-) diff --git a/include/boost/graph/astar_search.hpp b/include/boost/graph/astar_search.hpp index 855a7e5f6..7d6da7c3c 100644 --- a/include/boost/graph/astar_search.hpp +++ b/include/boost/graph/astar_search.hpp @@ -229,108 +229,6 @@ namespace boost { }; - template - struct astar_tree_bfs_visitor - { - - typedef typename property_traits::value_type C; - typedef typename property_traits::value_type distance_type; - - astar_tree_bfs_visitor(AStarHeuristic h, UniformCostVisitor vis, - UpdatableQueue& Q, PredecessorMap p, - CostMap c, DistanceMap d, WeightMap w, - BinaryFunction combine, - BinaryPredicate compare, C zero) - : m_h(h), m_vis(vis), m_Q(Q), m_predecessor(p), m_cost(c), - m_distance(d), m_weight(w), - m_combine(combine), m_compare(compare), m_zero(zero) {} - - - template - void initialize_vertex(Vertex u, const Graph& g) { - m_vis.initialize_vertex(u, g); - } - template - void discover_vertex(Vertex u, const Graph& g) { - m_vis.discover_vertex(u, g); - } - template - void examine_vertex(Vertex u, const Graph& g) { - m_vis.examine_vertex(u, g); - } - template - void finish_vertex(Vertex u, const Graph& g) { - m_vis.finish_vertex(u, g); - } - template - void examine_edge(Edge e, const Graph& g) { - if (m_compare(get(m_weight, e), m_zero)) - BOOST_THROW_EXCEPTION(negative_edge()); - m_vis.examine_edge(e, g); - } - template - void non_tree_edge(Edge, const Graph&) {} - - - - template - void tree_edge(Edge e, const Graph& g) { - using boost::get; - bool m_decreased = - relax(e, g, m_weight, m_predecessor, m_distance, m_combine, m_compare); - - if(m_decreased) { - m_vis.edge_relaxed(e, g); - put(m_cost, target(e, g), - m_combine(get(m_distance, target(e, g)), - m_h(target(e, g)))); - } else - m_vis.edge_not_relaxed(e, g); - } - - - template - void gray_target(Edge e, const Graph& g) { - abort(); // Should not get here in tree case - } - - - template - void black_target(Edge e, const Graph& g) { - abort(); // Should not get here in tree case - } - - - - AStarHeuristic m_h; - UniformCostVisitor m_vis; - UpdatableQueue& m_Q; - PredecessorMap m_predecessor; - CostMap m_cost; - DistanceMap m_distance; - WeightMap m_weight; - BinaryFunction m_combine; - BinaryPredicate m_compare; - C m_zero; - - }; - - template - struct astar_search_tree_queue_wrapper: public UnderlyingQ { - astar_search_tree_queue_wrapper(const UnderlyingQ& uq, CostMap cost): UnderlyingQ(uq), m_cost(cost) {} - - typedef typename boost::property_traits::key_type key_type; - void push(const key_type& k) {UnderlyingQ::push(std::make_pair(k, get(m_cost, k)));} - key_type top() const {return UnderlyingQ::top().first;} - - private: - CostMap m_cost; - }; - } // namespace detail From fd7f84560b6384453f86dbf905f17aa67634e737 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Wed, 5 Dec 2012 19:26:38 +0000 Subject: [PATCH 243/333] Changed to BOOST_ASSERT [SVN r81724] --- include/boost/graph/detail/d_ary_heap.hpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/include/boost/graph/detail/d_ary_heap.hpp b/include/boost/graph/detail/d_ary_heap.hpp index d9f9ae052..cf930fc18 100644 --- a/include/boost/graph/detail/d_ary_heap.hpp +++ b/include/boost/graph/detail/d_ary_heap.hpp @@ -126,17 +126,17 @@ namespace boost { } Value& top() { - assert (!this->empty()); + BOOST_ASSERT (!this->empty()); return data[0]; } const Value& top() const { - assert (!this->empty()); + BOOST_ASSERT (!this->empty()); return data[0]; } void pop() { - assert (!this->empty()); + BOOST_ASSERT (!this->empty()); put(index_in_heap, data[0], (size_type)(-1)); if (data.size() != 1) { data[0] = data.back(); From 0c2db206d3a49e0c18775f5c5b36c56bfcfd751f Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Wed, 5 Dec 2012 19:28:12 +0000 Subject: [PATCH 244/333] Added VF2 subgraph isomorphism algorithm from Flavio De Lorenzi and Vomel Christof [SVN r81725] --- doc/table_of_contents.html | 1 + doc/vf2_sub_graph_iso.html | 547 +++++++++ doc/vf2_sub_graph_iso_impl.pdf | Bin 0 -> 123602 bytes doc/vf2_sub_graph_iso_impl.tex | 474 ++++++++ example/Jamfile.v2 | 7 + example/vf2_random_graphs.sce | 96 ++ example/vf2_sub_graph_iso_csr_example.cpp | 45 + example/vf2_sub_graph_iso_example.cpp | 39 + example/vf2_sub_graph_iso_grd_example.cpp | 36 + example/vf2_sub_graph_iso_gviz_example.cpp | 143 +++ example/vf2_sub_graph_iso_multi_example.cpp | 145 +++ example/vf2_sub_graph_iso_undir_example.cpp | 73 ++ include/boost/graph/vf2_sub_graph_iso.hpp | 1182 +++++++++++++++++++ 13 files changed, 2788 insertions(+) create mode 100755 doc/vf2_sub_graph_iso.html create mode 100755 doc/vf2_sub_graph_iso_impl.pdf create mode 100755 doc/vf2_sub_graph_iso_impl.tex create mode 100755 example/vf2_random_graphs.sce create mode 100755 example/vf2_sub_graph_iso_csr_example.cpp create mode 100755 example/vf2_sub_graph_iso_example.cpp create mode 100755 example/vf2_sub_graph_iso_grd_example.cpp create mode 100755 example/vf2_sub_graph_iso_gviz_example.cpp create mode 100755 example/vf2_sub_graph_iso_multi_example.cpp create mode 100755 example/vf2_sub_graph_iso_undir_example.cpp create mode 100755 include/boost/graph/vf2_sub_graph_iso.hpp diff --git a/doc/table_of_contents.html b/doc/table_of_contents.html index db17b2ae3..3bf185239 100644 --- a/doc/table_of_contents.html +++ b/doc/table_of_contents.html @@ -240,6 +240,7 @@

      Table of Contents: the Boost Graph Library
    1. Graph Structure Comparisons
      1. isomorphism +
      2. vf2_sub_graph_iso (VF2 subgraph isomorphism algorithm)
      3. mcgregor_common_subgraphs
      diff --git a/doc/vf2_sub_graph_iso.html b/doc/vf2_sub_graph_iso.html new file mode 100755 index 000000000..5e90424f4 --- /dev/null +++ b/doc/vf2_sub_graph_iso.html @@ -0,0 +1,547 @@ + + + + + Boost Graph Library: VF2 (Sub)Graph Isomorphism + + + + C++ Boost +
      +

      + vf2_sub_graph_iso +

      +
      +// all defaults interface
      +template <typename GraphSmall,
      +          typename GraphLarge,
      +          typename SubGraphIsoMapCallBack>
      +bool vf2_sub_graph_iso(const GraphSmall& graph_small,
      +                       const GraphLarge& graph_large, 
      +                       SubGraphIsoMapCallBack user_callback)
      +
      +
      +// named parameter version
      +template <typename GraphSmall,
      +          typename GraphLarge,
      +          typename VertexOrderSmall,
      +          typename SubGraphIsoMapCallBack,
      +          typename Param,
      +          typename Tag,
      +          typename Rest>
      +bool vf2_sub_graph_iso(const GraphSmall& graph_small,
      +                       const GraphLarge& graph_large,
      +                       SubGraphIsoMapCallBack user_callback,
      +                       const VertexOrderSmall& vertex_order_small,
      +                       const bgl_named_params<Param, Tag, Rest>& params)
      +
      +
      +// non-named parameter version
      +template <typename GraphSmall,
      +          typename GraphLarge,
      +          typename IndexMapSmall,
      +          typename IndexMapLarge,
      +          typename VertexOrderSmall,
      +          typename EdgeCompatibilityPredicate,
      +          typename VertexCompatibilityPredicate,
      +          typename SubGraphIsoMapCallBack>
      +bool vf2_sub_graph_iso(const GraphSmall& graph_small,
      +                       const GraphLarge& graph_large,
      +                       SubGraphIsoMapCallBack user_callback,
      +                       IndexMapSmall index_map_small,
      +                       IndexMapLarge index_map_large, 
      +                       const VertexOrderSmall& vertex_order_small,
      +                       EdgeCompatibilityPredicate edge_comp,
      +                       VertexCompatibilityPredicate vertex_comp)
      +    
      +

      + An isomorphism between two graphs G1=(V1, E1) + and G2=(V2, E2) is a + bijective mapping M of the vertices of one graph to vertices of the other + graph that preserves the edge structure of the graphs. M is said to be a + graph-subgraph isomorphism iff M is an isomorphism between + G1 and a subgraph of G2. +

      + +

      + This function finds all graph-subgraph isomorphism mappings between + graphs graph_small and graph_large and outputs them to + user_callback. It continues until user_callback + returns true or the search space has been fully explored. + EdgeCompatibilityPredicate and + VertexCompatibilityPredicate predicates are used to test whether + edges and vertices are compatible. To use property maps for equivalence, + look at the + make_property_map_compatible + function. By default always_compatible is used, which returns + true for any pair of vertices or edges. +

      +

      + The current implementation is based on the VF2 algorithm, + introduced by Cordella et al. An in-depth description of the algorithm is + given in [1] and [2] + and references therein. In brief, the process of finding a mapping between + the two graphs G1 and G2 determines + the isomorphism mapping M, which associates vertices + G1 with vertices of G2 and vice + versa. It can be described by means of a state space representation, which + is explored by the algorithm according to a depth-first strategy. Each + state s of the matching process can be associated with a partial + mapping M(s). At each level, the algorithm computes the set of + the vertex pairs that are candidates to be added to the current state + s. If a pair of vertices (v, w) is feasible, the mapping + is extended and the associated successor state s' is computed. + The whole procedure is then repeated for state s'. A somewhat more + detailed description of the current implementation is given in the file + vf2_sub_graph_iso_impl.pdf. +

      + +

      Where Defined

      + boost/graph/vf2_sub_graph_iso.hpp +

      + All functions are defined in the boost namespace. +

      + +

      Parameters

      + + IN: const GraphSmall& graph_small +
      + The (first) smaller graph (fewer vertices) of the pair to be tested for + isomorphism. The type GraphSmall must be a + model of + Vertex List Graph + Edge List Graph, + Bidirectional Graph and + Adjacency Matrix. +
      + + IN: const GraphLarge& graph_large +
      + The (second) larger graph to be tested. + Type GraphLarge must be a model of + Vertex List Graph + Edge List Graph, + Bidirectional Graph and + Adjacency Matrix. +
      + + OUT: SubGraphIsoMapCallBack user_callback +
      + A function object to be called when a graph-subgraph isomorphism has been discovered. The + operator() must have following form: +
      +template <typename CorrespondenceMap1To2,
      +          typename CorrespondenceMap2To1>
      +bool operator()(CorrespondenceMap1To2 f, CorrespondenceMap2To1 g) const
      +      
      + Both the CorrespondenceMap1To2 + and CorresondenceMap2To1 types are models + of Readable + Property Map and map equivalent vertices across the two + graphs given to vf2_sub_graph_iso (or vf2_graph_iso. For + instance, if v is + from graph_small, w is from graph_large, + and the vertices can be considered equivalent, + then get(f, v) will be w and get(g, w) + will be v. If any vertex, say v in graph_small, + does not match a vertex in graph_large , + then get(f, v) will be graph_traits<GraphLarge>::null_vertex(). + Likewise for any un-matched vertices from graph_large, + get(g, w) will be graph_traits<GraphSmall>::null_vertex(). + + Returning false from the callback will abort the search immediately. Otherwise, + the entire search space will be explored. A "default" print callback + is provided as a utility function and another one is + given in Example 2. +
      + + IN: const VertexOrderSmall& vertex_order_small +
      + The ordered vertices of the smaller (first) graph graph_small. + During the matching process the vertices are examined in the order given by + vertex_order_small. Type VertexOrderSmall must be a model + of ContainerConcept + with value type + graph_traits<GraphSmall>::vertex_descriptor. +
      + Default The vertices are ordered by multiplicity of in/out degree. +
      + +

      Named Parameters

      + + IN: vertex_index1(IndexMapSmall index_map_small) +
      + This maps each vertex to an integer in the range [0, num_vertices(graph_small)). + Type IndexMapSmall must be a model of + Readable Property Map. +
      + Default: get(vertex_index, graph_small) +
      + + IN: vertex_index2(IndexMapLarge index_map_large) +
      + This maps each vertex to an integer in the range [0, num_vertices(graph_large)). + Type IndexMapLarge must be a model of + Readable Property Map. +
      + Default: get(vertex_index, graph_large) +
      + + IN: edges_equivalent(EdgeCompatibilityPredicate edge_comp) +
      + This function object is used to determine if edges between the two graphs + graph_small and graph_large are compatible. + Type EdgeCompatiblePredicate must be a model of + of Binary + Predicate and have argument types of + graph_traits<GraphSmall>::edge_descriptor and + graph_traits<GraphLarge>::edge_descriptor. A return value of true + indicates that the edges are compatible. +
      + Default: always_compatible +
      + + IN: vertices_equivalent(VertexCompatibilityPredicate vertex_comp) +
      + This function object is used to determine if vertices between the two graphs + graph_small and graph_large are compatible. + Type VertexCompatiblePredicate must be a model of + Binary Predicate + and have argument types of + graph_traits<GraphSmall>::vertex_descriptor and + graph_traits<GraphLarge>::vertex_descriptor. A return value of true + indicates that the vertices are compatible. +
      + Default: always_compatible +
      + +

      Related Functions

      +

      + Non-named parameter, named-parameter and all default parameter versions of + function +

      +
      +vf2_graph_iso(...)
      +    
      +

      + for isomorphism testing take the same parameters as the corresponding + functions vf2_sub_graph_iso for sub-graph isomorphism testing. + The algorithm finds all isomorphism mappings between graphs + graph1 and graph2 and outputs them to + user_callback. It continues until user_callback + returns true or the search space has been fully explored. As before, + EdgeCompatibilityPredicate and + VertexCompatibilityPredicate predicates are used to test + whether edges and vertices are compatible with + always_compatible as default. +

      + +

      Utility Functions and Structs

      +
      +template <typename PropertyMap1,
      +          typename PropertyMap2>
      +property_map_compatible<PropertyMap1, PropertyMap2>
      +make_property_map_compatible(const PropertyMap1 property_map1,
      +                             const PropertyMap2 property_map2) 
      +    
      +
      + Returns a binary predicate function object + (property_map_compatible<PropertyMap1, PropertyMap2>) that compares + vertices or edges between graphs using property maps. +
      + + struct always_compatible +
      + A binary function object that returns true for any pair of items. +
      + +
      +template <typename Graph1,
      +          typename Graph2>
      +struct vf2_print_callback
      +    
      +
      + Callback function object that prints out the correspondences between vertices + of Graph1 and Graph2. The constructor takes the two graphs G1 + and G2 and an optional bool parameter as arguments. If the latter is + set to true, the callback function will verify the mapping before outputting + it to standard output. +
      + +
      +// Variant of verify_sub_graph_iso with all default parameters
      +template<typename Graph1,
      +         typename Graph2,
      +         typename CorresponenceMap1To2>
      +inline bool verify_vf2_sub_graph_iso(const Graph1& graph1, const Graph2& graph2, 
      +                                     const CorresponenceMap1To2 f)
      +
      +
      +// Verifies a graph (sub)graph isomorphism map 
      +template<typename Graph1,
      +         typename Graph2,
      +         typename CorresponenceMap1To2,
      +         typename EdgeCompatibilityPredicate,
      +         typename VertexCompatibilityPredicate>
      +inline bool verify_vf2_sub_graph_iso(const Graph1& graph1, const Graph2& graph2, 
      +                                     const CorresponenceMap1To2 f,
      +                                     EdgeCompatibilityPredicate edge_comp, 
      +                                     VertexCompatibilityPredicate vertex_comp) 
      +    
      +
      +This function can be used to verify a (sub)graph isomorphism mapping f. The parameters are +akin to function vf2_sub_graph_iso (vf2_graph_iso). +
      + + +

      Complexity

      +

      + Spatial and time complexity are given in [2]. The spatial + complexity of VF2 is of order O(V), where V is the (maximum) number + of vertices of the two graphs. Time complexity is O(V2) in the best case and + O(V!·V) in the worst case. +

      + +

      Examples

      + +

      Example 1

      +

      + In the example below, a small graph graph1 and a larger graph + graph2 are defined. Here small and large refers to the number of + vertices of the graphs. vf2_sub_graph_iso computes all the + sub-graph isomorphism mappings between the two graphs and outputs them + via callback. +

      +
      +typedef adjacency_list<vecS, vecS, bidirectionalS> graph_type;
      +
      +// Build graph1
      +int num_vertices1 = 8; graph_type graph1(num_vertices1);
      +add_edge(0, 6, graph1); add_edge(0, 7, graph1);
      +add_edge(1, 5, graph1); add_edge(1, 7, graph1);
      +add_edge(2, 4, graph1); add_edge(2, 5, graph1); add_edge(2, 6, graph1);
      +add_edge(3, 4, graph1);
      +
      +// Build graph2
      +int num_vertices2 = 9; graph_type graph2(num_vertices2);
      +add_edge(0, 6, graph2); add_edge(0, 8, graph2);
      +add_edge(1, 5, graph2); add_edge(1, 7, graph2);
      +add_edge(2, 4, graph2); add_edge(2, 7, graph2); add_edge(2, 8, graph2);
      +add_edge(3, 4, graph2); add_edge(3, 5, graph2); add_edge(3, 6, graph2);
      +
      +// true instructs callback to verify a map using
      +// verify_vf2_sub_graph_iso
      +vf2_print_callback<graph_type, graph_type> callback(graph1, graph2, true);
      +
      +bool ret = vf2_sub_graph_iso(graph1, graph2, callback);
      +    
      +

      +The complete example can be found under +examples/vf2_sub_graph_iso_example.cpp. +
      +

      + + +

      Example 2

      + This example uses the GraphViz input parser, i.e. read_graphviz + function to interpret the two graphs specified in files graph_small.dot and graph_large.dot + using the using the GraphViz DOT language. Sample files are provided + below. vf2_sub_graph_iso computes all the sub-graph isomorphism mappings + between graph_small and graph_large. +
      +std::ifstream graph_small_file("graph_small.dot");
      +std::ifstream graph_large_file("graph_large.dot");
      +
      +// Vertex properties
      +typedef property <vertex_name_t, std::string> vertex_p;
      +
      +// adjacency_list-based type
      +typedef adjacency_list <vecS, vecS, undirectedS, vertex_p> graph_t;
      +
      +// Construct an empty graph_small and prepare the dynamic_property_maps.
      +graph_t graph_small(0);
      +dynamic_properties dp_small;
      +  
      +property_map<graph_t, vertex_name_t>::type name_small =
      +  get(vertex_name, graph_small);
      +dp_small.property("node_id", name_small);
      +
      +// Read graph_small
      +bool status = read_graphviz(graph_small_file, graph_small, dp_small, "node_id");
      +
      +// Construct an empty graph_large and prepare the dynamic_property_maps,
      +// following the read_graphviz example
      +graph_t graph_large(0);
      +dynamic_properties dp_large;
      +
      +property_map<graph_t, vertex_name_t>::type name_large =
      +  get(vertex_name, graph_large);
      +dp_large.property("node_id", name_large);
      +
      +// Read graph_large
      +status = read_graphviz(graph_large_file, graph_large, dp_large, "node_id");
      +
      +// Create the call_back function
      +typedef property_map<graph_t, vertex_name_t>::type p_map_t;
      +print_callback<graph_t, graph_t, p_map_t, p_map_t> callback(graph_small, graph_large,
      +                                                            name_small, name_large, true);
      + // Compute the sub-graph isomorphism mappings
      +bool ret = vf2_sub_graph_iso(graph_small, graph_large, callback);
      +    
      + + To output the mappings using the node names, the following callback function object is created: + +
      +// Define a print_callback
      +template <typename Graph1,
      +          typename Graph2,
      +          typename PropertyMap1,
      +          typename PropertyMap2>
      +struct print_callback {
      +    
      +  print_callback(const Graph1& graph1, const Graph2& graph2, 
      +                 PropertyMap1 p_map1, PropertyMap2 p_map2, 
      +                 bool verify = false) 
      +    : graph1_(graph1), graph2_(graph2), 
      +      p_map1_(p_map1), p_map2_(p_map2),
      +      verify_(verify) {}
      +
      +  template <typename CorrespondenceMap1To2,
      +            typename CorrespondenceMap2To1>
      +  bool operator()(CorrespondenceMap1To2 f, CorrespondenceMap2To1) const {
      +    
      +    if (verify_)
      +      std::cout << "Verify: " << std::boolalpha 
      +                << verify_vf2_sub_graph_iso(graph1_, graph2_, f)
      +                << std::endl;
      +    
      +// Print sub graph isomorphism map
      +    BGL_FORALL_VERTICES_T(v, graph1_, Graph1) 
      +      std::cout << '(' << get(p_map1_,v) << ", " 
      +                << get(p_map2_, get(f, v)) << ") ";
      +    
      +    std::cout << std::endl;
      +      
      +    return true;
      +  }
      +
      +private:
      +  const Graph1& graph1_;
      +  const Graph2& graph2_;
      +  
      +  const PropertyMap1& p_map1_;
      +  const PropertyMap2& p_map2_;
      +  
      +  const bool verify_;
      +};
      +    
      + + Using the sample DOT-files graph_small.dot: + +
      +graph G_small {
      +node1 -- node2;
      +node1 -- node3;
      +node3 -- node3;
      +node4 -- node1;
      +node4 -- node3;
      +}
      +    
      + + and graph_large.dot: + +
      +graph G_large {
      +node1 -- node3;
      +node1 -- node4;
      +node1 -- node6;
      +node2 -- node4;
      +node2 -- node5;
      +node3 -- node3;
      +node4 -- node5;
      +node4 -- node6;
      +node6 -- node6;
      +}
      +    
      + + vf2_sub_graph_iso finds the mappings (node1, node4) (node2, node2) + (node3, node6) (node4, node1) and (node1, node4) (node2, node5) + (node3, node6) (node4, node1). + To compile this example, you will need to build and link against the + "boost_graph" and "boost_regex" libraries + (cf. read_graphviz). + +

      +The complete example is provided under +examples/vf2_sub_graph_iso_gviz_example.cpp, +including a Scilab script to generate simple dot-files +examples/vf2_random_graphs.sce. +
      +

      + + +

      Additional Examples

      + +

      +These are: a multi-graph example +examples/vf2_sub_graph_iso_multi_example.cpp, +
      +one using a compressed_sparse_row_graph (works not for directed because in_edges not available) +examples/vf2_sub_graph_iso_csr_example.cpp, +
      +one putting a grid_graph +examples/vf2_sub_graph_iso_grd_example.cpp +
      +and one matching bidirectional und undirected graphs +examples/vf2_sub_graph_iso_undir_example.cpp. +
      +

      + +

      Bibliography

      + +
      +

      1 +
      + L. P. Cordella, P. Foggia, C. Sansone, and M. Vento. +
      An improved algorithm for matching large graphs. +
      In: 3rd IAPR-TC15 Workshop on Graph-based Representations in Pattern Recognition, pp. 149-159, Cuen, 2001. +
      +

      2 +
      + L. P. Cordella, P. Foggia, C. Sansone, and M. Vento. +
      A (Sub)Graph Isomorphism Algorithm for Matching Large Graphs. +
      IEEE Trans. Pattern Anal. Mach. Intell., vol. 26, no. 10, pp. 1367-1372, 2004. +
      +
      + +
      + Copyright © 2012, Flavio De Lorenzi + (fdlorenzi@gmail.com) + + + diff --git a/doc/vf2_sub_graph_iso_impl.pdf b/doc/vf2_sub_graph_iso_impl.pdf new file mode 100755 index 0000000000000000000000000000000000000000..e68df44a0040ce1e43773f27cc168a7913b7447b GIT binary patch literal 123602 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 literal 0 HcmV?d00001 diff --git a/doc/vf2_sub_graph_iso_impl.tex b/doc/vf2_sub_graph_iso_impl.tex new file mode 100755 index 000000000..ecb358e68 --- /dev/null +++ b/doc/vf2_sub_graph_iso_impl.tex @@ -0,0 +1,474 @@ +\documentclass[12pt]{article} +\usepackage{amsmath} +\usepackage{algorithmicx} +\usepackage{algpseudocode} +\usepackage{listings} + +% abbreviations and acronyms +\def\etal{{et al.\ }} +\def\eg{{\it e.g.\ }} +\def\etc{{\it etc.\ }} +\def\ie{{\it i.e.\ }} +\def\cf{{\it cf.\ }} + +\title{An Implementation of the {\sc VF2} (Sub)Graph Isomorphism Algorithm +Using The Boost Graph Library} +\author{Flavio De Lorenzi\thanks{E-mail: fdlorenzi@gmail.com}} + +\date{\today} + +\begin{document} +\maketitle +%\VerbatimFootnotes + +\begin{abstract} +This article describes an implementation of the {\sc VF2} algorithm, introduced +by Cordella \etal for solving the graph isomorphism and graph-subgraph +isomorphism problems, using the Boost Graph Library. This implementation +includes algorithmic improvements to account for self-loops and works for +directed and undirected graphs. +\end{abstract} + +\baselineskip=\normalbaselineskip + +%\newpage + +\section{Introduction} +This section briefly outlines the {\sc VF2} algorithm\footnote{The original +code by Pasquale Foggia and collaborators can be obtained from: +\texttt{http://www.cs.sunysb.edu/{\textasciitilde}algorith/implement/vflib/implement.shtml}}, +following closely \cite{cordella+2001, cordella+2004}. + +An isomorphism between two graphs $G_1=(V_1, E_1)$ and $G_2=(V_2, E_2)$ is a +bijective mapping $M$ of the vertices of one graph to vertices of the other +graph that preserves the edge structure of the graphs. $M$ is said to be a +graph-subgraph isomorphism iff $M$ is an isomorphism between $G_1$ and a +subgraph of $G_2$. + +A matching process between the two graphs $G_1$ and $G_2$ determines the +isomorphism mapping $M$ which associates vertices of $G_1$ with vertices of +$G_2$ and vice versa. The matching process can be described by means of a +state space representation combined with a depth-first strategy. The details +can be found in \cite{cordella+2001, cordella+2004} and references therein. + +Cordella \etal give the following high-level description of the matching +algorithm: + +\begin{algorithmic} +\Procedure{Match}{$s$} +\If {$M(s)$ covers all the nodes of $G_2$} + \State \Return $M(s)$ +\Else + \State Compute the set $P(s)$ of the pairs of vertices for inclusion in $M(s)$ + \ForAll {$(v,w) \in P(s)$} + \If {$F(s,v,w)$} + \State Compute the state $s'$ obtained by adding $(v,w)$ to $M(s)$ + \State \Call {Match}{$s'$} + \EndIf + \EndFor + \State Restore data structures +\EndIf +\EndProcedure +\end{algorithmic} + +$M(s)$ is a partial mapping associated with a state $s$, $P(s)$ is the set +of all possible pairs of vertices $(v,w)$ to be added to the current state $s$ +and $F(s,v,w)$ is a boolean function (called {\em feasibility function}) used +to prune the search tree. If its value is {\em true} the state $s'$ obtained +by adding $(v,w)$ to $s$ is guaranteed to be a partial isomorphism if $s$ is. + +% \subsubsection*{State Space Representation} + +To construct $P(s)$ and $F(s,v,w)$ Cordella \etal define the +{\em out-terminal set} as the set of vertices of $G_1$ that are not in $M(s)$ +but are successors of vertices in $M(s)$ (connected by out edges), and the +{\em in-terminal set} as the set of vertices that are not in $M(s)$ but are +predecessors of vertices in $M(s)$. Analogue sets are defined for $G_2$. + +% \subsubsection*{Data Structures} + +To compute $P(s)$ and $F(s,v,w)$ efficiently, Cordella \etal employ the +following data structures: + +\begin{itemize} + +\item Vectors \verb+core_1+ and \verb+core_2+ whose dimensions correspond to +the number of vertices in $G_1$ and $G_2$, respectively. These vectors store the +present mapping. + +\item Vectors \verb+in_1+, \verb+out_1+, \verb+in_2+ and \verb+out_2+ used to +describe the membership to the terminal sets. \verb+in_1+ is non-zero for a +particular vertex if the vertex is either in the partial mapping $M(s)$ or +belongs to the in-terminal state of $G_1$. The actual value is given by the +level of the depth-first search tree at which the vertex was included in the +corresponding set. + +\end{itemize} + + +\section{Implementation} + +The computations of the terminal sets or the addition (deletion) of a pair of +vertices to (from) a state are analogous for the two graphs $G_1$ and $G_2$. +For example, to add the vertex pair $(v, w)$ with $v \in V_1$ and $w \in V_2$ +to vector \verb+core_1+ is the same as adding $(w, v)$ to \verb+core_2+. This +observation suggests the following improvement to the original {\sc VF2} +implementation. Instead of implementing a state for $G_1$ and $G_2$ with +associated vectors \verb+core_1+, \verb+core_2+, \verb+in_1+, \verb+out_1+, +\verb+in_2+ and \verb+out_2+ directly, we implement a ``helper state'' class +\verb+base_state+ associated with a single graph. Class \verb+base_state+ then +contains \verb+core_+, \verb+in_+ and \verb+out_+, and member functions such as +%\eg \verb+push(const vertex_this_type& v_this, const vertex_other_type& v_other)+ +\eg \texttt{push(const vertex \_this\_type\& v\_this, const vertex\_other\_type\& v\_other)} +to add a vertex pair. The actual state associated with both graphs (implemented in +class \verb+state+) can thus be constructed using two ``helper states'', one +for each graph. For instance, the member function \verb+push+ to add a pair of +vertices to the actual state is obtained as illustrated in the code +fragment below: + +\lstset{breaklines=true, breakatwhitespace=true} +\lstset{columns=fullflexible} +\lstset{language=C++} +\begin{lstlisting} + +class state +{ + + ... + + base_state state1_; + base_state state2_; + +public: + // Add vertex pair to the state + void push(const vertex1_type& v, const vertex2_type& w) + { + state1_.push(v, w); + state2_.push(w, v); + } + + ... + +}; +\end{lstlisting} + +These classes (\verb+base_state+ and \verb+state+) and the non-recursive +matching procedure \verb+match+ are all members of namespace \verb+boost::detail+. + +The functions of the public interface are all defined in namespace \verb+boost+ and their +documentation will follow in the sections bellow. + +\subsection{Functions for Graph Sub-Graph Isomorphism Testing} + +\begin{lstlisting} +// Non-named parameter version +template +bool vf2_sub_graph_iso(const GraphSmall& graph_small, + const GraphLarge& graph_large, + SubGraphIsoMapCallBack user_callback, + IndexMapSmall index_map_small, + IndexMapLarge index_map_large, + const VertexOrderSmall& vertex_order_small, + EdgeCompatibilityPredicate edge_comp, + VertexCompatibilityPredicate vertex_comp) +\end{lstlisting} + + +\begin{lstlisting} +// Named parameter interface of vf2_sub_graph_iso +template +bool vf2_sub_graph_iso(const GraphSmall& graph_small, + const GraphLarge& graph_large, + SubGraphIsoMapCallBack user_callback, + const VertexOrderSmall& vertex_order_small, + const bgl_named_params& params) +\end{lstlisting} + + +\begin{lstlisting} +// All default interface for vf2_sub_graph_iso +template +bool vf2_sub_graph_iso(const GraphSmall& graph_small, + const GraphLarge& graph_large, + SubGraphIsoMapCallBack user_callback) +\end{lstlisting} + +This algorithm finds all graph-subgraph isomorphism mappings between graphs +\verb+graph_small+ and \verb+graph_large+ and outputs them to \verb+user_callback+. +It continues until \verb+user_callback+ returns true or the search space has +been fully explored.\\ +\verb+EdgeCompatibilityPredicate+ and \verb+VertexCompatibilityPredicate+ +predicates are used to test whether edges and vertices are compatible. +By default \verb+always_compatible+ is used, which returns true for any pair of +vertices or edges. + +\subsubsection*{Parameters} + +\begin{itemize} + +\item[IN:] \verb+const GraphSmall& graph_small+ The (first) smaller graph (fewer vertices) +of the pair to be tested for isomorphism. The type \verb+GraphSmall+ must be a +model of {\em Vertex List Graph}, {\em Bidirectional Graph}, {\em Edge List +Graph} and {\em Adjacency Matrix}. + + +\item[IN:] \verb+const GraphLarge& graph_large+ The (second) larger graph to be tested. +Type \verb+GraphLarge+ must be a model of +{\em Vertex List Graph}, {\em Bidirectional Graph}, {\em Edge List Graph} and +{\em Adjacency Matrix}. + +\item[OUT:] \verb+SubGraphIsoMapCallBack user_callback+ A function object to be +called when a graph-subgraph isomorphism has been discovered. The +\verb+operator()+ must have following form: +\begin{lstlisting} +template +bool operator()(CorrespondenceMap1To2 f, CorrespondenceMap2To1 g) const +\end{lstlisting} + +Both the \verb+CorrespondenceMap1To2+ and \verb+CorresondenceMap2To1+ types +are models of {\em Readable Property Map} and map equivalent vertices across +the two graphs given to \verb+vf2_sub_graph_iso+ (or \verb+vf2_graph_iso+). An +example is given below. + +Returning false from the callback will abort the search immediately. Otherwise, +the entire search space will be explored. + + +\item[IN:] \verb+const VertexOrderSmall& vertex_order_small+ The ordered +vertices of the smaller graph \verb+graph_small+. During the matching process the +vertices are examined in the order given by \verb+vertex_order_small+. Type +\verb+VertexOrderSmall+ must be a model of \verb+ContainerConcept+ with value +type \verb+graph_traits::vertex_descriptor+. +\\ +{\em Default:} The vertices are ordered by multiplicity of in/out degree. + +\end{itemize} + +\subsubsection*{Named Parameters} + +\begin{itemize} + +\item[IN:] \verb+vertex_index1(IndexMapSmall index_map_small)+ +This maps each vertex to an integer in the range \verb+[0, num_vertices(graph_small))+. +\\Type \verb+IndexMapSmall+ must be a model of {\em Readable Property Map}. +\\ +{\em Default:} \verb+get(vertex_index, graph_small)+ + +\item[IN:] \verb+vertex_index2(IndexMapLarge index_map_large)+ +This maps each vertex to an integer in the range \verb+[0, num_vertices(graph_large))+. +\\Type \verb+IndexMapLarge+ must be a model of {\em Readable Property Map}. +\\ +{\em Default:} \verb+get(vertex_index, graph_large)+ + +\item[IN:] \verb+edges_equivalent(EdgeCompatibilityPredicate edge_comp)+ +This function object is used to determine if edges between the two graphs +\verb+graph_small+ and \verb+graph_large+ are compatible.\\ +Type \verb+EdgeCompatiblePredicate+ must be a model of {\em Binary +Predicate} and have argument types of +\verb+graph_traits::edge_descriptor+ and +\verb+graph_traits::edge_descriptor+. A return value of true +indicates that the edges are compatible.\\ +{\em Default:} \verb+always_compatible+ + +\item[IN:] \verb+vertices_equivalent(VertexCompatibilityPredicate vertex_comp)+ +This function object is used to determine if vertices between the two graphs +\verb+graph_small+ and \verb+graph_large+ are compatible.\\ +Type \verb+VertexCompatiblePredicate+ must be a model of {\em Binary +Predicate} and have argument types of\\ +\verb+graph_traits::vertex_descriptor+ and\\ +\verb+graph_traits::vertex_descriptor+. A return value of true +indicates that the vertices are compatible. +\\ +{\em Default:} \verb+always_compatible+ + +\end{itemize} + + +\subsection{Functions for Isomorphism Testing} + +Non-named parameter, named-parameter and all default parameter versions of +function +\begin{lstlisting} +vf2_graph_iso(...) +\end{lstlisting} + +for isomorphism testing take the same parameters as the corresponding +functions \verb+vf2_sub_graph_iso+. The algorithm finds all isomorphism +mappings between graphs \verb+graph1+ and \verb+graph2+ and outputs them to +\verb+user_callback+. It continues until \verb+user_callback+ returns true +or the search space has been fully explored. As before, +\verb+EdgeCompatibilityPredicate+ and\\ +\verb+VertexCompatibilityPredicate+ +predicates are used to test whether edges and vertices are compatible with +\verb+always_compatible+ as default. + +\subsection{Utility Functions and Structs} + +\begin{lstlisting} +template +property_map_compatible +make_property_map_compatible(const PropertyMap1 property_map1, + const PropertyMap2 property_map2) +\end{lstlisting} +Returns a binary predicate function object \\ +(\verb+property_map_compatible+) that compares +vertices or edges between graphs using property maps. + + +\begin{lstlisting} +struct always_compatible +\end{lstlisting} +A binary function object that returns true for any pair of items. + + +\begin{lstlisting} +template +struct vf2_print_callback +\end{lstlisting} +Callback function object that prints out the correspondences between vertices +of \verb+Graph1+ and \verb+Graph2+. The constructor takes the two graphs $G_1$ +and $G_2$ and an optional \verb+bool+ parameter as arguments. If the latter is +set to \verb+true+, the callback function will verify the mapping before outputting +it to standard output. + +\begin{lstlisting} +// Verifies a graph (sub)graph isomorphism map +template +inline bool verify_vf2_sub_graph_iso(const Graph1& graph1, + const Graph2& graph2, + const CorresponenceMap1To2 f, + EdgeCompatibilityPredicate edge_comp, + VertexCompatibilityPredicate vertex_comp) +\end{lstlisting} + + +\begin{lstlisting} +// Variant of verify_sub_graph_iso with all default parameters +template +inline bool verify_vf2_sub_graph_iso(const Graph1& graph1, + const Graph2& graph2, + const CorresponenceMap1To2 f) +\end{lstlisting} + +This function can be used to verify a (sub)graph isomorphism mapping {\em f}. +The parameters are akin to function \verb+vf2_sub_graph_iso+ +(\verb+vf2_graph_iso+). + + +\subsection{Complexity} + +Spatial and time complexity are given in \cite{cordella+2004}. The spatial +complexity of {\sc VF2} is of order $O(V)$, where $V$ is the (maximum) number +of vertices of the two graphs. Time complexity is $O(V^2)$ in the best case and +$O(V!V)$ in the worst case. + +\subsection{A Graph Sub-Graph Isomorphism Example} + +In the example below, a small graph \verb+graph1+ and a larger graph +\verb+graph2+ are defined. \\ \verb+vf2_sub_graph_iso+ computes all the +mappings between the two graphs and outputs them via \verb+callback+. + + +\begin{lstlisting} +typedef adjacency_list graph_type; + +// Build graph1 +int num_vertices1 = 8; graph_type graph1(num_vertices1); +add_edge(0, 6, graph1); add_edge(0, 7, graph1); +add_edge(1, 5, graph1); add_edge(1, 7, graph1); +add_edge(2, 4, graph1); add_edge(2, 5, graph1); add_edge(2, 6, graph1); +add_edge(3, 4, graph1); + +// Build graph2 +int num_vertices2 = 9; graph_type graph2(num_vertices2); +add_edge(0, 6, graph2); add_edge(0, 8, graph2); +add_edge(1, 5, graph2); add_edge(1, 7, graph2); +add_edge(2, 4, graph2); add_edge(2, 7, graph2); add_edge(2, 8, graph2); +add_edge(3, 4, graph2); add_edge(3, 5, graph2); add_edge(3, 6, graph2); + +// true instructs callback to verify a map using +// verify_vf2_sub_graph_iso +vf2_print_callback callback(graph1, graph2, true); + +bool ret = vf2_sub_graph_iso(graph1, graph2, callback); +\end{lstlisting} + +\appendix +\section{Testing} + +Also included are \verb+vf2_sub_graph_iso_gviz_example.cpp+ and a Scilab \newline +(\verb+http://www.scilab.org/+) script \verb+vf2_random_graphs.sce+ for testing the +implementation. The script generates pairs of simple graphs of (possibly) different +size, such that there exists at least one (sub)graph isomorphism mapping +between the two graphs. The graphs are written to files \verb+graph_small.dot+ +and \verb+graph_large.dot+ using the Graphviz {\em DOT} language +(\verb+http://www.graphviz.org+). The following parameters can be used to +control the output: + +\begin{itemize} + +\item \verb+nbig+ Dimension of the large adjacency matrix +\item \verb+nsmall+ Dimension of the small adjacency matrix +\item \verb+density+ Density of the non-zero entries (of an initial square +matrix with dimension \verb+nbig+) +\item \verb+directed+ If set to one, a pair of directed graphs is generated, +otherwise undirected graphs are produced. +\item \verb+loops+ If set to one, self-loops are allowed, otherwise self-loops +are excluded. +\end{itemize} + +The generated dot-files specifying the graphs can be given as command line +arguments to the executable test program, which uses boost's GraphViz input +parser to build the graphs. The graphs are then tested for (sub)graph +isomorphism. The isomorphism mappings are verified and written to standard +output. + +To build the test executable, you will need to build and link against the +"boost\_graph" and "boost\_regex" libraries, \cf also \verb+read_graphviz+. + +%%%%%%%%%%%%%%% +% Bibliography +%%%%%%%%%%%%%% +\begin{thebibliography}{10} + +\bibitem{cordella+2001} L. P. Cordella, P. Foggia, C. Sansone, and M. Vento, + ``An improved algorithm for matching large graphs,'' \emph{In: 3rd IAPR-TC15 + Workshop on Graph-based Representations in Pattern Recognition, Cuen}, + pp. 149--159, 2001. + +\bibitem{cordella+2004} L. P. Cordella, P. Foggia, C. Sansone, and M. Vento, + ``A (Sub)Graph Isomorphism Algorithm for Matching Large Graphs,'' + \emph{IEEE Trans. Pattern Anal. Mach. Intell.}, vol. 26, no. 10, + pp. 1367--1372, 2004 + +\end{thebibliography} + + +\end{document} diff --git a/example/Jamfile.v2 b/example/Jamfile.v2 index 59bf7d8df..55f4caf9c 100644 --- a/example/Jamfile.v2 +++ b/example/Jamfile.v2 @@ -44,3 +44,10 @@ exe strong_components : strong_components.cpp ../build//boost_graph ; exe strong-components : strong-components.cpp ; exe subgraph : subgraph.cpp ; exe subgraph_properties : subgraph_properties.cpp ; +exe vf2_sub_graph_iso_csr_example : vf2_sub_graph_iso_csr_example.cpp ; +exe vf2_sub_graph_iso_example : vf2_sub_graph_iso_example.cpp ; +exe vf2_sub_graph_iso_grd_example : vf2_sub_graph_iso_grd_example.cpp ; +exe vf2_sub_graph_iso_gviz_example : vf2_sub_graph_iso_gviz_example.cpp ../build//boost_graph ; +exe vf2_sub_graph_iso_multi_example : vf2_sub_graph_iso_multi_example.cpp ; +exe vf2_sub_graph_iso_undir_example : vf2_sub_graph_iso_undir_example.cpp ; + diff --git a/example/vf2_random_graphs.sce b/example/vf2_random_graphs.sce new file mode 100755 index 000000000..e29a3bc9c --- /dev/null +++ b/example/vf2_random_graphs.sce @@ -0,0 +1,96 @@ +//======================================================================= +// Copyright (C) 2012 Flavio De Lorenzi (fdlorenzi@gmail.com) +// +// 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) +//======================================================================= + +// A script to generate simple pairs of graphs of (possibly) different +// size, such that there exists (at least) one (sub)graph isomorphism mapping +// between the two graphs. The graphs are written to files graph_small.dot +// and graph_large.dot using the Graphviz DOT language http://www.graphviz.org. +// The following parameters can be used to control the output: +// +// - nbig: Dimension of the large adjacency matrix +// - nsmall: Dimension of the small adjacency matrix +// - density: Density of the non-zero entries (of an initial square +// matrix with dimension nbig) +// - directed: If set to one, a pair of directed graphs is generated, +// otherwise undirected graphs are produced. +// - loops: If set to one, self-loops are allowed, otherwise self-loops +// are excluded. +// +// The generated dot-files specifying the graphs can be given as command line +// arguments to the executable test program (vf2_sub_graph_iso_gviz_example.cpp), +// which uses boost's GraphViz input parser to build the graphs. + +clear; + +directed=0; // Set to 1 to generate a directed graph, otherwise an + // undirected graph is generated + +loops=1; // Set to 1 to allow self-loops, otherwise loops are excluded + +nbig=6; density=0.4; // Size and density of non-zero elements of the large matrix +nsmall=4; // Size of the small matrix: nsmall<=nbig + +// Create a matrix with ~density * nbig^2 non-zero elements +M=full(sprand(nbig, nbig, density, "uniform")); +NZ=find(M<>0); +M(NZ)=1; + +if directed <> 1 then + M=triu(M); +end + +if loops <> 1 then + M=M-eye(M).*M +end + +indices=linspace(1, nbig, nbig)'; + +// Random row and column permutations +indices_perm=grand(1, 'prm', indices); + +M_perm=M(indices_perm, indices_perm); +M_perm=M_perm(1:nsmall, 1:nsmall); + +function write_digraph(file_name, Mat) + fd = mopen(file_name, "w"); + n = size(Mat, "r"); + mfprintf(fd, "digraph G {\n"); + for i = 1:n + for j = 1:n + if Mat(i,j)<>0 then + mfprintf(fd, "node%u -> node%u;\n", i, j); + end + end + end + mfprintf(fd, "}\n"); + mclose(fd); +endfunction + +function write_graph(file_name, Mat) + fd = mopen(file_name, "w"); + n = size(Mat, "r"); + mfprintf(fd, "graph G {\n"); + for i = 1:n + for j = 1:n + if Mat(i,j)<>0 then + mfprintf(fd, "node%u -- node%u;\n", i, j); + end + end + end + mfprintf(fd, "}\n"); + mclose(fd); +endfunction + +// Write graphs: +if directed <> 1 then + write_graph("graph_large.dot", M); + write_graph("graph_small.dot", M_perm); +else + write_digraph("graph_large.dot", M); + write_digraph("graph_small.dot", M_perm); +end diff --git a/example/vf2_sub_graph_iso_csr_example.cpp b/example/vf2_sub_graph_iso_csr_example.cpp new file mode 100755 index 000000000..d60bbaa83 --- /dev/null +++ b/example/vf2_sub_graph_iso_csr_example.cpp @@ -0,0 +1,45 @@ +//======================================================================= +// Copyright (C) 2012 Flavio De Lorenzi (fdlorenzi@gmail.com) +// +// 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) +//======================================================================= + +#include +#include +#include +using namespace boost; + + +int main() { + typedef adjacency_list graph_raw_t; + + // Build graph_raw1 + int num_vertices1 = 8; graph_raw_t graph_raw1(num_vertices1); + add_edge(0, 6, graph_raw1); add_edge(0, 7, graph_raw1); + add_edge(1, 5, graph_raw1); add_edge(1, 7, graph_raw1); + add_edge(2, 4, graph_raw1); add_edge(2, 5, graph_raw1); add_edge(2, 6, graph_raw1); + add_edge(3, 4, graph_raw1); + + // Build graph_raw2 + int num_vertices2 = 9; graph_raw_t graph_raw2(num_vertices2); + add_edge(0, 6, graph_raw2); add_edge(0, 8, graph_raw2); + add_edge(1, 5, graph_raw2); add_edge(1, 7, graph_raw2); + add_edge(2, 4, graph_raw2); add_edge(2, 7, graph_raw2); add_edge(2, 8, graph_raw2); + add_edge(3, 4, graph_raw2); add_edge(3, 5, graph_raw2); add_edge(3, 6, graph_raw2); + + typedef compressed_sparse_row_graph graph_csr_t; + + graph_csr_t graph1(graph_raw1); + graph_csr_t graph2(graph_raw2); + + // true instructs callback to verify a map using + // verify_vf2_sub_graph_iso + vf2_print_callback callback(graph1, graph2, true); + + bool ret = vf2_sub_graph_iso(graph1, graph2, callback); + (void)ret; + + return 0; +} diff --git a/example/vf2_sub_graph_iso_example.cpp b/example/vf2_sub_graph_iso_example.cpp new file mode 100755 index 000000000..ab353cb2a --- /dev/null +++ b/example/vf2_sub_graph_iso_example.cpp @@ -0,0 +1,39 @@ +//======================================================================= +// Copyright (C) 2012 Flavio De Lorenzi (fdlorenzi@gmail.com) +// +// 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) +//======================================================================= + +#include +#include +using namespace boost; + + +int main() { + typedef adjacency_list graph_type; + + // Build graph1 + int num_vertices1 = 8; graph_type graph1(num_vertices1); + add_edge(0, 6, graph1); add_edge(0, 7, graph1); + add_edge(1, 5, graph1); add_edge(1, 7, graph1); + add_edge(2, 4, graph1); add_edge(2, 5, graph1); add_edge(2, 6, graph1); + add_edge(3, 4, graph1); + + // Build graph2 + int num_vertices2 = 9; graph_type graph2(num_vertices2); + add_edge(0, 6, graph2); add_edge(0, 8, graph2); + add_edge(1, 5, graph2); add_edge(1, 7, graph2); + add_edge(2, 4, graph2); add_edge(2, 7, graph2); add_edge(2, 8, graph2); + add_edge(3, 4, graph2); add_edge(3, 5, graph2); add_edge(3, 6, graph2); + + // true instructs callback to verify a map using + // verify_vf2_sub_graph_iso + vf2_print_callback callback(graph1, graph2, true); + + bool ret = vf2_sub_graph_iso(graph1, graph2, callback); + (void)ret; + + return 0; +} diff --git a/example/vf2_sub_graph_iso_grd_example.cpp b/example/vf2_sub_graph_iso_grd_example.cpp new file mode 100755 index 000000000..b04f29dd6 --- /dev/null +++ b/example/vf2_sub_graph_iso_grd_example.cpp @@ -0,0 +1,36 @@ +//======================================================================= +// Copyright (C) 2012 Flavio De Lorenzi (fdlorenzi@gmail.com) +// +// 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) +//======================================================================= + +#include +#include +#include +using namespace boost; + + +int main() { + + typedef grid_graph<2> graph_type; + // Build graph1 + // Define dimension lengths, a 2x2 in this case + boost::array lengths1 = { { 2, 2 } }; + graph_type graph1(lengths1); + + // Build graph2 + // Define dimension lengths, a 2x3 in this case + boost::array lengths2 = { { 2, 3 } }; + graph_type graph2(lengths2); + + // true instructs callback to verify a map using + // verify_vf2_sub_graph_iso + vf2_print_callback callback(graph1, graph2, true); + + bool ret = vf2_sub_graph_iso(graph1, graph2, callback); + (void)ret; + + return 0; +} diff --git a/example/vf2_sub_graph_iso_gviz_example.cpp b/example/vf2_sub_graph_iso_gviz_example.cpp new file mode 100755 index 000000000..002a45b24 --- /dev/null +++ b/example/vf2_sub_graph_iso_gviz_example.cpp @@ -0,0 +1,143 @@ +//======================================================================= +// Copyright (C) 2012 Flavio De Lorenzi (fdlorenzi@gmail.com) +// +// 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) +//======================================================================= + +#include +#include +#include +#include +using namespace std; + +#include +#include +#include +#include +using namespace boost; + + +// Define a print_callback +template +struct print_callback { + + print_callback(const Graph1& graph1, const Graph2& graph2, + PropertyMap1 p_map1, PropertyMap2 p_map2, + bool verify = false) + : graph1_(graph1), graph2_(graph2), + p_map1_(p_map1), p_map2_(p_map2), + verify_(verify) {} + + template + bool operator()(CorrespondenceMap1To2 f, CorrespondenceMap2To1) const { + + if (verify_) + std::cout << "Verify: " << std::boolalpha + << verify_vf2_sub_graph_iso(graph1_, graph2_, f) + << std::endl; + + // Print sub graph isomorphism map + BGL_FORALL_VERTICES_T(v, graph1_, Graph1) + std::cout << '(' << get(p_map1_,v) << ", " + << get(p_map2_, get(f, v)) << ") "; + + std::cout << std::endl; + + return true; + } + +private: + const Graph1& graph1_; + const Graph2& graph2_; + + const PropertyMap1& p_map1_; + const PropertyMap2& p_map2_; + + const bool verify_; +}; + + +int main(int argc, char** argv) { + + if (argc != 3) { + cerr << "usage: " << argv[0] << " graph_small graph_large" << endl; + return EXIT_FAILURE; + } + ifstream graph_small_file(argv[1]); + ifstream graph_large_file(argv[2]); + if (!graph_small_file || !graph_large_file) { + cerr << "Files not found" << endl; + return EXIT_FAILURE; + } + + + // Vertex properties + typedef property vertex_p; + // adjacency_list-based type +#if 0 + typedef adjacency_list graph_t; +#else + typedef adjacency_list graph_t; +#endif + + // Construct an empty graph_small and prepare the dynamic_property_maps. + graph_t graph_small(0); + dynamic_properties dp_small; + + property_map::type name_small = + get(vertex_name, graph_small); + dp_small.property("node_id", name_small); + + // Read graph_small + bool status = read_graphviz(graph_small_file, graph_small, dp_small, "node_id"); + (void)status; + + // Construct an empty graph_large and prepare the dynamic_property_maps, + // following the read_graphviz example + graph_t graph_large(0); + dynamic_properties dp_large; + + property_map::type name_large = + get(vertex_name, graph_large); + dp_large.property("node_id", name_large); + + // Read graph_large + status = read_graphviz(graph_large_file, graph_large, dp_large, "node_id"); + + + // Create the call_back function + typedef property_map::type p_map_t; + print_callback callback(graph_small, graph_large, + name_small, name_large, true); + + // Compute the sub-graph isomorphism mappings +#if 1 + bool ret = vf2_sub_graph_iso(graph_small, graph_large, callback); + //bool ret = vf2_graph_iso(graph_small, graph_large, callback); +#else + typedef graph_traits::vertex_descriptor vertex_t; + typedef property_map::type index_map_t; + + index_map_t index_small = get(vertex_index, graph_small); + index_map_t index_large = get(vertex_index, graph_large); + + graph_traits::vertex_iterator vi, vi_end; + + vector vertex_order1; + for (tie(vi, vi_end) = vertices(graph_small); vi != vi_end; ++vi) + vertex_order1.push_back(*vi); + + bool ret = vf2_sub_graph_iso(graph_small, graph_large, callback, vertex_order1, + vertex_index1_map(index_small).vertex_index2_map(index_large)); + +#endif + (void)ret; + + return 0; +} diff --git a/example/vf2_sub_graph_iso_multi_example.cpp b/example/vf2_sub_graph_iso_multi_example.cpp new file mode 100755 index 000000000..c552ae8ad --- /dev/null +++ b/example/vf2_sub_graph_iso_multi_example.cpp @@ -0,0 +1,145 @@ +//======================================================================= +// Copyright (C) 2012 Flavio De Lorenzi (fdlorenzi@gmail.com) +// +// 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) +//======================================================================= + +#include +#include +#include +#include +#include +using namespace boost; + + +template +struct my_print_callback { + + my_print_callback(const Graph1& graph1, const Graph2& graph2, + EdgeCompatibilityPredicate edge_comp, + VertexCompatibilityPredicate vertex_comp) + : graph1_(graph1), graph2_(graph2), edge_comp_(edge_comp), vertex_comp_(vertex_comp) {} + + template + bool operator()(CorrespondenceMap1To2 f, CorrespondenceMap2To1) const { + + std::cout << "Verify: " << std::boolalpha + << verify_vf2_sub_graph_iso(graph1_, graph2_, f, edge_comp_, vertex_comp_) + << std::endl; + + // Print sub graph isomorphism map + BGL_FORALL_VERTICES_T(v, graph1_, Graph1) + std::cout << '(' << v << ", " << get(f, v) << ") "; + + std::cout << std::endl; + + return true; + } + +private: + const Graph1& graph1_; + const Graph2& graph2_; + EdgeCompatibilityPredicate edge_comp_; + VertexCompatibilityPredicate vertex_comp_; +}; + + + + +int main() { + typedef property edge_property; + typedef property vertex_property; + + //typedef adjacency_list graph_type; + typedef adjacency_list graph_type; + //typedef adjacency_list graph_type; + //typedef adjacency_list graph_type; + + // Build graph1 + graph_type graph1; + + add_vertex(vertex_property('a'), graph1); + add_vertex(vertex_property('a'), graph1); + add_vertex(vertex_property('a'), graph1); + + add_edge(0, 1, edge_property('b'), graph1); + add_edge(0, 1, edge_property('b'), graph1); + add_edge(0, 1, edge_property('d'), graph1); + + add_edge(1, 2, edge_property('s'), graph1); + + add_edge(2, 2, edge_property('l'), graph1); + add_edge(2, 2, edge_property('l'), graph1); + + + // Build graph2 + graph_type graph2; + + add_vertex(vertex_property('a'), graph2); + add_vertex(vertex_property('a'), graph2); + add_vertex(vertex_property('a'), graph2); + add_vertex(vertex_property('a'), graph2); + add_vertex(vertex_property('a'), graph2); + add_vertex(vertex_property('a'), graph2); + + add_edge(0, 1, edge_property('a'), graph2); + add_edge(0, 1, edge_property('a'), graph2); + add_edge(0, 1, edge_property('b'), graph2); + + + add_edge(1, 2, edge_property('s'), graph2); + + add_edge(2, 3, edge_property('b'), graph2); + add_edge(2, 3, edge_property('d'), graph2); + add_edge(2, 3, edge_property('b'), graph2); + + add_edge(3, 4, edge_property('s'), graph2); + + add_edge(4, 4, edge_property('l'), graph2); + add_edge(4, 4, edge_property('l'), graph2); + + add_edge(4, 5, edge_property('c'), graph2); + add_edge(4, 5, edge_property('c'), graph2); + add_edge(4, 5, edge_property('c'), graph2); + + add_edge(5, 0, edge_property('s'), graph2); + + // create predicates + typedef property_map::type vertex_name_map_t; + + typedef property_map_compatible vertex_comp_t; + vertex_comp_t vertex_comp = + make_property_map_compatible(get(vertex_name, graph1), get(vertex_name, graph2)); + + typedef property_map::type edge_name_map_t; + + typedef property_map_compatible edge_comp_t; + edge_comp_t edge_comp = + make_property_map_compatible(get(edge_name, graph1), get(edge_name, graph2)); + + + graph_traits::vertex_iterator vi, vi_end; + + // define the order in whcih vertices of graph1 are examined + std::vector::vertex_descriptor> vertex_order1; + for (tie(vi, vi_end) = vertices(graph1); vi != vi_end; ++vi) + vertex_order1.push_back(*vi); + + // true instructs callback to verify a map using + // verify_vf2_sub_graph_iso + my_print_callback + callback(graph1, graph2, edge_comp, vertex_comp); + + bool ret = vf2_sub_graph_iso(graph1, graph2, callback, vertex_order1, + edges_equivalent(edge_comp).vertices_equivalent(vertex_comp)); + + (void)ret; + + return 0; +} diff --git a/example/vf2_sub_graph_iso_undir_example.cpp b/example/vf2_sub_graph_iso_undir_example.cpp new file mode 100755 index 000000000..f3d6eae09 --- /dev/null +++ b/example/vf2_sub_graph_iso_undir_example.cpp @@ -0,0 +1,73 @@ +//======================================================================= +// Copyright (C) 2012 Flavio De Lorenzi (fdlorenzi@gmail.com) +// +// 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) +//======================================================================= + +#include +#include +#include +using namespace boost; + + +int main() { + typedef adjacency_list graph_bidir_t; + + // Build graph1 + int num_vertices1 = 8; graph_bidir_t graph1(num_vertices1); + add_edge(0, 6, graph1); add_edge(0, 7, graph1); + add_edge(1, 5, graph1); add_edge(1, 7, graph1); + add_edge(2, 4, graph1); add_edge(2, 5, graph1); add_edge(2, 6, graph1); + add_edge(3, 4, graph1); + // reversed edges + add_edge(6, 0, graph1); add_edge(7, 0, graph1); + add_edge(5, 1, graph1); add_edge(7, 1, graph1); + add_edge(4, 2, graph1); add_edge(5, 2, graph1); add_edge(6, 2, graph1); + add_edge(4, 3, graph1); + + add_edge(7, 7, graph1); + add_edge(7, 7, graph1); + + + // Build graph2 + int num_vertices2 = 9; graph_bidir_t graph2(num_vertices2); + add_edge(0, 6, graph2); add_edge(0, 8, graph2); + add_edge(1, 5, graph2); add_edge(1, 7, graph2); + add_edge(2, 4, graph2); add_edge(2, 7, graph2); add_edge(2, 8, graph2); + add_edge(3, 4, graph2); add_edge(3, 5, graph2); add_edge(3, 6, graph2); + // reversed edges + add_edge(6, 0, graph2); add_edge(8, 0, graph2); + add_edge(5, 1, graph2); add_edge(7, 1, graph2); + add_edge(4, 2, graph2); add_edge(7, 2, graph2); add_edge(8, 2, graph2); + add_edge(4, 3, graph2); add_edge(5, 3, graph2); add_edge(6, 3, graph2); + + add_edge(5, 5, graph2); + add_edge(5, 5, graph2); + + // Build graph3 + typedef adjacency_list graph_undir_t; + + int num_vertices3 = 9; graph_undir_t graph3(num_vertices3); + add_edge(0, 6, graph3); add_edge(0, 8, graph3); + add_edge(1, 5, graph3); add_edge(1, 7, graph3); + add_edge(2, 4, graph3); add_edge(2, 7, graph3); add_edge(2, 8, graph3); + add_edge(3, 4, graph3); add_edge(3, 5, graph3); add_edge(3, 6, graph3); + + add_edge(5, 5, graph3); + + // true instructs callback to verify a map using + // verify_vf2_sub_graph_iso + vf2_print_callback callback12(graph1, graph2, true); + + bool ret = vf2_sub_graph_iso(graph1, graph2, callback12); + std::cout << std::endl; + std::cout << std::endl; + + vf2_print_callback callback13(graph1, graph3, true); + ret = vf2_sub_graph_iso(graph1, graph3, callback13); + (void)ret; + + return 0; +} diff --git a/include/boost/graph/vf2_sub_graph_iso.hpp b/include/boost/graph/vf2_sub_graph_iso.hpp new file mode 100755 index 000000000..6e469c074 --- /dev/null +++ b/include/boost/graph/vf2_sub_graph_iso.hpp @@ -0,0 +1,1182 @@ +//======================================================================= +// Copyright (C) 2012 Flavio De Lorenzi (fdlorenzi@gmail.com) +// +// The algorithm implemented here is derived from original ideas by +// Pasquale Foggia and colaborators. For further information see +// e.g. Cordella et al. 2001, 2004. +// +// 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_VF2_SUB_GRAPH_ISO_HPP +#define BOOST_VF2_SUB_GRAPH_ISO_HPP + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifndef BOOST_GRAPH_ITERATION_MACROS_HPP +#define BOOST_ISO_INCLUDED_ITER_MACROS // local macro, see bottom of file +#include +#endif + +namespace boost { + + // Utility functions (analogue to mcgregor_common_subgraphs) + // Returns binary predicate function object that compares vertices or edges + // between graphs using property maps + template + struct property_map_compatible { + + property_map_compatible(const PropertyMap1 property_map1, + const PropertyMap2 property_map2) + : property_map1_(property_map1), property_map2_(property_map2) {} + + template + bool operator()(const Item1 item1, const Item2 item2) const { + return (get(property_map1_, item1) == get(property_map2_, item2)); + } + + private: + const PropertyMap1 property_map1_; + const PropertyMap2 property_map2_; + }; + + // Returns a property_map_compatible object that compares the values + // of property_map1 and property_map2. + template + property_map_compatible + make_property_map_compatible(const PropertyMap1 property_map1, + const PropertyMap2 property_map2) { + return property_map_compatible + (property_map1, property_map2); + } + + // Binary function object that always returns true. Used when + // vertices or edges are always compatible (i.e. have no labels). + struct always_compatible { + template + bool operator()(const Item1&, const Item2&) const { + return true; + } + }; + + + // Default print_callback + template + struct vf2_print_callback { + + vf2_print_callback(const Graph1& graph1, const Graph2& graph2, + bool verify = false) + : graph1_(graph1), graph2_(graph2), verify_(verify) {} + + template + bool operator()(CorrespondenceMap1To2 f, CorrespondenceMap2To1) const { + + if (verify_) + std::cout << "Verify: " << std::boolalpha + << verify_vf2_sub_graph_iso(graph1_, graph2_, f) + << std::endl; + + // Print sub graph isomorphism map + BGL_FORALL_VERTICES_T(v, graph1_, Graph1) + std::cout << '(' << get(vertex_index, graph1_, v) << ", " + << get(vertex_index, graph1_, get(f, v)) << ") "; + + std::cout << std::endl; + + return true; + } + + private: + const Graph1& graph1_; + const Graph2& graph2_; + + const bool verify_; + }; + + namespace detail { + + // State associated with a single graph (graph_this) + template + class base_state { + + typedef typename graph_traits::vertex_descriptor vertex_this_type; + typedef typename graph_traits::vertex_descriptor vertex_other_type; + + typedef typename graph_traits::vertices_size_type size_type; + + const GraphThis& graph_this_; + const GraphOther& graph_other_; + + IndexMapThis index_map_this_; + IndexMapOther index_map_other_; + + std::vector core_vec_; + typedef iterator_property_map::iterator, + IndexMapThis, vertex_other_type, + vertex_other_type&> core_map_type; + core_map_type core_; + + std::vector in_vec_, out_vec_; + typedef iterator_property_map::iterator, + IndexMapThis, size_type, size_type&> in_out_map_type; + in_out_map_type in_, out_; + + size_type term_in_count_, term_out_count_, term_both_count_, core_count_; + + // Forbidden + base_state(const base_state&); + base_state& operator=(const base_state&); + + public: + + base_state(const GraphThis& graph_this, const GraphOther& graph_other, + IndexMapThis index_map_this, IndexMapOther index_map_other) + : graph_this_(graph_this), graph_other_(graph_other), + index_map_this_(index_map_this), index_map_other_(index_map_other), + term_in_count_(0), term_out_count_(0), term_both_count_(0), core_count_(0) { + + core_vec_.resize(num_vertices(graph_this_), graph_traits::null_vertex()); + core_ = make_iterator_property_map(core_vec_.begin(), index_map_this_); + + in_vec_.resize(num_vertices(graph_this_), 0); + in_ = make_iterator_property_map(in_vec_.begin(), index_map_this_); + + out_vec_.resize(num_vertices(graph_this_), 0); + out_ = make_iterator_property_map(out_vec_.begin(), index_map_this_); + } + + // Adds a vertex pair to the state of graph graph_this + void push(const vertex_this_type& v_this, const vertex_other_type& v_other) { + + ++core_count_; + + put(core_, v_this, v_other); + + if (!get(in_, v_this)) { + put(in_, v_this, core_count_); + ++term_in_count_; + if (get(out_, v_this)) + ++term_both_count_; + } + + if (!get(out_, v_this)) { + put(out_, v_this, core_count_); + ++term_out_count_; + if (get(in_, v_this)) + ++term_both_count_; + } + + BGL_FORALL_INEDGES_T(v_this, e, graph_this_, GraphThis) { + vertex_this_type w = source(e, graph_this_); + if (!get(in_, w)) { + put(in_, w, core_count_); + ++term_in_count_; + if (get(out_, w)) + ++term_both_count_; + } + } + + BGL_FORALL_OUTEDGES_T(v_this, e, graph_this_, GraphThis) { + vertex_this_type w = target(e, graph_this_); + if (!get(out_, w)) { + put(out_, w, core_count_); + ++term_out_count_; + if (get(in_, w)) + ++term_both_count_; + } + } + + } + + // Removes vertex pair from state of graph_this + void pop(const vertex_this_type& v_this, const vertex_other_type&) { + + if (!core_count_) return; + + if (get(in_, v_this) == core_count_) { + put(in_, v_this, 0); + --term_in_count_; + if (get(out_, v_this)) + --term_both_count_; + } + + BGL_FORALL_INEDGES_T(v_this, e, graph_this_, GraphThis) { + vertex_this_type w = source(e, graph_this_); + if (get(in_, w) == core_count_) { + put(in_, w, 0); + --term_in_count_; + if (get(out_, w)) + --term_both_count_; + } + } + + if (get(out_, v_this) == core_count_) { + put(out_, v_this, 0); + --term_out_count_; + if (get(in_, v_this)) + --term_both_count_; + } + + BGL_FORALL_OUTEDGES_T(v_this, e, graph_this_, GraphThis) { + vertex_this_type w = target(e, graph_this_); + if (get(out_, w) == core_count_) { + put(out_, w, 0); + --term_out_count_; + if (get(in_, w)) + --term_both_count_; + } + } + put(core_, v_this, graph_traits::null_vertex()); + + --core_count_; + + } + + // Returns true if the in-terminal set is not empty + bool term_in() const { + return core_count_ < term_in_count_ ; + } + + // Returns true if vertex belongs to the in-terminal set + bool term_in(const vertex_this_type& v) const { + return (get(in_, v) > 0) && + (get(core_, v) == graph_traits::null_vertex()); + } + + // Returns true if the out-terminal set is not empty + bool term_out() const { + return core_count_ < term_out_count_; + } + + // Returns true if vertex belongs to the out-terminal set + bool term_out(const vertex_this_type& v) const { + return (get(out_, v) > 0) && + (get(core_, v) == graph_traits::null_vertex()); + } + + // Returns true of both (in- and out-terminal) sets are not empty + bool term_both() const { + return core_count_ < term_both_count_; + } + + // Returns true if vertex belongs to both (in- and out-terminal) sets + bool term_both(const vertex_this_type& v) const { + return (get(in_, v) > 0) && (get(out_, v) > 0) && + (get(core_, v) == graph_traits::null_vertex()); + } + + // Returns true if vertex belongs to the core map, i.e. it is in the + // present mapping + bool in_core(const vertex_this_type& v) const { + return get(core_, v) != graph_traits::null_vertex(); + } + + // Returns the number of vertices in the mapping + size_type count() const { + return core_count_; + } + + // Returns the image (in graph_other) of vertex v (in graph_this) + vertex_other_type core(const vertex_this_type& v) const { + return get(core_, v); + } + + // Returns the mapping + core_map_type get_map() const { + return core_; + } + + // Returns the "time" (or depth) when vertex was added to the in-terminal set + size_type in_depth(const vertex_this_type& v) const { + return get(in_, v); + } + + // Returns the "time" (or depth) when vertex was added to the out-terminal set + size_type out_depth(const vertex_this_type& v) const { + return get(out_, v); + } + + // Returns the terminal set counts + boost::tuple + term_set() const { + return boost::make_tuple(term_in_count_, term_out_count_, + term_both_count_); + } + + }; + + + // Function object that checks whether a valid edge + // exists. For multi-graphs matched edges are excluded + template + struct compatible_edge_exists { + + compatible_edge_exists() {}; + + typedef typename boost::graph_traits::out_edge_iterator edge_iterator_type; + + template + bool operator()(typename graph_traits::vertex_descriptor s, + typename graph_traits::vertex_descriptor t, + EdgePredicate is_valid_edge, const Graph& g) { + + edge_iterator_type ei, ei_end; + for (boost::tie(ei, ei_end) = out_edges(s, g); ei != ei_end; ++ei) { + if ((target(*ei, g) == t) && is_valid_edge(*ei) && + (matched_edges_.find(ei) == matched_edges_.end())) { + matched_edges_.insert(ei); + return true; + } + } + + return false; + } + + private: + + std::set matched_edges_; + }; + + template + struct compatible_edge_exists >::type> { + + compatible_edge_exists() {}; + + template + bool operator()(typename graph_traits::vertex_descriptor s, + typename graph_traits::vertex_descriptor t, + EdgePredicate is_valid_edge, const Graph& g) { + + typename graph_traits::edge_descriptor e; + bool found; + boost::tie(e, found) = edge(s, t, g); + if (!found) + return false; + else if (is_valid_edge(e)) + return true; + + return false; + } + + }; + + + // Generates a predicate for edge e1 given a binary predicate and a + // fixed edge e2 + template + struct edge1_predicate { + + edge1_predicate(EdgeCompatibilityPredicate edge_comp, + typename graph_traits::edge_descriptor e2) + : edge_comp_(edge_comp), e2_(e2) {} + + bool operator()(typename graph_traits::edge_descriptor e1) const { + return edge_comp_(e1, e2_); + } + + EdgeCompatibilityPredicate edge_comp_; + typename graph_traits::edge_descriptor e2_; + }; + + + // Generates a predicate for edge e2 given given a binary predicate and a + // fixed edge e1 + template + struct edge2_predicate { + + edge2_predicate(EdgeCompatibilityPredicate edge_comp, + typename graph_traits::edge_descriptor e1) + : edge_comp_(edge_comp), e1_(e1) {} + + bool operator()(typename graph_traits::edge_descriptor e2) const { + return edge_comp_(e1_, e2); + } + + EdgeCompatibilityPredicate edge_comp_; + typename graph_traits::edge_descriptor e1_; + }; + + + enum problem_selector { sub_graph_iso, isomorphism }; + + // The actual state associated with both graphs + template + class state { + + typedef typename graph_traits::vertex_descriptor vertex1_type; + typedef typename graph_traits::vertex_descriptor vertex2_type; + + typedef typename graph_traits::edge_descriptor edge1_type; + typedef typename graph_traits::edge_descriptor edge2_type; + + typedef typename graph_traits::vertices_size_type graph1_size_type; + typedef typename graph_traits::vertices_size_type graph2_size_type; + + const Graph1& graph1_; + const Graph2& graph2_; + + IndexMap1 index_map1_; + + EdgeCompatibilityPredicate edge_comp_; + VertexCompatibilityPredicate vertex_comp_; + + base_state state1_; + base_state state2_; + + // Two helper functions used in Feasibility and Valid functions to test + // terminal set counts when testing for: + // - graph sub-graph isomorphism, or + inline bool comp_term_sets(graph1_size_type a, + graph2_size_type b, + boost::mpl::int_) const { + return a <= b; + } + + // - graph isomorphism + inline bool comp_term_sets(graph1_size_type a, + graph2_size_type b, + boost::mpl::int_) const { + return a == b; + } + + // Forbidden + state(const state&); + state& operator=(const state&); + + public: + + state(const Graph1& graph1, const Graph2& graph2, + IndexMap1 index_map1, IndexMap2 index_map2, + EdgeCompatibilityPredicate edge_comp, + VertexCompatibilityPredicate vertex_comp) + : graph1_(graph1), graph2_(graph2), + index_map1_(index_map1), + edge_comp_(edge_comp), vertex_comp_(vertex_comp), + state1_(graph1, graph2, index_map1, index_map2), + state2_(graph2, graph1, index_map2, index_map1) {} + + // Add vertex pair to the state + void push(const vertex1_type& v, const vertex2_type& w) { + state1_.push(v, w); + state2_.push(w, v); + } + + // Remove vertex pair from state + void pop(const vertex1_type& v, const vertex2_type&) { + vertex2_type w = state1_.core(v); + state1_.pop(v, w); + state2_.pop(w, v); + } + + // Checks the feasibility of a new vertex pair + bool feasible(const vertex1_type& v_new, const vertex2_type& w_new) { + + if (!vertex_comp_(v_new, w_new)) return false; + + // graph1 + graph1_size_type term_in1_count = 0, term_out1_count = 0, rest1_count = 0; + + { + compatible_edge_exists edge2_exists; + + BGL_FORALL_INEDGES_T(v_new, e1, graph1_, Graph1) { + vertex1_type v = source(e1, graph1_); + + if (state1_.in_core(v) || (v == v_new)) { + vertex2_type w = w_new; + if (v != v_new) + w = state1_.core(v); + if (!edge2_exists(w, w_new, + edge2_predicate(edge_comp_, e1), + graph2_)) + return false; + + } else { + if (0 < state1_.in_depth(v)) + ++term_in1_count; + if (0 < state1_.out_depth(v)) + ++term_out1_count; + if ((state1_.in_depth(v) == 0) && (state1_.out_depth(v) == 0)) + ++rest1_count; + } + } + } + + { + compatible_edge_exists edge2_exists; + + BGL_FORALL_OUTEDGES_T(v_new, e1, graph1_, Graph1) { + vertex1_type v = target(e1, graph1_); + if (state1_.in_core(v) || (v == v_new)) { + vertex2_type w = w_new; + if (v != v_new) + w = state1_.core(v); + + if (!edge2_exists(w_new, w, + edge2_predicate(edge_comp_, e1), + graph2_)) + return false; + + } else { + if (0 < state1_.in_depth(v)) + ++term_in1_count; + if (0 < state1_.out_depth(v)) + ++term_out1_count; + if ((state1_.in_depth(v) == 0) && (state1_.out_depth(v) == 0)) + ++rest1_count; + } + } + } + + // graph2 + graph2_size_type term_out2_count = 0, term_in2_count = 0, rest2_count = 0; + + { + compatible_edge_exists edge1_exists; + + BGL_FORALL_INEDGES_T(w_new, e2, graph2_, Graph2) { + vertex2_type w = source(e2, graph2_); + if (state2_.in_core(w) || (w == w_new)) { + vertex1_type v = v_new; + if (w != w_new) + v = state2_.core(w); + + if (!edge1_exists(v, v_new, + edge1_predicate(edge_comp_, e2), + graph1_)) + return false; + + } else { + if (0 < state2_.in_depth(w)) + ++term_in2_count; + if (0 < state2_.out_depth(w)) + ++term_out2_count; + if ((state2_.in_depth(w) == 0) && (state2_.out_depth(w) == 0)) + ++rest2_count; + } + } + } + + { + compatible_edge_exists edge1_exists; + + BGL_FORALL_OUTEDGES_T(w_new, e2, graph2_, Graph2) { + vertex2_type w = target(e2, graph2_); + if (state2_.in_core(w) || (w == w_new)) { + vertex1_type v = v_new; + if (w != w_new) + v = state2_.core(w); + + if (!edge1_exists(v_new, v, + edge1_predicate(edge_comp_, e2), + graph1_)) + return false; + + } else { + if (0 < state2_.in_depth(w)) + ++term_in2_count; + if (0 < state2_.out_depth(w)) + ++term_out2_count; + if ((state2_.in_depth(w) == 0) && (state2_.out_depth(w) == 0)) + ++rest2_count; + } + } + } + + return comp_term_sets(term_in1_count, term_in2_count, + boost::mpl::int_()) && + comp_term_sets(term_out1_count, term_out2_count, + boost::mpl::int_()) && + comp_term_sets(rest1_count, rest2_count, + boost::mpl::int_()); + } + + // Returns true if vertex v in graph1 is a possible candidate to + // be added to the current state + bool possible_candidate1(const vertex1_type& v) const { + if (state1_.term_both() && state2_.term_both()) + return state1_.term_both(v); + else if (state1_.term_out() && state2_.term_out()) + return state1_.term_out(v); + else if (state1_.term_in() && state2_.term_in()) + return state1_.term_in(v); + else + return !state1_.in_core(v); + } + + // Returns true if vertex w in graph2 is a possible candidate to + // be added to the current state + bool possible_candidate2(const vertex2_type& w) const { + if (state1_.term_both() && state2_.term_both()) + return state2_.term_both(w); + else if (state1_.term_out() && state2_.term_out()) + return state2_.term_out(w); + else if (state1_.term_in() && state2_.term_in()) + return state2_.term_in(w); + else + return !state2_.in_core(w); + } + + // Returns true if a mapping was found + bool success() const { + return state1_.count() == num_vertices(graph1_); + } + + // Returns true if a state is valid + bool valid() const { + boost::tuple term1; + boost::tuple term2; + + term1 = state1_.term_set(); + term2 = state2_.term_set(); + + return comp_term_sets(boost::get<0>(term1), boost::get<0>(term2), + boost::mpl::int_()) && + comp_term_sets(boost::get<1>(term1), boost::get<1>(term2), + boost::mpl::int_()) && + comp_term_sets(boost::get<2>(term1), boost::get<2>(term2), + boost::mpl::int_()); + } + + // Calls the user_callback with a graph (sub)graph mapping + bool call_back(SubGraphIsoMapCallBack user_callback) const { + return user_callback(state1_.get_map(), state2_.get_map()); + } + + }; + + + // Data structure to keep info used for back tracking during + // matching process + template + struct vf2_match_continuation { + typename VertexOrder1::const_iterator graph1_verts_iter; + typename graph_traits::vertex_iterator graph2_verts_iter; + }; + + // Non-recursive method that explores state space using a depth-first + // search strategy. At each depth possible pairs candidate are compute + // and tested for feasibility to extend the mapping. If a complete + // mapping is found, the mapping is output to user_callback in the form + // of a correspondence map (graph1 to graph2). Returning false from the + // user_callback will terminate the search. Function match will return + // true if the entire search space was explored. + template + bool match(const Graph1& graph1, const Graph2& graph2, + SubGraphIsoMapCallBack user_callback, const VertexOrder1& vertex_order1, + state& s) { + + typename VertexOrder1::const_iterator graph1_verts_iter; + + typedef typename graph_traits::vertex_iterator vertex2_iterator_type; + vertex2_iterator_type graph2_verts_iter, graph2_verts_iter_end; + + typedef vf2_match_continuation match_continuation_type; + std::vector k; + + recur: + if (s.success()) { + if (!s.call_back(user_callback)) + return false; + + goto back_track; + } + + if (!s.valid()) + goto back_track; + + graph1_verts_iter = vertex_order1.begin(); + while (graph1_verts_iter != vertex_order1.end() && + !s.possible_candidate1(*graph1_verts_iter)) { + ++graph1_verts_iter; + } + + boost::tie(graph2_verts_iter, graph2_verts_iter_end) = vertices(graph2); + while (graph2_verts_iter != graph2_verts_iter_end) { + if (s.possible_candidate2(*graph2_verts_iter)) { + if (s.feasible(*graph1_verts_iter, *graph2_verts_iter)) { + match_continuation_type kk; + kk.graph1_verts_iter = graph1_verts_iter; + kk.graph2_verts_iter = graph2_verts_iter; + k.push_back(kk); + + s.push(*graph1_verts_iter, *graph2_verts_iter); + goto recur; + } + } + graph2_loop: ++graph2_verts_iter; + } + + back_track: + if (k.empty()) + return true; + + const match_continuation_type kk = k.back(); + graph1_verts_iter = kk.graph1_verts_iter; + graph2_verts_iter = kk.graph2_verts_iter; + k.pop_back(); + + s.pop(*graph1_verts_iter, *graph2_verts_iter); + + goto graph2_loop; + } + + + // Used to sort nodes by in/out degrees + template + struct vertex_in_out_degree_cmp { + typedef typename graph_traits::vertex_descriptor vertex_type; + + vertex_in_out_degree_cmp(const Graph& graph) + : graph_(graph) {} + + bool operator()(const vertex_type& v, const vertex_type& w) const { + // lexicographical comparison + return std::make_pair(in_degree(v, graph_), out_degree(v, graph_)) < + std::make_pair(in_degree(w, graph_), out_degree(w, graph_)); + + } + + const Graph graph_; + }; + + + // Used to sort nodes by frequency/degrees + template + struct vertex_frequency_degree_cmp { + typedef typename graph_traits::vertex_descriptor vertex_type; + + vertex_frequency_degree_cmp(const Graph& graph, const FrequencyMap& freq) + : graph_(graph), freq_(freq) {} + + bool operator()(const vertex_type& v, const vertex_type& w) const { + // lexicographical comparison + return std::make_pair(freq_[v], in_degree(v, graph_)+out_degree(v, graph_)) < + std::make_pair(freq_[w], in_degree(w, graph_)+out_degree(w, graph_)); + + } + + const Graph& graph_; + const FrequencyMap& freq_; + }; + + + // Sorts vertices of a graph by frequency/degree + template + void sort_vertices(const Graph& graph, const IndexMap index_map, VertexOrder& order) { + typedef typename graph_traits::vertices_size_type size_type; + + boost::range::sort(order, vertex_in_out_degree_cmp(graph)); + + std::vector freq_vec(num_vertices(graph), 0); + typedef iterator_property_map::iterator, + IndexMap, size_type, size_type&> frequency_map_type; + + frequency_map_type freq = make_iterator_property_map(freq_vec.begin(), index_map); + + typedef typename VertexOrder::iterator order_iterator; + + for (order_iterator order_iter = order.begin(); order_iter != order.end(); ) { + size_type count = 0; + for (order_iterator count_iter = order_iter; + (count_iter != order.end()) && + (in_degree(*order_iter, graph) == in_degree(*count_iter, graph)) && + (out_degree(*order_iter, graph) == out_degree(*count_iter, graph)); + ++count_iter) + ++count; + + for (size_type i = 0; i < count; ++i) { + freq[*order_iter] = count; + ++order_iter; + } + } + + boost::range::sort(order, vertex_frequency_degree_cmp(graph, freq)); + + } + + } // namespace detail + + + // Enumerates all graph sub-graph isomorphism mappings between graphs + // graph_small and graph_large. Continues until user_callback returns true or the + // search space has been fully explored. + template + bool vf2_sub_graph_iso(const GraphSmall& graph_small, const GraphLarge& graph_large, + SubGraphIsoMapCallBack user_callback, + IndexMapSmall index_map_small, IndexMapLarge index_map_large, + const VertexOrderSmall& vertex_order_small, + EdgeCompatibilityPredicate edge_comp, + VertexCompatibilityPredicate vertex_comp) { + + // Graph requirements + BOOST_CONCEPT_ASSERT(( BidirectionalGraphConcept )); + BOOST_CONCEPT_ASSERT(( VertexListGraphConcept )); + BOOST_CONCEPT_ASSERT(( EdgeListGraphConcept )); + BOOST_CONCEPT_ASSERT(( AdjacencyMatrixConcept )); + + BOOST_CONCEPT_ASSERT(( BidirectionalGraphConcept )); + BOOST_CONCEPT_ASSERT(( VertexListGraphConcept )); + BOOST_CONCEPT_ASSERT(( EdgeListGraphConcept )); + BOOST_CONCEPT_ASSERT(( AdjacencyMatrixConcept )); + + typedef typename graph_traits::vertex_descriptor vertex_small_type; + typedef typename graph_traits::vertex_descriptor vertex_large_type; + + typedef typename graph_traits::vertices_size_type size_type_small; + typedef typename graph_traits::vertices_size_type size_type_large; + + // Property map requirements + BOOST_CONCEPT_ASSERT(( ReadablePropertyMapConcept )); + typedef typename property_traits::value_type IndexMapSmallValue; + BOOST_STATIC_ASSERT(( is_convertible::value )); + + BOOST_CONCEPT_ASSERT(( ReadablePropertyMapConcept )); + typedef typename property_traits::value_type IndexMapLargeValue; + BOOST_STATIC_ASSERT(( is_convertible::value )); + + // Edge & vertex compatibility requirements + typedef typename graph_traits::edge_descriptor edge_small_type; + typedef typename graph_traits::edge_descriptor edge_large_type; + + BOOST_CONCEPT_ASSERT(( BinaryPredicateConcept )); + + BOOST_CONCEPT_ASSERT(( BinaryPredicateConcept )); + + // Vertex order requirements + BOOST_CONCEPT_ASSERT(( ContainerConcept )); + typedef typename VertexOrderSmall::value_type order_value_type; + BOOST_STATIC_ASSERT(( is_same::value )); + BOOST_ASSERT( num_vertices(graph_small) == vertex_order_small.size() ); + + if (num_vertices(graph_small) > num_vertices(graph_large)) + return false; + + typename graph_traits::edges_size_type num_edges_small = num_edges(graph_small); + typename graph_traits::edges_size_type num_edges_large = num_edges(graph_large); + + // Double the number of edges for undirected graphs: each edge counts as + // in-edge and out-edge + if (is_undirected(graph_small)) num_edges_small *= 2; + if (is_undirected(graph_large)) num_edges_large *= 2; + if (num_edges_small > num_edges_large) + return false; + + if ((num_vertices(graph_small) == 0) && (num_vertices(graph_large) == 0)) + return true; + + detail::state + s(graph_small, graph_large, index_map_small, index_map_large, edge_comp, vertex_comp); + + return detail::match(graph_small, graph_large, user_callback, vertex_order_small, s); + } + + + // All default interface for vf2_sub_graph_iso + template + bool vf2_sub_graph_iso(const GraphSmall& graph_small, const GraphLarge& graph_large, + SubGraphIsoMapCallBack user_callback) { + + typedef typename graph_traits::vertex_descriptor vertex_small_type; + + std::vector vertex_order_small; + BGL_FORALL_VERTICES_T(v, graph_small, GraphSmall) + vertex_order_small.push_back(v); + + detail::sort_vertices(graph_small, get(vertex_index, graph_small), vertex_order_small); + + return vf2_sub_graph_iso(graph_small, graph_large, user_callback, + get(vertex_index, graph_small), get(vertex_index, graph_large), + vertex_order_small, + always_compatible(), always_compatible()); + } + + + // Named parameter interface of vf2_sub_graph_iso + template + bool vf2_sub_graph_iso(const GraphSmall& graph_small, const GraphLarge& graph_large, + SubGraphIsoMapCallBack user_callback, + const VertexOrderSmall& vertex_order_small, + const bgl_named_params& params) { + + return vf2_sub_graph_iso(graph_small, graph_large, user_callback, + choose_const_pmap(get_param(params, vertex_index1), + graph_small, vertex_index), + choose_const_pmap(get_param(params, vertex_index2), + graph_large, vertex_index), + vertex_order_small, + choose_param(get_param(params, edges_equivalent_t()), + always_compatible()), + choose_param(get_param(params, vertices_equivalent_t()), + always_compatible()) + ); + + } + + + // Enumerates all isomorphism mappings between graphs graph1_ and graph2_. + // Continues until user_callback returns true or the search space has been + // fully explored. + template + bool vf2_graph_iso(const Graph1& graph1, const Graph2& graph2, + GraphIsoMapCallBack user_callback, + IndexMap1 index_map1, IndexMap2 index_map2, + const VertexOrder1& vertex_order1, + EdgeCompatibilityPredicate edge_comp, + VertexCompatibilityPredicate vertex_comp) { + + // Graph requirements + BOOST_CONCEPT_ASSERT(( BidirectionalGraphConcept )); + BOOST_CONCEPT_ASSERT(( VertexListGraphConcept )); + BOOST_CONCEPT_ASSERT(( EdgeListGraphConcept )); + BOOST_CONCEPT_ASSERT(( AdjacencyMatrixConcept )); + + BOOST_CONCEPT_ASSERT(( BidirectionalGraphConcept )); + BOOST_CONCEPT_ASSERT(( VertexListGraphConcept )); + BOOST_CONCEPT_ASSERT(( EdgeListGraphConcept )); + BOOST_CONCEPT_ASSERT(( AdjacencyMatrixConcept )); + + + typedef typename graph_traits::vertex_descriptor vertex1_type; + typedef typename graph_traits::vertex_descriptor vertex2_type; + + typedef typename graph_traits::vertices_size_type size_type1; + typedef typename graph_traits::vertices_size_type size_type2; + + // Property map requirements + BOOST_CONCEPT_ASSERT(( ReadablePropertyMapConcept )); + typedef typename property_traits::value_type IndexMap1Value; + BOOST_STATIC_ASSERT(( is_convertible::value )); + + BOOST_CONCEPT_ASSERT(( ReadablePropertyMapConcept )); + typedef typename property_traits::value_type IndexMap2Value; + BOOST_STATIC_ASSERT(( is_convertible::value )); + + // Edge & vertex compatibility requirements + typedef typename graph_traits::edge_descriptor edge1_type; + typedef typename graph_traits::edge_descriptor edge2_type; + + BOOST_CONCEPT_ASSERT(( BinaryPredicateConcept )); + + BOOST_CONCEPT_ASSERT(( BinaryPredicateConcept )); + + // Vertex order requirements + BOOST_CONCEPT_ASSERT(( ContainerConcept )); + typedef typename VertexOrder1::value_type order_value_type; + BOOST_STATIC_ASSERT(( is_same::value )); + BOOST_ASSERT( num_vertices(graph1) == vertex_order1.size() ); + + + if (num_vertices(graph1) != num_vertices(graph2)) + return false; + + typename graph_traits::edges_size_type num_edges1 = num_edges(graph1); + typename graph_traits::edges_size_type num_edges2 = num_edges(graph2); + + // Double the number of edges for undirected graphs: each edge counts as + // in-edge and out-edge + if (is_undirected(graph1)) num_edges1 *= 2; + if (is_undirected(graph2)) num_edges2 *= 2; + if (num_edges1 != num_edges2) + return false; + + if ((num_vertices(graph1) == 0) && (num_vertices(graph2) == 0)) + return true; + + detail::state + s(graph1, graph2, index_map1, index_map2, edge_comp, vertex_comp); + + return detail::match(graph1, graph2, user_callback, vertex_order1, s); + } + + + // All default interface for vf2_graph_iso + template + bool vf2_graph_iso(const Graph1& graph1, const Graph2& graph2, + GraphIsoMapCallBack user_callback) { + + typedef typename graph_traits::vertex_descriptor vertex1_type; + + std::vector vertex_order1; + BGL_FORALL_VERTICES_T(v, graph1, Graph1) + vertex_order1.push_back(v); + + detail::sort_vertices(graph1, get(vertex_index, graph1), vertex_order1); + + return vf2_graph_iso(graph1, graph2, user_callback, + get(vertex_index, graph1), get(vertex_index, graph2), + vertex_order1, + always_compatible(), always_compatible()); + } + + + // Named parameter interface of vf2_graph_iso + template + bool vf2_graph_iso(const Graph1& graph1, const Graph2& graph2, + GraphIsoMapCallBack user_callback, + const VertexOrder1& vertex_order1, + const bgl_named_params& params) { + + return vf2_graph_iso(graph1, graph2, user_callback, + choose_const_pmap(get_param(params, vertex_index1), + graph1, vertex_index), + choose_const_pmap(get_param(params, vertex_index2), + graph2, vertex_index), + vertex_order1, + choose_param(get_param(params, edges_equivalent_t()), + always_compatible()), + choose_param(get_param(params, vertices_equivalent_t()), + always_compatible()) + ); + + } + + + // Verifies a graph (sub)graph isomorphism map + template + inline bool verify_vf2_sub_graph_iso(const Graph1& graph1, const Graph2& graph2, + const CorresponenceMap1To2 f, + EdgeCompatibilityPredicate edge_comp, + VertexCompatibilityPredicate vertex_comp) { + + BOOST_CONCEPT_ASSERT(( EdgeListGraphConcept )); + BOOST_CONCEPT_ASSERT(( AdjacencyMatrixConcept )); + + detail::compatible_edge_exists edge2_exists; + + BGL_FORALL_EDGES_T(e1, graph1, Graph1) { + typename graph_traits::vertex_descriptor s1, t1; + typename graph_traits::vertex_descriptor s2, t2; + + s1 = source(e1, graph1); t1 = target(e1, graph1); + s2 = get(f, s1); t2 = get(f, t1); + + if (!vertex_comp(s1, s2) || !vertex_comp(t1, t2)) + return false; + + typename graph_traits::edge_descriptor e2; + + if (!edge2_exists(s2, t2, + detail::edge2_predicate(edge_comp, e1), + graph2)) + return false; + + } + + return true; + } + + // Variant of verify_sub_graph_iso with all default parameters + template + inline bool verify_vf2_sub_graph_iso(const Graph1& graph1, const Graph2& graph2, + const CorresponenceMap1To2 f) { + return verify_vf2_sub_graph_iso(graph1, graph2, f, + always_compatible(), always_compatible()); + } + + + +} // namespace boost + +#ifdef BOOST_ISO_INCLUDED_ITER_MACROS +#undef BOOST_ISO_INCLUDED_ITER_MACROS +#include +#endif + +#endif // BOOST_VF2_SUB_GRAPH_ISO_HPP From add307aafce354a2dab1bad20c43f0f8e5a2247f Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Fri, 7 Dec 2012 01:33:49 +0000 Subject: [PATCH 245/333] Added info on default argument; fixes #7771 [SVN r81747] --- doc/small_world_generator.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/small_world_generator.html b/doc/small_world_generator.html index 0b853502f..5dfffae54 100644 --- a/doc/small_world_generator.html +++ b/doc/small_world_generator.html @@ -45,7 +45,7 @@ small_world_iterator(); small_world_iterator(RandomGenerator& gen, vertices_size_type n, - vertices_size_type k, double probability, + vertices_size_type k, double probability = 0., bool allow_self_loops = false); // Iterator operations reference operator*() const; @@ -82,7 +82,7 @@

      Constructors

       small_world_iterator(RandomGenerator& gen, vertices_size_type n,
      -                     vertices_size_type k, double probability,
      +                     vertices_size_type k, double probability = 0.,
                            bool allow_self_loops = false);
       
      From 867f8cf49525f01bfdfa0211c12d61e268f9b525 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Fri, 7 Dec 2012 19:29:12 +0000 Subject: [PATCH 246/333] Fixed directed_graph and undirected_graph handling of vertex_all and edge_all properties [SVN r81770] --- include/boost/graph/directed_graph.hpp | 133 ++++++++++++++++------- include/boost/graph/undirected_graph.hpp | 92 ++++++++++++++-- include/boost/pending/property.hpp | 21 ++++ 3 files changed, 197 insertions(+), 49 deletions(-) diff --git a/include/boost/graph/directed_graph.hpp b/include/boost/graph/directed_graph.hpp index 250d0b63d..585308d18 100644 --- a/include/boost/graph/directed_graph.hpp +++ b/include/boost/graph/directed_graph.hpp @@ -9,6 +9,10 @@ #include #include +#include +#include +#include +#include namespace boost { @@ -27,8 +31,8 @@ struct directed_graph_tag { }; */ template < typename VertexProp = no_property, - typename EdgeProp= no_property, - typename GraphProp= no_property> + typename EdgeProp = no_property, + typename GraphProp = no_property> class directed_graph { public: @@ -39,15 +43,14 @@ class directed_graph typedef typename lookup_one_property::type vertex_bundled; typedef typename lookup_one_property::type edge_bundled; -private: - // Wrap the user-specified properties with an index. - typedef property vertex_property; - typedef property edge_property; - +public: + // Embed indices into the vertex type. + typedef property internal_vertex_property; + typedef property internal_edge_property; public: typedef adjacency_list< listS, listS, bidirectionalS, - vertex_property, edge_property, GraphProp, + internal_vertex_property, internal_edge_property, GraphProp, listS > graph_type; @@ -80,8 +83,8 @@ class directed_graph typedef typename graph_type::edge_parallel_category edge_parallel_category; typedef typename graph_type::traversal_category traversal_category; - typedef unsigned vertex_index_type; - typedef unsigned edge_index_type; + typedef std::size_t vertex_index_type; + typedef std::size_t edge_index_type; directed_graph(GraphProp const& p = GraphProp()) : m_graph(p), m_num_vertices(0), m_num_edges(0), m_max_vertex_index(0) @@ -137,6 +140,7 @@ class directed_graph vertices_size_type num_vertices() const { return m_num_vertices; } + private: // This helper function manages the attribution of vertex indices. vertex_descriptor make_index(vertex_descriptor v) { @@ -150,7 +154,7 @@ class directed_graph { return make_index(boost::add_vertex(m_graph)); } vertex_descriptor add_vertex(vertex_property_type const& p) - { return make_index(boost::add_vertex(vertex_property(0u, p), m_graph)); } + { return make_index(boost::add_vertex(internal_vertex_property(0u, p), m_graph)); } void clear_vertex(vertex_descriptor v) { @@ -186,7 +190,7 @@ class directed_graph std::pair add_edge(vertex_descriptor u, vertex_descriptor v, edge_property_type const& p) - { return make_index(boost::add_edge(u, v, edge_property(0u, p), m_graph)); } + { return make_index(boost::add_edge(u, v, internal_edge_property(0u, p), m_graph)); } void remove_edge(vertex_descriptor u, vertex_descriptor v) { @@ -516,37 +520,32 @@ remove_in_edge_if(typename DIRECTED_GRAPH::vertex_descriptor v, DIRECTED_GRAPH& g) { return remove_in_edge_if(v, pred, g.impl()); } -// Helper code for working with property maps -namespace detail -{ - struct directed_graph_vertex_property_selector { - template - struct bind_ { - typedef typename DirectedGraph::graph_type Graph; - typedef property_map PropertyMap; - typedef typename PropertyMap::type type; - typedef typename PropertyMap::const_type const_type; - }; - }; - - struct directed_graph_edge_property_selector { - template - struct bind_ { - typedef typename DirectedGraph::graph_type Graph; - typedef property_map PropertyMap; - typedef typename PropertyMap::type type; - typedef typename PropertyMap::const_type const_type; - }; - }; -} - -template <> -struct vertex_property_selector -{ typedef detail::directed_graph_vertex_property_selector type; }; +template +struct property_map: property_map {}; + +template +struct property_map { + typedef transform_value_property_map< + detail::remove_first_property, + typename property_map::const_type> + const_type; + typedef transform_value_property_map< + detail::remove_first_property, + typename property_map::type> + type; +}; -template <> -struct edge_property_selector -{ typedef detail::directed_graph_edge_property_selector type; }; +template +struct property_map { + typedef transform_value_property_map< + detail::remove_first_property, + typename property_map::const_type> + const_type; + typedef transform_value_property_map< + detail::remove_first_property, + typename property_map::type> + type; +}; // PropertyGraph concepts template @@ -559,6 +558,26 @@ inline typename property_map::const_type get(Property p, DIRECTED_GRAPH const& g) { return get(p, g.impl()); } +template +inline typename property_map::type +get(vertex_all_t, DIRECTED_GRAPH& g) +{ return typename property_map::type(detail::remove_first_property(), get(vertex_all, g.impl())); } + +template +inline typename property_map::const_type +get(vertex_all_t, DIRECTED_GRAPH const& g) +{ return typename property_map::const_type(detail::remove_first_property(), get(vertex_all, g.impl())); } + +template +inline typename property_map::type +get(edge_all_t, DIRECTED_GRAPH& g) +{ return typename property_map::type(detail::remove_first_property(), get(edge_all, g.impl())); } + +template +inline typename property_map::const_type +get(edge_all_t, DIRECTED_GRAPH const& g) +{ return typename property_map::const_type(detail::remove_first_property(), get(edge_all, g.impl())); } + template inline typename property_traits< typename property_map< @@ -568,10 +587,40 @@ inline typename property_traits< get(Property p, DIRECTED_GRAPH const& g, Key const& k) { return get(p, g.impl(), k); } +template +inline typename property_traits< + typename property_map< + typename DIRECTED_GRAPH::graph_type, vertex_all_t + >::const_type +>::value_type +get(vertex_all_t, DIRECTED_GRAPH const& g, Key const& k) +{ return get(vertex_all, g.impl(), k).m_base; } + +template +inline typename property_traits< + typename property_map< + typename DIRECTED_GRAPH::graph_type, edge_all_t + >::const_type +>::value_type +get(edge_all_t, DIRECTED_GRAPH const& g, Key const& k) +{ return get(edge_all, g.impl(), k).m_base; } + template inline void put(Property p, DIRECTED_GRAPH& g, Key const& k, Value const& v) { put(p, g.impl(), k, v); } +template +inline void put(vertex_all_t, DIRECTED_GRAPH& g, Key const& k, Value const& v) +{ put(vertex_all, g.impl(), k, + typename DIRECTED_GRAPH::internal_vertex_property(get(vertex_index, g.impl(), k), v)); +} + +template +inline void put(edge_all_t, DIRECTED_GRAPH& g, Key const& k, Value const& v) +{ put(edge_all, g.impl(), k, + typename DIRECTED_GRAPH::internal_vertex_property(get(edge_index, g.impl(), k), v)); +} + template typename graph_property::type& get_property(DIRECTED_GRAPH& g, Property p) diff --git a/include/boost/graph/undirected_graph.hpp b/include/boost/graph/undirected_graph.hpp index 738a5c950..5c000dc2a 100644 --- a/include/boost/graph/undirected_graph.hpp +++ b/include/boost/graph/undirected_graph.hpp @@ -9,6 +9,10 @@ #include #include +#include +#include +#include +#include namespace boost { @@ -39,16 +43,16 @@ class undirected_graph typedef typename lookup_one_property::type vertex_bundled; typedef typename lookup_one_property::type edge_bundled; -private: +public: // Embed indices into the vertex type. - typedef property vertex_property; - typedef property edge_property; + typedef property internal_vertex_property; + typedef property internal_edge_property; public: typedef adjacency_list graph_type; private: @@ -151,7 +155,7 @@ class undirected_graph { return make_index(boost::add_vertex(m_graph)); } vertex_descriptor add_vertex(vertex_property_type const& p) - { return make_index(boost::add_vertex(vertex_property(0u, p), m_graph)); } + { return make_index(boost::add_vertex(internal_vertex_property(0u, p), m_graph)); } void clear_vertex(vertex_descriptor v) { std::pair @@ -188,7 +192,7 @@ class undirected_graph std::pair add_edge(vertex_descriptor u, vertex_descriptor v, edge_property_type const& p) - { return make_index(boost::add_edge(u, v, edge_property(0u, p), m_graph)); } + { return make_index(boost::add_edge(u, v, internal_edge_property(0u, p), m_graph)); } void remove_edge(vertex_descriptor u, vertex_descriptor v) { // find all edges, (u, v) @@ -525,6 +529,30 @@ remove_in_edge_if(typename UNDIRECTED_GRAPH::vertex_descriptor v, template struct property_map: property_map {}; +template +struct property_map { + typedef transform_value_property_map< + detail::remove_first_property, + typename property_map::const_type> + const_type; + typedef transform_value_property_map< + detail::remove_first_property, + typename property_map::type> + type; +}; + +template +struct property_map { + typedef transform_value_property_map< + detail::remove_first_property, + typename property_map::const_type> + const_type; + typedef transform_value_property_map< + detail::remove_first_property, + typename property_map::type> + type; +}; + // PropertyGraph concepts template inline typename property_map::type @@ -536,6 +564,26 @@ inline typename property_map::const_type get(Property p, UNDIRECTED_GRAPH const& g) { return get(p, g.impl()); } +template +inline typename property_map::type +get(vertex_all_t, UNDIRECTED_GRAPH& g) +{ return typename property_map::type(detail::remove_first_property(), get(vertex_all, g.impl())); } + +template +inline typename property_map::const_type +get(vertex_all_t, UNDIRECTED_GRAPH const& g) +{ return typename property_map::const_type(detail::remove_first_property(), get(vertex_all, g.impl())); } + +template +inline typename property_map::type +get(edge_all_t, UNDIRECTED_GRAPH& g) +{ return typename property_map::type(detail::remove_first_property(), get(edge_all, g.impl())); } + +template +inline typename property_map::const_type +get(edge_all_t, UNDIRECTED_GRAPH const& g) +{ return typename property_map::const_type(detail::remove_first_property(), get(edge_all, g.impl())); } + template inline typename property_traits< typename property_map< @@ -545,10 +593,40 @@ inline typename property_traits< get(Property p, UNDIRECTED_GRAPH const& g, Key const& k) { return get(p, g.impl(), k); } +template +inline typename property_traits< + typename property_map< + typename UNDIRECTED_GRAPH::graph_type, vertex_all_t + >::const_type +>::value_type +get(vertex_all_t, UNDIRECTED_GRAPH const& g, Key const& k) +{ return get(vertex_all, g.impl(), k).m_base; } + +template +inline typename property_traits< + typename property_map< + typename UNDIRECTED_GRAPH::graph_type, edge_all_t + >::const_type +>::value_type +get(edge_all_t, UNDIRECTED_GRAPH const& g, Key const& k) +{ return get(edge_all, g.impl(), k).m_base; } + template inline void put(Property p, UNDIRECTED_GRAPH& g, Key const& k, Value const& v) { put(p, g.impl(), k, v); } +template +inline void put(vertex_all_t, UNDIRECTED_GRAPH& g, Key const& k, Value const& v) +{ put(vertex_all, g.impl(), k, + typename UNDIRECTED_GRAPH::internal_vertex_property(get(vertex_index, g.impl(), k), v)); +} + +template +inline void put(edge_all_t, UNDIRECTED_GRAPH& g, Key const& k, Value const& v) +{ put(edge_all, g.impl(), k, + typename UNDIRECTED_GRAPH::internal_vertex_property(get(edge_index, g.impl(), k), v)); +} + template inline typename graph_property::type& get_property(UNDIRECTED_GRAPH& g, Property p) diff --git a/include/boost/pending/property.hpp b/include/boost/pending/property.hpp index 3053908d7..e63a2d203 100644 --- a/include/boost/pending/property.hpp +++ b/include/boost/pending/property.hpp @@ -244,6 +244,27 @@ namespace boost { } // namespace detail +namespace detail { + // Stuff for directed_graph and undirected_graph to skip over their first + // vertex_index and edge_index properties when providing vertex_all and + // edge_all; make sure you know the exact structure of your properties if you + // use there. + struct remove_first_property { + template + struct result { + typedef typename boost::function_traits::arg1_type a1; + typedef typename boost::remove_reference::type non_ref; + typedef typename non_ref::next_type nx; + typedef typename boost::mpl::if_, boost::add_const, nx>::type with_const; + typedef typename boost::add_reference::type type; + }; + template + typename Prop::next_type& operator()(Prop& p) const {return p.m_base;} + template + const typename Prop::next_type& operator()(const Prop& p) const {return p.m_base;} + }; +} + } // namesapce boost #endif /* BOOST_PROPERTY_HPP */ From 36d3d833753f3e744605359be7b44698c777b9c4 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Fri, 7 Dec 2012 19:30:28 +0000 Subject: [PATCH 247/333] Fixed adding properties in labeled_graph; fixes #7773 [SVN r81771] --- include/boost/graph/labeled_graph.hpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/include/boost/graph/labeled_graph.hpp b/include/boost/graph/labeled_graph.hpp index 2ff7830e3..5b688b02e 100644 --- a/include/boost/graph/labeled_graph.hpp +++ b/include/boost/graph/labeled_graph.hpp @@ -140,7 +140,7 @@ namespace graph_detail { // Tag dispatch on unique associative containers (i.e. maps). template std::pair::vertex_descriptor, bool> - insert_labeled_vertex(Container& c, Graph& g, Label const& l, Prop const&, + insert_labeled_vertex(Container& c, Graph& g, Label const& l, Prop const& p, unique_associative_container_tag) { // Here, we actually have to try the insertion first, and only add @@ -150,6 +150,7 @@ namespace graph_detail { std::pair x = c.insert(std::make_pair(l, Vertex())); if(x.second) { x.first->second = add_vertex(g); + put(boost::vertex_all, g, x.first->second, p); } return std::make_pair(x.first->second, x.second); } From 25852f92afaeca12b3abddeca7f7d37485a5803b Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Fri, 7 Dec 2012 19:41:01 +0000 Subject: [PATCH 248/333] Applied patch from #7766; fixes #7766 [SVN r81772] --- include/boost/graph/named_graph.hpp | 44 ++++++++++++++++++++++++++--- 1 file changed, 40 insertions(+), 4 deletions(-) diff --git a/include/boost/graph/named_graph.hpp b/include/boost/graph/named_graph.hpp index 1150e4363..4c687a086 100644 --- a/include/boost/graph/named_graph.hpp +++ b/include/boost/graph/named_graph.hpp @@ -11,16 +11,23 @@ #define BOOST_GRAPH_NAMED_GRAPH_HPP #include -#include -#include -#include -#include +#include +#include +#include #include #include +#include #include +#include // for boost::lookup_one_property #include +#include // for boost::make_tuple +#include +#include +#include #include +#include // for std::equal_to #include // for std::runtime_error +#include // for std::pair namespace boost { namespace graph { @@ -410,6 +417,35 @@ add_edge(typename BGL_NAMED_GRAPH::vertex_name_type const& u_name, g.derived()); } +// Overloads to support EdgeMutablePropertyGraph graphs +template +std::pair::edge_descriptor, bool> +add_edge(typename BGL_NAMED_GRAPH::vertex_descriptor const& u, + typename BGL_NAMED_GRAPH::vertex_name_type const& v_name, + typename edge_property_type::type const& p, + BGL_NAMED_GRAPH& g) { + return add_edge(u, add_vertex(v_name, g.derived()), p, g.derived()); +} + +template +std::pair::edge_descriptor, bool> +add_edge(typename BGL_NAMED_GRAPH::vertex_name_type const& u_name, + typename BGL_NAMED_GRAPH::vertex_descriptor const& v, + typename edge_property_type::type const& p, + BGL_NAMED_GRAPH& g) { + return add_edge(add_vertex(u_name, g.derived()), v, p, g.derived()); +} + +template +std::pair::edge_descriptor, bool> +add_edge(typename BGL_NAMED_GRAPH::vertex_name_type const& u_name, + typename BGL_NAMED_GRAPH::vertex_name_type const& v_name, + typename edge_property_type::type const& p, + BGL_NAMED_GRAPH& g) { + return add_edge(add_vertex(u_name, g.derived()), + add_vertex(v_name, g.derived()), p, g.derived()); +} + #undef BGL_NAMED_GRAPH #undef BGL_NAMED_GRAPH_PARAMS From 5f6963e0f0d86d3f679137180245d45f2d2b5359 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Mon, 10 Dec 2012 15:26:59 +0000 Subject: [PATCH 249/333] Fixed typo; fixes #7780 [SVN r81822] --- doc/push_relabel_max_flow.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/push_relabel_max_flow.html b/doc/push_relabel_max_flow.html index 4fcab20a2..cb96c83a9 100644 --- a/doc/push_relabel_max_flow.html +++ b/doc/push_relabel_max_flow.html @@ -158,7 +158,7 @@

      Example

      #include <boost/config.hpp> #include <iostream> #include <string> -#include <boost/graph/push_relabel_map_flow.hpp> +#include <boost/graph/push_relabel_max_flow.hpp> #include <boost/graph/adjacency_list.hpp> #include <boost/graph/read_dimacs.hpp> From 233cc514c5a0f98fb7468a9c3804374d7fce88f8 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Wed, 12 Dec 2012 03:38:48 +0000 Subject: [PATCH 250/333] Re-added incident edges example from documentation; fixed undirected_adjacency_list.expected to match current code; fixed link to undirected.cpp example in documentation; fixes #7787 [SVN r81869] --- doc/graph_concepts.html | 2 +- example/undirected_adjacency_list.cpp | 18 +++++++++++++----- example/undirected_adjacency_list.expected | 2 ++ 3 files changed, 16 insertions(+), 6 deletions(-) diff --git a/doc/graph_concepts.html b/doc/graph_concepts.html index b18ce3bb5..a7dd3060b 100644 --- a/doc/graph_concepts.html +++ b/doc/graph_concepts.html @@ -396,7 +396,7 @@

      demonstrates using the out_edges(), source(), and target() with an undirected graph. The source code for this example and the following one can be found in examples/undirected.cpp. +href="../example/undirected_adjacency_list.cpp">example/undirected_adjacency_list.cpp.

      diff --git a/example/undirected_adjacency_list.cpp b/example/undirected_adjacency_list.cpp
      index 97b14d990..49d312021 100644
      --- a/example/undirected_adjacency_list.cpp
      +++ b/example/undirected_adjacency_list.cpp
      @@ -26,12 +26,12 @@ undirected_graph_demo1()
         add_edge(zero, two, undigraph);
         add_edge(one, two, undigraph);
       
      -  std::cout << "out_edges(0): ";
      +  std::cout << "out_edges(0):";
         for (boost::tie(out, out_end) = out_edges(zero, undigraph); out != out_end; ++out)
      -    std::cout << *out;
      -  std::cout << std::endl << "in_edges(0): ";
      +    std::cout << ' ' << *out;
      +  std::cout << std::endl << "in_edges(0):";
         for (boost::tie(in, in_end) = in_edges(zero, undigraph); in != in_end; ++in)
      -    std::cout << *in;
      +    std::cout << ' ' << *in;
         std::cout << std::endl;
       }
       
      @@ -91,6 +91,14 @@ undirected_graph_demo2()
       #endif
         std::cout << "weight[(u,v)] = " << get(weight, e1) << std::endl;
         std::cout << "weight[(v,u)] = " << get(weight, e2) << std::endl;
      +
      +  std::cout << "the edges incident to v: ";
      +  typename boost::graph_traits::out_edge_iterator e, e_end;
      +  typename boost::graph_traits::vertex_descriptor 
      +    s = vertex(0, undigraph);
      +  for (boost::tie(e, e_end) = out_edges(s, undigraph); e != e_end; ++e)
      +    std::cout << "(" << source(*e, undigraph) 
      +              << "," << target(*e, undigraph) << ")" << std::endl;
       }
       
       
      @@ -103,7 +111,7 @@ main()
         typedef adjacency_list < vecS, vecS, directedS,
           no_property, Weight > DirectedGraph;
         undirected_graph_demo1 < UndirectedGraph > ();
      -  undirected_graph_demo2 < UndirectedGraph > ();
         directed_graph_demo < DirectedGraph > ();
      +  undirected_graph_demo2 < UndirectedGraph > ();
         return 0;
       }
      diff --git a/example/undirected_adjacency_list.expected b/example/undirected_adjacency_list.expected
      index 015a7afc9..b02c64016 100644
      --- a/example/undirected_adjacency_list.expected
      +++ b/example/undirected_adjacency_list.expected
      @@ -1,3 +1,5 @@
      +out_edges(0): (0,1) (0,2)
      +in_edges(0): (1,0) (2,0)
       in a directed graph is (u,v) == (v,u) ? 0
       weight[(u,v)] = 1.2
       weight[(v,u)] = 2.4
      
      From f53d02e0eb52ebf2f6b41a7a6c4de010c54eaa58 Mon Sep 17 00:00:00 2001
      From: Jeremiah Willcock 
      Date: Sun, 16 Dec 2012 01:51:51 +0000
      Subject: [PATCH 251/333] Added updates from Flavio De Lorenzi to
       vf2_sub_graph_iso code
      
      [SVN r82007]
      ---
       doc/vf2_sub_graph_iso.html                  | 391 +++++++---------
       doc/vf2_sub_graph_iso_impl.pdf              | Bin 123602 -> 0 bytes
       doc/vf2_sub_graph_iso_impl.tex              | 474 --------------------
       example/Jamfile.v2                          |   4 -
       example/vf2_random_graphs.sce               |  96 ----
       example/vf2_sub_graph_iso_csr_example.cpp   |  45 --
       example/vf2_sub_graph_iso_example.cpp       |  13 +-
       example/vf2_sub_graph_iso_grd_example.cpp   |  36 --
       example/vf2_sub_graph_iso_gviz_example.cpp  | 143 ------
       example/vf2_sub_graph_iso_multi_example.cpp |  92 +---
       example/vf2_sub_graph_iso_undir_example.cpp |  73 ---
       include/boost/graph/vf2_sub_graph_iso.hpp   | 355 +++++++--------
       test/Jamfile.v2                             |   1 +
       test/vf2_sub_graph_iso_test.cpp             | 293 ++++++++++++
       14 files changed, 630 insertions(+), 1386 deletions(-)
       delete mode 100755 doc/vf2_sub_graph_iso_impl.pdf
       delete mode 100755 doc/vf2_sub_graph_iso_impl.tex
       delete mode 100755 example/vf2_random_graphs.sce
       delete mode 100755 example/vf2_sub_graph_iso_csr_example.cpp
       delete mode 100755 example/vf2_sub_graph_iso_grd_example.cpp
       delete mode 100755 example/vf2_sub_graph_iso_gviz_example.cpp
       delete mode 100755 example/vf2_sub_graph_iso_undir_example.cpp
       create mode 100644 test/vf2_sub_graph_iso_test.cpp
      
      diff --git a/doc/vf2_sub_graph_iso.html b/doc/vf2_sub_graph_iso.html
      index 5e90424f4..a1667ffea 100755
      --- a/doc/vf2_sub_graph_iso.html
      +++ b/doc/vf2_sub_graph_iso.html
      @@ -34,31 +34,31 @@
           C++ Boost
           

      - vf2_sub_graph_iso + vf2_subgraph_iso

       // all defaults interface
       template <typename GraphSmall,
                 typename GraphLarge,
      -          typename SubGraphIsoMapCallBack>
      -bool vf2_sub_graph_iso(const GraphSmall& graph_small,
      -                       const GraphLarge& graph_large, 
      -                       SubGraphIsoMapCallBack user_callback)
      +          typename SubGraphIsoMapCallback>
      +bool vf2_subgraph_iso(const GraphSmall& graph_small,
      +                      const GraphLarge& graph_large, 
      +                      SubGraphIsoMapCallback user_callback)
       
       
       // named parameter version
       template <typename GraphSmall,
                 typename GraphLarge,
                 typename VertexOrderSmall,
      -          typename SubGraphIsoMapCallBack,
      +          typename SubGraphIsoMapCallback,
                 typename Param,
                 typename Tag,
                 typename Rest>
      -bool vf2_sub_graph_iso(const GraphSmall& graph_small,
      -                       const GraphLarge& graph_large,
      -                       SubGraphIsoMapCallBack user_callback,
      -                       const VertexOrderSmall& vertex_order_small,
      -                       const bgl_named_params<Param, Tag, Rest>& params)
      +bool vf2_subgraph_iso(const GraphSmall& graph_small,
      +                      const GraphLarge& graph_large,
      +                      SubGraphIsoMapCallback user_callback,
      +                      const VertexOrderSmall& vertex_order_small,
      +                      const bgl_named_params<Param, Tag, Rest>& params)
       
       
       // non-named parameter version
      @@ -67,17 +67,17 @@ 

      typename IndexMapSmall, typename IndexMapLarge, typename VertexOrderSmall, - typename EdgeCompatibilityPredicate, - typename VertexCompatibilityPredicate, - typename SubGraphIsoMapCallBack> -bool vf2_sub_graph_iso(const GraphSmall& graph_small, - const GraphLarge& graph_large, - SubGraphIsoMapCallBack user_callback, - IndexMapSmall index_map_small, - IndexMapLarge index_map_large, - const VertexOrderSmall& vertex_order_small, - EdgeCompatibilityPredicate edge_comp, - VertexCompatibilityPredicate vertex_comp) + typename EdgeEquivalencePredicate, + typename VertexEquivalencePredicate, + typename SubGraphIsoMapCallback> +bool vf2_subgraph_iso(const GraphSmall& graph_small, + const GraphLarge& graph_large, + SubGraphIsoMapCallback user_callback, + IndexMapSmall index_map_small, + IndexMapLarge index_map_large, + const VertexOrderSmall& vertex_order_small, + EdgeEquivalencePredicate edge_comp, + VertexEquivalencePredicate vertex_comp)

      An isomorphism between two graphs G1=(V1, E1) @@ -91,14 +91,17 @@

      This function finds all graph-subgraph isomorphism mappings between graphs graph_small and graph_large and outputs them to - user_callback. It continues until user_callback - returns true or the search space has been fully explored. - EdgeCompatibilityPredicate and - VertexCompatibilityPredicate predicates are used to test whether - edges and vertices are compatible. To use property maps for equivalence, + user_callback. It continues until user_callback + returns true or the search space has been fully explored. vf2_subgraph_iso + returns true if a graph-subgraph isomorphism exists and false otherwise. + EdgeEquivalencePredicate and + VertexEquivalencePredicate predicates are used to test whether + edges and vertices are equivalent. To use property maps for equivalence, look at the - make_property_map_compatible - function. By default always_compatible is used, which returns + + make_property_map_equivalent + function. By default + always_equivalent is used, which returns true for any pair of vertices or edges.

      @@ -116,9 +119,7 @@

      the vertex pairs that are candidates to be added to the current state s. If a pair of vertices (v, w) is feasible, the mapping is extended and the associated successor state s' is computed. - The whole procedure is then repeated for state s'. A somewhat more - detailed description of the current implementation is given in the file - vf2_sub_graph_iso_impl.pdf. + The whole procedure is then repeated for state s'.

      Where Defined

      @@ -134,7 +135,7 @@

      Parameters

      The (first) smaller graph (fewer vertices) of the pair to be tested for isomorphism. The type GraphSmall must be a model of - Vertex List Graph + Vertex List Graph, Edge List Graph, Bidirectional Graph and Adjacency Matrix. @@ -144,13 +145,13 @@

      Parameters

      The (second) larger graph to be tested. Type GraphLarge must be a model of - Vertex List Graph + Vertex List Graph, Edge List Graph, Bidirectional Graph and Adjacency Matrix.
      - OUT: SubGraphIsoMapCallBack user_callback + OUT: SubGraphIsoMapCallback user_callback
      A function object to be called when a graph-subgraph isomorphism has been discovered. The operator() must have following form: @@ -163,7 +164,7 @@

      Parameters

      and CorresondenceMap2To1 types are models of Readable Property Map and map equivalent vertices across the two - graphs given to vf2_sub_graph_iso (or vf2_graph_iso. For + graphs given to vf2_subgraph_iso (or vf2_graph_iso. For instance, if v is from graph_small, w is from graph_large, and the vertices can be considered equivalent, @@ -176,8 +177,7 @@

      Parameters

      Returning false from the callback will abort the search immediately. Otherwise, the entire search space will be explored. A "default" print callback - is provided as a utility function and another one is - given in Example 2. + is provided as a utility function.
      IN: const VertexOrderSmall& vertex_order_small @@ -189,7 +189,7 @@

      Parameters

      with value type graph_traits<GraphSmall>::vertex_descriptor.
      - Default The vertices are ordered by multiplicity of in/out degree. + Default The vertices are ordered by multiplicity of in/out degrees.

      Named Parameters

      @@ -212,32 +212,32 @@

      Named Parameters

      Default: get(vertex_index, graph_large) - IN: edges_equivalent(EdgeCompatibilityPredicate edge_comp) + IN: edges_equivalent(EdgeEquivalencePredicate edge_comp)
      This function object is used to determine if edges between the two graphs - graph_small and graph_large are compatible. - Type EdgeCompatiblePredicate must be a model of - of Binary + graph_small and graph_large are equivalent. + Type EdgeEquivalencePredicate must be a model of + Binary Predicate and have argument types of graph_traits<GraphSmall>::edge_descriptor and graph_traits<GraphLarge>::edge_descriptor. A return value of true - indicates that the edges are compatible. + indicates that the edges are equivalent.
      - Default: always_compatible + Default: always_equivalent
      - IN: vertices_equivalent(VertexCompatibilityPredicate vertex_comp) + IN: vertices_equivalent(VertexEquivalencePredicate vertex_comp)
      This function object is used to determine if vertices between the two graphs - graph_small and graph_large are compatible. - Type VertexCompatiblePredicate must be a model of + graph_small and graph_large are equivalent. + Type VertexEquivalencePredicate must be a model of Binary Predicate and have argument types of graph_traits<GraphSmall>::vertex_descriptor and graph_traits<GraphLarge>::vertex_descriptor. A return value of true - indicates that the vertices are compatible. + indicates that the vertices are equivalent.
      - Default: always_compatible + Default: always_equivalent

      Related Functions

      @@ -245,77 +245,66 @@

      Related Functions

      Non-named parameter, named-parameter and all default parameter versions of function

      -
      +    
       vf2_graph_iso(...)
      -    
      +

      for isomorphism testing take the same parameters as the corresponding - functions vf2_sub_graph_iso for sub-graph isomorphism testing. + functions vf2_subgraph_iso for subgraph isomorphism testing. The algorithm finds all isomorphism mappings between graphs graph1 and graph2 and outputs them to user_callback. It continues until user_callback returns true or the search space has been fully explored. As before, - EdgeCompatibilityPredicate and - VertexCompatibilityPredicate predicates are used to test - whether edges and vertices are compatible with - always_compatible as default. + EdgeEquivalencePredicate and + VertexEquivalencePredicate predicates are used to test + whether edges and vertices are equivalent. By default + always_equivalent as used.

      Utility Functions and Structs

      -
      -template <typename PropertyMap1,
      -          typename PropertyMap2>
      -property_map_compatible<PropertyMap1, PropertyMap2>
      -make_property_map_compatible(const PropertyMap1 property_map1,
      -                             const PropertyMap2 property_map2) 
      -    
      -
      - Returns a binary predicate function object - (property_map_compatible<PropertyMap1, PropertyMap2>) that compares - vertices or edges between graphs using property maps. -
      - - struct always_compatible -
      - A binary function object that returns true for any pair of items. -
      - -
      -template <typename Graph1,
      +    
      +template<typename Graph1,
                 typename Graph2>
       struct vf2_print_callback
      -    
      +
      Callback function object that prints out the correspondences between vertices of Graph1 and Graph2. The constructor takes the two graphs G1 - and G2 and an optional bool parameter as arguments. If the latter is - set to true, the callback function will verify the mapping before outputting - it to standard output. + and G2. +
      + +
      +template<typename Graph>
      +std::vector<typename graph_traits<Graph>::vertex_descriptor>
      +  vertex_order_by_mult(const Graph& graph) 
      +    
      +
      + Returns a vector containing the vertices of a graph, sorted by multiplicity of in/out degrees.
      -// Variant of verify_sub_graph_iso with all default parameters
      +// Variant of verify_subgraph_iso with all default parameters
       template<typename Graph1,
                typename Graph2,
                typename CorresponenceMap1To2>
      -inline bool verify_vf2_sub_graph_iso(const Graph1& graph1, const Graph2& graph2, 
      -                                     const CorresponenceMap1To2 f)
      +inline bool verify_vf2_subgraph_iso(const Graph1& graph1, const Graph2& graph2, 
      +                                    const CorresponenceMap1To2 f)
       
       
       // Verifies a graph (sub)graph isomorphism map 
       template<typename Graph1,
                typename Graph2,
                typename CorresponenceMap1To2,
      -         typename EdgeCompatibilityPredicate,
      -         typename VertexCompatibilityPredicate>
      -inline bool verify_vf2_sub_graph_iso(const Graph1& graph1, const Graph2& graph2, 
      -                                     const CorresponenceMap1To2 f,
      -                                     EdgeCompatibilityPredicate edge_comp, 
      -                                     VertexCompatibilityPredicate vertex_comp) 
      +         typename EdgeEquivalencePredicate,
      +         typename VertexEquivalencePredicate>
      +inline bool verify_vf2_subgraph_iso(const Graph1& graph1, const Graph2& graph2, 
      +                                    const CorresponenceMap1To2 f,
      +                                    EdgeEquivalencePredicate edge_comp, 
      +                                    VertexEquivalencePredicate vertex_comp) 
           
      This function can be used to verify a (sub)graph isomorphism mapping f. The parameters are -akin to function vf2_sub_graph_iso (vf2_graph_iso). +analogous to function vf2_subgraph_iso (vf2_graph_iso).
      @@ -333,12 +322,12 @@

      Example 1

      In the example below, a small graph graph1 and a larger graph graph2 are defined. Here small and large refers to the number of - vertices of the graphs. vf2_sub_graph_iso computes all the - sub-graph isomorphism mappings between the two graphs and outputs them + vertices of the graphs. vf2_subgraph_iso computes all the + subgraph isomorphism mappings between the two graphs and outputs them via callback.

      -typedef adjacency_list<vecS, vecS, bidirectionalS> graph_type;
      +typedef adjacency_list<setS, vecS, bidirectionalS> graph_type;
       
       // Build graph1
       int num_vertices1 = 8; graph_type graph1(num_vertices1);
      @@ -353,12 +342,14 @@ 

      Example 1

      add_edge(1, 5, graph2); add_edge(1, 7, graph2); add_edge(2, 4, graph2); add_edge(2, 7, graph2); add_edge(2, 8, graph2); add_edge(3, 4, graph2); add_edge(3, 5, graph2); add_edge(3, 6, graph2); - -// true instructs callback to verify a map using -// verify_vf2_sub_graph_iso -vf2_print_callback<graph_type, graph_type> callback(graph1, graph2, true); - -bool ret = vf2_sub_graph_iso(graph1, graph2, callback); + +// Create callback to print mappings +vf2_print_callback<graph_type, graph_type> callback(graph1, graph2); + + +// Print out all subgraph isomorphism mappings between graph1 and graph2. +// Vertices and edges are assumed to be always equivalent. +vf2_subgraph_iso(graph1, graph2, callback);

      The complete example can be found under @@ -368,160 +359,80 @@

      Example 1

      Example 2

      - This example uses the GraphViz input parser, i.e. read_graphviz - function to interpret the two graphs specified in files graph_small.dot and graph_large.dot - using the using the GraphViz DOT language. Sample files are provided - below. vf2_sub_graph_iso computes all the sub-graph isomorphism mappings - between graph_small and graph_large. +

      + In this example, the subgraph isomorphism mappings between multi-graphs are computed. The vertices + and edges of the multi-graphs are differentiated using property maps. +

      -std::ifstream graph_small_file("graph_small.dot");
      -std::ifstream graph_large_file("graph_large.dot");
      -
      -// Vertex properties
      -typedef property <vertex_name_t, std::string> vertex_p;
      -
      -// adjacency_list-based type
      -typedef adjacency_list <vecS, vecS, undirectedS, vertex_p> graph_t;
      -
      -// Construct an empty graph_small and prepare the dynamic_property_maps.
      -graph_t graph_small(0);
      -dynamic_properties dp_small;
      -  
      -property_map<graph_t, vertex_name_t>::type name_small =
      -  get(vertex_name, graph_small);
      -dp_small.property("node_id", name_small);
      -
      -// Read graph_small
      -bool status = read_graphviz(graph_small_file, graph_small, dp_small, "node_id");
      -
      -// Construct an empty graph_large and prepare the dynamic_property_maps,
      -// following the read_graphviz example
      -graph_t graph_large(0);
      -dynamic_properties dp_large;
      -
      -property_map<graph_t, vertex_name_t>::type name_large =
      -  get(vertex_name, graph_large);
      -dp_large.property("node_id", name_large);
      -
      -// Read graph_large
      -status = read_graphviz(graph_large_file, graph_large, dp_large, "node_id");
      -
      -// Create the call_back function
      -typedef property_map<graph_t, vertex_name_t>::type p_map_t;
      -print_callback<graph_t, graph_t, p_map_t, p_map_t> callback(graph_small, graph_large,
      -                                                            name_small, name_large, true);
      - // Compute the sub-graph isomorphism mappings
      -bool ret = vf2_sub_graph_iso(graph_small, graph_large, callback);
      -    
      +// Define edge and vertex properties +typedef property<edge_name_t, char> edge_property; +typedef property<vertex_name_t, char, property<vertex_index_t, int> > vertex_property; + +// Using a vecS graphs => the index maps are implicit. +typedef adjacency_list<vecS, vecS, bidirectionalS, vertex_property, edge_property> graph_type; + +// Create graph1 +graph_type graph1; +// Add vertices... +add_vertex(vertex_property('a'), graph1); +... +//... and edges +add_edge(0, 1, edge_property('b'), graph1); +add_edge(0, 1, edge_property('b'), graph1); +... + +// Create graph2 +graph_type graph2; +add_vertex(vertex_property('a'), graph2); +... +add_edge(0, 1, edge_property('a'), graph2); +... + - To output the mappings using the node names, the following callback function object is created: +

      + To differentiate vertices and edges with property maps, binary predicates are created using the + + make_property_map_equivalent function: +

      -// Define a print_callback
      -template <typename Graph1,
      -          typename Graph2,
      -          typename PropertyMap1,
      -          typename PropertyMap2>
      -struct print_callback {
      -    
      -  print_callback(const Graph1& graph1, const Graph2& graph2, 
      -                 PropertyMap1 p_map1, PropertyMap2 p_map2, 
      -                 bool verify = false) 
      -    : graph1_(graph1), graph2_(graph2), 
      -      p_map1_(p_map1), p_map2_(p_map2),
      -      verify_(verify) {}
      -
      -  template <typename CorrespondenceMap1To2,
      -            typename CorrespondenceMap2To1>
      -  bool operator()(CorrespondenceMap1To2 f, CorrespondenceMap2To1) const {
      -    
      -    if (verify_)
      -      std::cout << "Verify: " << std::boolalpha 
      -                << verify_vf2_sub_graph_iso(graph1_, graph2_, f)
      -                << std::endl;
      -    
      -// Print sub graph isomorphism map
      -    BGL_FORALL_VERTICES_T(v, graph1_, Graph1) 
      -      std::cout << '(' << get(p_map1_,v) << ", " 
      -                << get(p_map2_, get(f, v)) << ") ";
      -    
      -    std::cout << std::endl;
      -      
      -    return true;
      -  }
      -
      -private:
      -  const Graph1& graph1_;
      -  const Graph2& graph2_;
      -  
      -  const PropertyMap1& p_map1_;
      -  const PropertyMap2& p_map2_;
      -  
      -  const bool verify_;
      -};
      +// Create the vertex binary predicate
      +typedef property_map<graph_type, vertex_name_t>::type vertex_name_map_t;
      +typedef property_map_equivalent<vertex_name_map_t, vertex_name_map_t> vertex_comp_t;
      +vertex_comp_t vertex_comp =
      +  make_property_map_equivalent(get(vertex_name, graph1), get(vertex_name, graph2));
      +
      +// Create the vertex binary predicate
      +typedef property_map<graph_type, edge_name_t>::type edge_name_map_t;
      +typedef property_map_equivalent<edge_name_map_t, edge_name_map_t> edge_comp_t;
      +edge_comp_t edge_comp =
      +  make_property_map_equivalent(get(edge_name, graph1), get(edge_name, graph2));
           
      - Using the sample DOT-files graph_small.dot: - -
      -graph G_small {
      -node1 -- node2;
      -node1 -- node3;
      -node3 -- node3;
      -node4 -- node1;
      -node4 -- node3;
      -}
      -    
      - - and graph_large.dot: - +

      + Finally, a callback function object is created and the subgraph isomorphism mappings are + computed: +

      -graph G_large {
      -node1 -- node3;
      -node1 -- node4;
      -node1 -- node6;
      -node2 -- node4;
      -node2 -- node5;
      -node3 -- node3;
      -node4 -- node5;
      -node4 -- node6;
      -node6 -- node6;
      -}
      +// Create callback
      +vf2_print_callback<graph_type, graph_type> callback(graph1, graph2);
      +
      +
      +// Print out all subgraph isomorphism mappings between graph1 and graph2.
      +// Function vertex_order_by_mult is used to compute the order of 
      +// vertices of graph1. That's the order in which the vertices are examined
      +// during the matching process.
      +vf2_subgraph_iso(graph1, graph2, callback, vertex_order_by_mult(graph1),
      +                 edges_equivalent(edge_comp).vertices_equivalent(vertex_comp));
           
      - vf2_sub_graph_iso finds the mappings (node1, node4) (node2, node2) - (node3, node6) (node4, node1) and (node1, node4) (node2, node5) - (node3, node6) (node4, node1). - To compile this example, you will need to build and link against the - "boost_graph" and "boost_regex" libraries - (cf. read_graphviz). -

      -The complete example is provided under -examples/vf2_sub_graph_iso_gviz_example.cpp, -including a Scilab script to generate simple dot-files -examples/vf2_random_graphs.sce. +For the complete example, see +examples/vf2_sub_graph_iso_multi_example.cpp.

      -

      Additional Examples

      - -

      -These are: a multi-graph example -examples/vf2_sub_graph_iso_multi_example.cpp, -
      -one using a compressed_sparse_row_graph (works not for directed because in_edges not available) -examples/vf2_sub_graph_iso_csr_example.cpp, -
      -one putting a grid_graph -examples/vf2_sub_graph_iso_grd_example.cpp -
      -and one matching bidirectional und undirected graphs -examples/vf2_sub_graph_iso_undir_example.cpp. -
      -

      -

      Bibliography

      diff --git a/doc/vf2_sub_graph_iso_impl.pdf b/doc/vf2_sub_graph_iso_impl.pdf deleted file mode 100755 index e68df44a0040ce1e43773f27cc168a7913b7447b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 123602 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 diff --git a/doc/vf2_sub_graph_iso_impl.tex b/doc/vf2_sub_graph_iso_impl.tex deleted file mode 100755 index ecb358e68..000000000 --- a/doc/vf2_sub_graph_iso_impl.tex +++ /dev/null @@ -1,474 +0,0 @@ -\documentclass[12pt]{article} -\usepackage{amsmath} -\usepackage{algorithmicx} -\usepackage{algpseudocode} -\usepackage{listings} - -% abbreviations and acronyms -\def\etal{{et al.\ }} -\def\eg{{\it e.g.\ }} -\def\etc{{\it etc.\ }} -\def\ie{{\it i.e.\ }} -\def\cf{{\it cf.\ }} - -\title{An Implementation of the {\sc VF2} (Sub)Graph Isomorphism Algorithm -Using The Boost Graph Library} -\author{Flavio De Lorenzi\thanks{E-mail: fdlorenzi@gmail.com}} - -\date{\today} - -\begin{document} -\maketitle -%\VerbatimFootnotes - -\begin{abstract} -This article describes an implementation of the {\sc VF2} algorithm, introduced -by Cordella \etal for solving the graph isomorphism and graph-subgraph -isomorphism problems, using the Boost Graph Library. This implementation -includes algorithmic improvements to account for self-loops and works for -directed and undirected graphs. -\end{abstract} - -\baselineskip=\normalbaselineskip - -%\newpage - -\section{Introduction} -This section briefly outlines the {\sc VF2} algorithm\footnote{The original -code by Pasquale Foggia and collaborators can be obtained from: -\texttt{http://www.cs.sunysb.edu/{\textasciitilde}algorith/implement/vflib/implement.shtml}}, -following closely \cite{cordella+2001, cordella+2004}. - -An isomorphism between two graphs $G_1=(V_1, E_1)$ and $G_2=(V_2, E_2)$ is a -bijective mapping $M$ of the vertices of one graph to vertices of the other -graph that preserves the edge structure of the graphs. $M$ is said to be a -graph-subgraph isomorphism iff $M$ is an isomorphism between $G_1$ and a -subgraph of $G_2$. - -A matching process between the two graphs $G_1$ and $G_2$ determines the -isomorphism mapping $M$ which associates vertices of $G_1$ with vertices of -$G_2$ and vice versa. The matching process can be described by means of a -state space representation combined with a depth-first strategy. The details -can be found in \cite{cordella+2001, cordella+2004} and references therein. - -Cordella \etal give the following high-level description of the matching -algorithm: - -\begin{algorithmic} -\Procedure{Match}{$s$} -\If {$M(s)$ covers all the nodes of $G_2$} - \State \Return $M(s)$ -\Else - \State Compute the set $P(s)$ of the pairs of vertices for inclusion in $M(s)$ - \ForAll {$(v,w) \in P(s)$} - \If {$F(s,v,w)$} - \State Compute the state $s'$ obtained by adding $(v,w)$ to $M(s)$ - \State \Call {Match}{$s'$} - \EndIf - \EndFor - \State Restore data structures -\EndIf -\EndProcedure -\end{algorithmic} - -$M(s)$ is a partial mapping associated with a state $s$, $P(s)$ is the set -of all possible pairs of vertices $(v,w)$ to be added to the current state $s$ -and $F(s,v,w)$ is a boolean function (called {\em feasibility function}) used -to prune the search tree. If its value is {\em true} the state $s'$ obtained -by adding $(v,w)$ to $s$ is guaranteed to be a partial isomorphism if $s$ is. - -% \subsubsection*{State Space Representation} - -To construct $P(s)$ and $F(s,v,w)$ Cordella \etal define the -{\em out-terminal set} as the set of vertices of $G_1$ that are not in $M(s)$ -but are successors of vertices in $M(s)$ (connected by out edges), and the -{\em in-terminal set} as the set of vertices that are not in $M(s)$ but are -predecessors of vertices in $M(s)$. Analogue sets are defined for $G_2$. - -% \subsubsection*{Data Structures} - -To compute $P(s)$ and $F(s,v,w)$ efficiently, Cordella \etal employ the -following data structures: - -\begin{itemize} - -\item Vectors \verb+core_1+ and \verb+core_2+ whose dimensions correspond to -the number of vertices in $G_1$ and $G_2$, respectively. These vectors store the -present mapping. - -\item Vectors \verb+in_1+, \verb+out_1+, \verb+in_2+ and \verb+out_2+ used to -describe the membership to the terminal sets. \verb+in_1+ is non-zero for a -particular vertex if the vertex is either in the partial mapping $M(s)$ or -belongs to the in-terminal state of $G_1$. The actual value is given by the -level of the depth-first search tree at which the vertex was included in the -corresponding set. - -\end{itemize} - - -\section{Implementation} - -The computations of the terminal sets or the addition (deletion) of a pair of -vertices to (from) a state are analogous for the two graphs $G_1$ and $G_2$. -For example, to add the vertex pair $(v, w)$ with $v \in V_1$ and $w \in V_2$ -to vector \verb+core_1+ is the same as adding $(w, v)$ to \verb+core_2+. This -observation suggests the following improvement to the original {\sc VF2} -implementation. Instead of implementing a state for $G_1$ and $G_2$ with -associated vectors \verb+core_1+, \verb+core_2+, \verb+in_1+, \verb+out_1+, -\verb+in_2+ and \verb+out_2+ directly, we implement a ``helper state'' class -\verb+base_state+ associated with a single graph. Class \verb+base_state+ then -contains \verb+core_+, \verb+in_+ and \verb+out_+, and member functions such as -%\eg \verb+push(const vertex_this_type& v_this, const vertex_other_type& v_other)+ -\eg \texttt{push(const vertex \_this\_type\& v\_this, const vertex\_other\_type\& v\_other)} -to add a vertex pair. The actual state associated with both graphs (implemented in -class \verb+state+) can thus be constructed using two ``helper states'', one -for each graph. For instance, the member function \verb+push+ to add a pair of -vertices to the actual state is obtained as illustrated in the code -fragment below: - -\lstset{breaklines=true, breakatwhitespace=true} -\lstset{columns=fullflexible} -\lstset{language=C++} -\begin{lstlisting} - -class state -{ - - ... - - base_state state1_; - base_state state2_; - -public: - // Add vertex pair to the state - void push(const vertex1_type& v, const vertex2_type& w) - { - state1_.push(v, w); - state2_.push(w, v); - } - - ... - -}; -\end{lstlisting} - -These classes (\verb+base_state+ and \verb+state+) and the non-recursive -matching procedure \verb+match+ are all members of namespace \verb+boost::detail+. - -The functions of the public interface are all defined in namespace \verb+boost+ and their -documentation will follow in the sections bellow. - -\subsection{Functions for Graph Sub-Graph Isomorphism Testing} - -\begin{lstlisting} -// Non-named parameter version -template -bool vf2_sub_graph_iso(const GraphSmall& graph_small, - const GraphLarge& graph_large, - SubGraphIsoMapCallBack user_callback, - IndexMapSmall index_map_small, - IndexMapLarge index_map_large, - const VertexOrderSmall& vertex_order_small, - EdgeCompatibilityPredicate edge_comp, - VertexCompatibilityPredicate vertex_comp) -\end{lstlisting} - - -\begin{lstlisting} -// Named parameter interface of vf2_sub_graph_iso -template -bool vf2_sub_graph_iso(const GraphSmall& graph_small, - const GraphLarge& graph_large, - SubGraphIsoMapCallBack user_callback, - const VertexOrderSmall& vertex_order_small, - const bgl_named_params& params) -\end{lstlisting} - - -\begin{lstlisting} -// All default interface for vf2_sub_graph_iso -template -bool vf2_sub_graph_iso(const GraphSmall& graph_small, - const GraphLarge& graph_large, - SubGraphIsoMapCallBack user_callback) -\end{lstlisting} - -This algorithm finds all graph-subgraph isomorphism mappings between graphs -\verb+graph_small+ and \verb+graph_large+ and outputs them to \verb+user_callback+. -It continues until \verb+user_callback+ returns true or the search space has -been fully explored.\\ -\verb+EdgeCompatibilityPredicate+ and \verb+VertexCompatibilityPredicate+ -predicates are used to test whether edges and vertices are compatible. -By default \verb+always_compatible+ is used, which returns true for any pair of -vertices or edges. - -\subsubsection*{Parameters} - -\begin{itemize} - -\item[IN:] \verb+const GraphSmall& graph_small+ The (first) smaller graph (fewer vertices) -of the pair to be tested for isomorphism. The type \verb+GraphSmall+ must be a -model of {\em Vertex List Graph}, {\em Bidirectional Graph}, {\em Edge List -Graph} and {\em Adjacency Matrix}. - - -\item[IN:] \verb+const GraphLarge& graph_large+ The (second) larger graph to be tested. -Type \verb+GraphLarge+ must be a model of -{\em Vertex List Graph}, {\em Bidirectional Graph}, {\em Edge List Graph} and -{\em Adjacency Matrix}. - -\item[OUT:] \verb+SubGraphIsoMapCallBack user_callback+ A function object to be -called when a graph-subgraph isomorphism has been discovered. The -\verb+operator()+ must have following form: -\begin{lstlisting} -template -bool operator()(CorrespondenceMap1To2 f, CorrespondenceMap2To1 g) const -\end{lstlisting} - -Both the \verb+CorrespondenceMap1To2+ and \verb+CorresondenceMap2To1+ types -are models of {\em Readable Property Map} and map equivalent vertices across -the two graphs given to \verb+vf2_sub_graph_iso+ (or \verb+vf2_graph_iso+). An -example is given below. - -Returning false from the callback will abort the search immediately. Otherwise, -the entire search space will be explored. - - -\item[IN:] \verb+const VertexOrderSmall& vertex_order_small+ The ordered -vertices of the smaller graph \verb+graph_small+. During the matching process the -vertices are examined in the order given by \verb+vertex_order_small+. Type -\verb+VertexOrderSmall+ must be a model of \verb+ContainerConcept+ with value -type \verb+graph_traits::vertex_descriptor+. -\\ -{\em Default:} The vertices are ordered by multiplicity of in/out degree. - -\end{itemize} - -\subsubsection*{Named Parameters} - -\begin{itemize} - -\item[IN:] \verb+vertex_index1(IndexMapSmall index_map_small)+ -This maps each vertex to an integer in the range \verb+[0, num_vertices(graph_small))+. -\\Type \verb+IndexMapSmall+ must be a model of {\em Readable Property Map}. -\\ -{\em Default:} \verb+get(vertex_index, graph_small)+ - -\item[IN:] \verb+vertex_index2(IndexMapLarge index_map_large)+ -This maps each vertex to an integer in the range \verb+[0, num_vertices(graph_large))+. -\\Type \verb+IndexMapLarge+ must be a model of {\em Readable Property Map}. -\\ -{\em Default:} \verb+get(vertex_index, graph_large)+ - -\item[IN:] \verb+edges_equivalent(EdgeCompatibilityPredicate edge_comp)+ -This function object is used to determine if edges between the two graphs -\verb+graph_small+ and \verb+graph_large+ are compatible.\\ -Type \verb+EdgeCompatiblePredicate+ must be a model of {\em Binary -Predicate} and have argument types of -\verb+graph_traits::edge_descriptor+ and -\verb+graph_traits::edge_descriptor+. A return value of true -indicates that the edges are compatible.\\ -{\em Default:} \verb+always_compatible+ - -\item[IN:] \verb+vertices_equivalent(VertexCompatibilityPredicate vertex_comp)+ -This function object is used to determine if vertices between the two graphs -\verb+graph_small+ and \verb+graph_large+ are compatible.\\ -Type \verb+VertexCompatiblePredicate+ must be a model of {\em Binary -Predicate} and have argument types of\\ -\verb+graph_traits::vertex_descriptor+ and\\ -\verb+graph_traits::vertex_descriptor+. A return value of true -indicates that the vertices are compatible. -\\ -{\em Default:} \verb+always_compatible+ - -\end{itemize} - - -\subsection{Functions for Isomorphism Testing} - -Non-named parameter, named-parameter and all default parameter versions of -function -\begin{lstlisting} -vf2_graph_iso(...) -\end{lstlisting} - -for isomorphism testing take the same parameters as the corresponding -functions \verb+vf2_sub_graph_iso+. The algorithm finds all isomorphism -mappings between graphs \verb+graph1+ and \verb+graph2+ and outputs them to -\verb+user_callback+. It continues until \verb+user_callback+ returns true -or the search space has been fully explored. As before, -\verb+EdgeCompatibilityPredicate+ and\\ -\verb+VertexCompatibilityPredicate+ -predicates are used to test whether edges and vertices are compatible with -\verb+always_compatible+ as default. - -\subsection{Utility Functions and Structs} - -\begin{lstlisting} -template -property_map_compatible -make_property_map_compatible(const PropertyMap1 property_map1, - const PropertyMap2 property_map2) -\end{lstlisting} -Returns a binary predicate function object \\ -(\verb+property_map_compatible+) that compares -vertices or edges between graphs using property maps. - - -\begin{lstlisting} -struct always_compatible -\end{lstlisting} -A binary function object that returns true for any pair of items. - - -\begin{lstlisting} -template -struct vf2_print_callback -\end{lstlisting} -Callback function object that prints out the correspondences between vertices -of \verb+Graph1+ and \verb+Graph2+. The constructor takes the two graphs $G_1$ -and $G_2$ and an optional \verb+bool+ parameter as arguments. If the latter is -set to \verb+true+, the callback function will verify the mapping before outputting -it to standard output. - -\begin{lstlisting} -// Verifies a graph (sub)graph isomorphism map -template -inline bool verify_vf2_sub_graph_iso(const Graph1& graph1, - const Graph2& graph2, - const CorresponenceMap1To2 f, - EdgeCompatibilityPredicate edge_comp, - VertexCompatibilityPredicate vertex_comp) -\end{lstlisting} - - -\begin{lstlisting} -// Variant of verify_sub_graph_iso with all default parameters -template -inline bool verify_vf2_sub_graph_iso(const Graph1& graph1, - const Graph2& graph2, - const CorresponenceMap1To2 f) -\end{lstlisting} - -This function can be used to verify a (sub)graph isomorphism mapping {\em f}. -The parameters are akin to function \verb+vf2_sub_graph_iso+ -(\verb+vf2_graph_iso+). - - -\subsection{Complexity} - -Spatial and time complexity are given in \cite{cordella+2004}. The spatial -complexity of {\sc VF2} is of order $O(V)$, where $V$ is the (maximum) number -of vertices of the two graphs. Time complexity is $O(V^2)$ in the best case and -$O(V!V)$ in the worst case. - -\subsection{A Graph Sub-Graph Isomorphism Example} - -In the example below, a small graph \verb+graph1+ and a larger graph -\verb+graph2+ are defined. \\ \verb+vf2_sub_graph_iso+ computes all the -mappings between the two graphs and outputs them via \verb+callback+. - - -\begin{lstlisting} -typedef adjacency_list graph_type; - -// Build graph1 -int num_vertices1 = 8; graph_type graph1(num_vertices1); -add_edge(0, 6, graph1); add_edge(0, 7, graph1); -add_edge(1, 5, graph1); add_edge(1, 7, graph1); -add_edge(2, 4, graph1); add_edge(2, 5, graph1); add_edge(2, 6, graph1); -add_edge(3, 4, graph1); - -// Build graph2 -int num_vertices2 = 9; graph_type graph2(num_vertices2); -add_edge(0, 6, graph2); add_edge(0, 8, graph2); -add_edge(1, 5, graph2); add_edge(1, 7, graph2); -add_edge(2, 4, graph2); add_edge(2, 7, graph2); add_edge(2, 8, graph2); -add_edge(3, 4, graph2); add_edge(3, 5, graph2); add_edge(3, 6, graph2); - -// true instructs callback to verify a map using -// verify_vf2_sub_graph_iso -vf2_print_callback callback(graph1, graph2, true); - -bool ret = vf2_sub_graph_iso(graph1, graph2, callback); -\end{lstlisting} - -\appendix -\section{Testing} - -Also included are \verb+vf2_sub_graph_iso_gviz_example.cpp+ and a Scilab \newline -(\verb+http://www.scilab.org/+) script \verb+vf2_random_graphs.sce+ for testing the -implementation. The script generates pairs of simple graphs of (possibly) different -size, such that there exists at least one (sub)graph isomorphism mapping -between the two graphs. The graphs are written to files \verb+graph_small.dot+ -and \verb+graph_large.dot+ using the Graphviz {\em DOT} language -(\verb+http://www.graphviz.org+). The following parameters can be used to -control the output: - -\begin{itemize} - -\item \verb+nbig+ Dimension of the large adjacency matrix -\item \verb+nsmall+ Dimension of the small adjacency matrix -\item \verb+density+ Density of the non-zero entries (of an initial square -matrix with dimension \verb+nbig+) -\item \verb+directed+ If set to one, a pair of directed graphs is generated, -otherwise undirected graphs are produced. -\item \verb+loops+ If set to one, self-loops are allowed, otherwise self-loops -are excluded. -\end{itemize} - -The generated dot-files specifying the graphs can be given as command line -arguments to the executable test program, which uses boost's GraphViz input -parser to build the graphs. The graphs are then tested for (sub)graph -isomorphism. The isomorphism mappings are verified and written to standard -output. - -To build the test executable, you will need to build and link against the -"boost\_graph" and "boost\_regex" libraries, \cf also \verb+read_graphviz+. - -%%%%%%%%%%%%%%% -% Bibliography -%%%%%%%%%%%%%% -\begin{thebibliography}{10} - -\bibitem{cordella+2001} L. P. Cordella, P. Foggia, C. Sansone, and M. Vento, - ``An improved algorithm for matching large graphs,'' \emph{In: 3rd IAPR-TC15 - Workshop on Graph-based Representations in Pattern Recognition, Cuen}, - pp. 149--159, 2001. - -\bibitem{cordella+2004} L. P. Cordella, P. Foggia, C. Sansone, and M. Vento, - ``A (Sub)Graph Isomorphism Algorithm for Matching Large Graphs,'' - \emph{IEEE Trans. Pattern Anal. Mach. Intell.}, vol. 26, no. 10, - pp. 1367--1372, 2004 - -\end{thebibliography} - - -\end{document} diff --git a/example/Jamfile.v2 b/example/Jamfile.v2 index 55f4caf9c..6d7d62f6a 100644 --- a/example/Jamfile.v2 +++ b/example/Jamfile.v2 @@ -44,10 +44,6 @@ exe strong_components : strong_components.cpp ../build//boost_graph ; exe strong-components : strong-components.cpp ; exe subgraph : subgraph.cpp ; exe subgraph_properties : subgraph_properties.cpp ; -exe vf2_sub_graph_iso_csr_example : vf2_sub_graph_iso_csr_example.cpp ; exe vf2_sub_graph_iso_example : vf2_sub_graph_iso_example.cpp ; -exe vf2_sub_graph_iso_grd_example : vf2_sub_graph_iso_grd_example.cpp ; -exe vf2_sub_graph_iso_gviz_example : vf2_sub_graph_iso_gviz_example.cpp ../build//boost_graph ; exe vf2_sub_graph_iso_multi_example : vf2_sub_graph_iso_multi_example.cpp ; -exe vf2_sub_graph_iso_undir_example : vf2_sub_graph_iso_undir_example.cpp ; diff --git a/example/vf2_random_graphs.sce b/example/vf2_random_graphs.sce deleted file mode 100755 index e29a3bc9c..000000000 --- a/example/vf2_random_graphs.sce +++ /dev/null @@ -1,96 +0,0 @@ -//======================================================================= -// Copyright (C) 2012 Flavio De Lorenzi (fdlorenzi@gmail.com) -// -// 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) -//======================================================================= - -// A script to generate simple pairs of graphs of (possibly) different -// size, such that there exists (at least) one (sub)graph isomorphism mapping -// between the two graphs. The graphs are written to files graph_small.dot -// and graph_large.dot using the Graphviz DOT language http://www.graphviz.org. -// The following parameters can be used to control the output: -// -// - nbig: Dimension of the large adjacency matrix -// - nsmall: Dimension of the small adjacency matrix -// - density: Density of the non-zero entries (of an initial square -// matrix with dimension nbig) -// - directed: If set to one, a pair of directed graphs is generated, -// otherwise undirected graphs are produced. -// - loops: If set to one, self-loops are allowed, otherwise self-loops -// are excluded. -// -// The generated dot-files specifying the graphs can be given as command line -// arguments to the executable test program (vf2_sub_graph_iso_gviz_example.cpp), -// which uses boost's GraphViz input parser to build the graphs. - -clear; - -directed=0; // Set to 1 to generate a directed graph, otherwise an - // undirected graph is generated - -loops=1; // Set to 1 to allow self-loops, otherwise loops are excluded - -nbig=6; density=0.4; // Size and density of non-zero elements of the large matrix -nsmall=4; // Size of the small matrix: nsmall<=nbig - -// Create a matrix with ~density * nbig^2 non-zero elements -M=full(sprand(nbig, nbig, density, "uniform")); -NZ=find(M<>0); -M(NZ)=1; - -if directed <> 1 then - M=triu(M); -end - -if loops <> 1 then - M=M-eye(M).*M -end - -indices=linspace(1, nbig, nbig)'; - -// Random row and column permutations -indices_perm=grand(1, 'prm', indices); - -M_perm=M(indices_perm, indices_perm); -M_perm=M_perm(1:nsmall, 1:nsmall); - -function write_digraph(file_name, Mat) - fd = mopen(file_name, "w"); - n = size(Mat, "r"); - mfprintf(fd, "digraph G {\n"); - for i = 1:n - for j = 1:n - if Mat(i,j)<>0 then - mfprintf(fd, "node%u -> node%u;\n", i, j); - end - end - end - mfprintf(fd, "}\n"); - mclose(fd); -endfunction - -function write_graph(file_name, Mat) - fd = mopen(file_name, "w"); - n = size(Mat, "r"); - mfprintf(fd, "graph G {\n"); - for i = 1:n - for j = 1:n - if Mat(i,j)<>0 then - mfprintf(fd, "node%u -- node%u;\n", i, j); - end - end - end - mfprintf(fd, "}\n"); - mclose(fd); -endfunction - -// Write graphs: -if directed <> 1 then - write_graph("graph_large.dot", M); - write_graph("graph_small.dot", M_perm); -else - write_digraph("graph_large.dot", M); - write_digraph("graph_small.dot", M_perm); -end diff --git a/example/vf2_sub_graph_iso_csr_example.cpp b/example/vf2_sub_graph_iso_csr_example.cpp deleted file mode 100755 index d60bbaa83..000000000 --- a/example/vf2_sub_graph_iso_csr_example.cpp +++ /dev/null @@ -1,45 +0,0 @@ -//======================================================================= -// Copyright (C) 2012 Flavio De Lorenzi (fdlorenzi@gmail.com) -// -// 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) -//======================================================================= - -#include -#include -#include -using namespace boost; - - -int main() { - typedef adjacency_list graph_raw_t; - - // Build graph_raw1 - int num_vertices1 = 8; graph_raw_t graph_raw1(num_vertices1); - add_edge(0, 6, graph_raw1); add_edge(0, 7, graph_raw1); - add_edge(1, 5, graph_raw1); add_edge(1, 7, graph_raw1); - add_edge(2, 4, graph_raw1); add_edge(2, 5, graph_raw1); add_edge(2, 6, graph_raw1); - add_edge(3, 4, graph_raw1); - - // Build graph_raw2 - int num_vertices2 = 9; graph_raw_t graph_raw2(num_vertices2); - add_edge(0, 6, graph_raw2); add_edge(0, 8, graph_raw2); - add_edge(1, 5, graph_raw2); add_edge(1, 7, graph_raw2); - add_edge(2, 4, graph_raw2); add_edge(2, 7, graph_raw2); add_edge(2, 8, graph_raw2); - add_edge(3, 4, graph_raw2); add_edge(3, 5, graph_raw2); add_edge(3, 6, graph_raw2); - - typedef compressed_sparse_row_graph graph_csr_t; - - graph_csr_t graph1(graph_raw1); - graph_csr_t graph2(graph_raw2); - - // true instructs callback to verify a map using - // verify_vf2_sub_graph_iso - vf2_print_callback callback(graph1, graph2, true); - - bool ret = vf2_sub_graph_iso(graph1, graph2, callback); - (void)ret; - - return 0; -} diff --git a/example/vf2_sub_graph_iso_example.cpp b/example/vf2_sub_graph_iso_example.cpp index ab353cb2a..8e17d2a70 100755 --- a/example/vf2_sub_graph_iso_example.cpp +++ b/example/vf2_sub_graph_iso_example.cpp @@ -12,7 +12,8 @@ using namespace boost; int main() { - typedef adjacency_list graph_type; + + typedef adjacency_list graph_type; // Build graph1 int num_vertices1 = 8; graph_type graph1(num_vertices1); @@ -28,12 +29,12 @@ int main() { add_edge(2, 4, graph2); add_edge(2, 7, graph2); add_edge(2, 8, graph2); add_edge(3, 4, graph2); add_edge(3, 5, graph2); add_edge(3, 6, graph2); - // true instructs callback to verify a map using - // verify_vf2_sub_graph_iso - vf2_print_callback callback(graph1, graph2, true); + // Create callback to print mappings + vf2_print_callback callback(graph1, graph2); - bool ret = vf2_sub_graph_iso(graph1, graph2, callback); - (void)ret; + // Print out all subgraph isomorphism mappings between graph1 and graph2. + // Vertices and edges are assumed to be always equivalent. + vf2_subgraph_iso(graph1, graph2, callback); return 0; } diff --git a/example/vf2_sub_graph_iso_grd_example.cpp b/example/vf2_sub_graph_iso_grd_example.cpp deleted file mode 100755 index b04f29dd6..000000000 --- a/example/vf2_sub_graph_iso_grd_example.cpp +++ /dev/null @@ -1,36 +0,0 @@ -//======================================================================= -// Copyright (C) 2012 Flavio De Lorenzi (fdlorenzi@gmail.com) -// -// 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) -//======================================================================= - -#include -#include -#include -using namespace boost; - - -int main() { - - typedef grid_graph<2> graph_type; - // Build graph1 - // Define dimension lengths, a 2x2 in this case - boost::array lengths1 = { { 2, 2 } }; - graph_type graph1(lengths1); - - // Build graph2 - // Define dimension lengths, a 2x3 in this case - boost::array lengths2 = { { 2, 3 } }; - graph_type graph2(lengths2); - - // true instructs callback to verify a map using - // verify_vf2_sub_graph_iso - vf2_print_callback callback(graph1, graph2, true); - - bool ret = vf2_sub_graph_iso(graph1, graph2, callback); - (void)ret; - - return 0; -} diff --git a/example/vf2_sub_graph_iso_gviz_example.cpp b/example/vf2_sub_graph_iso_gviz_example.cpp deleted file mode 100755 index 002a45b24..000000000 --- a/example/vf2_sub_graph_iso_gviz_example.cpp +++ /dev/null @@ -1,143 +0,0 @@ -//======================================================================= -// Copyright (C) 2012 Flavio De Lorenzi (fdlorenzi@gmail.com) -// -// 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) -//======================================================================= - -#include -#include -#include -#include -using namespace std; - -#include -#include -#include -#include -using namespace boost; - - -// Define a print_callback -template -struct print_callback { - - print_callback(const Graph1& graph1, const Graph2& graph2, - PropertyMap1 p_map1, PropertyMap2 p_map2, - bool verify = false) - : graph1_(graph1), graph2_(graph2), - p_map1_(p_map1), p_map2_(p_map2), - verify_(verify) {} - - template - bool operator()(CorrespondenceMap1To2 f, CorrespondenceMap2To1) const { - - if (verify_) - std::cout << "Verify: " << std::boolalpha - << verify_vf2_sub_graph_iso(graph1_, graph2_, f) - << std::endl; - - // Print sub graph isomorphism map - BGL_FORALL_VERTICES_T(v, graph1_, Graph1) - std::cout << '(' << get(p_map1_,v) << ", " - << get(p_map2_, get(f, v)) << ") "; - - std::cout << std::endl; - - return true; - } - -private: - const Graph1& graph1_; - const Graph2& graph2_; - - const PropertyMap1& p_map1_; - const PropertyMap2& p_map2_; - - const bool verify_; -}; - - -int main(int argc, char** argv) { - - if (argc != 3) { - cerr << "usage: " << argv[0] << " graph_small graph_large" << endl; - return EXIT_FAILURE; - } - ifstream graph_small_file(argv[1]); - ifstream graph_large_file(argv[2]); - if (!graph_small_file || !graph_large_file) { - cerr << "Files not found" << endl; - return EXIT_FAILURE; - } - - - // Vertex properties - typedef property vertex_p; - // adjacency_list-based type -#if 0 - typedef adjacency_list graph_t; -#else - typedef adjacency_list graph_t; -#endif - - // Construct an empty graph_small and prepare the dynamic_property_maps. - graph_t graph_small(0); - dynamic_properties dp_small; - - property_map::type name_small = - get(vertex_name, graph_small); - dp_small.property("node_id", name_small); - - // Read graph_small - bool status = read_graphviz(graph_small_file, graph_small, dp_small, "node_id"); - (void)status; - - // Construct an empty graph_large and prepare the dynamic_property_maps, - // following the read_graphviz example - graph_t graph_large(0); - dynamic_properties dp_large; - - property_map::type name_large = - get(vertex_name, graph_large); - dp_large.property("node_id", name_large); - - // Read graph_large - status = read_graphviz(graph_large_file, graph_large, dp_large, "node_id"); - - - // Create the call_back function - typedef property_map::type p_map_t; - print_callback callback(graph_small, graph_large, - name_small, name_large, true); - - // Compute the sub-graph isomorphism mappings -#if 1 - bool ret = vf2_sub_graph_iso(graph_small, graph_large, callback); - //bool ret = vf2_graph_iso(graph_small, graph_large, callback); -#else - typedef graph_traits::vertex_descriptor vertex_t; - typedef property_map::type index_map_t; - - index_map_t index_small = get(vertex_index, graph_small); - index_map_t index_large = get(vertex_index, graph_large); - - graph_traits::vertex_iterator vi, vi_end; - - vector vertex_order1; - for (tie(vi, vi_end) = vertices(graph_small); vi != vi_end; ++vi) - vertex_order1.push_back(*vi); - - bool ret = vf2_sub_graph_iso(graph_small, graph_large, callback, vertex_order1, - vertex_index1_map(index_small).vertex_index2_map(index_large)); - -#endif - (void)ret; - - return 0; -} diff --git a/example/vf2_sub_graph_iso_multi_example.cpp b/example/vf2_sub_graph_iso_multi_example.cpp index c552ae8ad..8654d4a34 100755 --- a/example/vf2_sub_graph_iso_multi_example.cpp +++ b/example/vf2_sub_graph_iso_multi_example.cpp @@ -6,60 +6,16 @@ // http://www.boost.org/LICENSE_1_0.txt) //======================================================================= -#include -#include -#include #include #include using namespace boost; - -template -struct my_print_callback { - - my_print_callback(const Graph1& graph1, const Graph2& graph2, - EdgeCompatibilityPredicate edge_comp, - VertexCompatibilityPredicate vertex_comp) - : graph1_(graph1), graph2_(graph2), edge_comp_(edge_comp), vertex_comp_(vertex_comp) {} - - template - bool operator()(CorrespondenceMap1To2 f, CorrespondenceMap2To1) const { - - std::cout << "Verify: " << std::boolalpha - << verify_vf2_sub_graph_iso(graph1_, graph2_, f, edge_comp_, vertex_comp_) - << std::endl; - - // Print sub graph isomorphism map - BGL_FORALL_VERTICES_T(v, graph1_, Graph1) - std::cout << '(' << v << ", " << get(f, v) << ") "; - - std::cout << std::endl; - - return true; - } - -private: - const Graph1& graph1_; - const Graph2& graph2_; - EdgeCompatibilityPredicate edge_comp_; - VertexCompatibilityPredicate vertex_comp_; -}; - - - - int main() { typedef property edge_property; - typedef property vertex_property; - - //typedef adjacency_list graph_type; - typedef adjacency_list graph_type; - //typedef adjacency_list graph_type; - //typedef adjacency_list graph_type; + typedef property > vertex_property; + + // Using a vecS graphs => the index maps are implicit. + typedef adjacency_list graph_type; // Build graph1 graph_type graph1; @@ -77,7 +33,6 @@ int main() { add_edge(2, 2, edge_property('l'), graph1); add_edge(2, 2, edge_property('l'), graph1); - // Build graph2 graph_type graph2; @@ -92,7 +47,6 @@ int main() { add_edge(0, 1, edge_property('a'), graph2); add_edge(0, 1, edge_property('b'), graph2); - add_edge(1, 2, edge_property('s'), graph2); add_edge(2, 3, edge_property('b'), graph2); @@ -112,34 +66,24 @@ int main() { // create predicates typedef property_map::type vertex_name_map_t; - - typedef property_map_compatible vertex_comp_t; + typedef property_map_equivalent vertex_comp_t; vertex_comp_t vertex_comp = - make_property_map_compatible(get(vertex_name, graph1), get(vertex_name, graph2)); + make_property_map_equivalent(get(vertex_name, graph1), get(vertex_name, graph2)); typedef property_map::type edge_name_map_t; - - typedef property_map_compatible edge_comp_t; + typedef property_map_equivalent edge_comp_t; edge_comp_t edge_comp = - make_property_map_compatible(get(edge_name, graph1), get(edge_name, graph2)); - - - graph_traits::vertex_iterator vi, vi_end; - - // define the order in whcih vertices of graph1 are examined - std::vector::vertex_descriptor> vertex_order1; - for (tie(vi, vi_end) = vertices(graph1); vi != vi_end; ++vi) - vertex_order1.push_back(*vi); - - // true instructs callback to verify a map using - // verify_vf2_sub_graph_iso - my_print_callback - callback(graph1, graph2, edge_comp, vertex_comp); - - bool ret = vf2_sub_graph_iso(graph1, graph2, callback, vertex_order1, - edges_equivalent(edge_comp).vertices_equivalent(vertex_comp)); - - (void)ret; + make_property_map_equivalent(get(edge_name, graph1), get(edge_name, graph2)); + + // Create callback + vf2_print_callback callback(graph1, graph2); + + // Print out all subgraph isomorphism mappings between graph1 and graph2. + // Function vertex_order_by_mult is used to compute the order of + // vertices of graph1. That's the order in which the vertices are examined + // during the matching process. + vf2_subgraph_iso(graph1, graph2, callback, vertex_order_by_mult(graph1), + edges_equivalent(edge_comp).vertices_equivalent(vertex_comp)); return 0; } diff --git a/example/vf2_sub_graph_iso_undir_example.cpp b/example/vf2_sub_graph_iso_undir_example.cpp deleted file mode 100755 index f3d6eae09..000000000 --- a/example/vf2_sub_graph_iso_undir_example.cpp +++ /dev/null @@ -1,73 +0,0 @@ -//======================================================================= -// Copyright (C) 2012 Flavio De Lorenzi (fdlorenzi@gmail.com) -// -// 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) -//======================================================================= - -#include -#include -#include -using namespace boost; - - -int main() { - typedef adjacency_list graph_bidir_t; - - // Build graph1 - int num_vertices1 = 8; graph_bidir_t graph1(num_vertices1); - add_edge(0, 6, graph1); add_edge(0, 7, graph1); - add_edge(1, 5, graph1); add_edge(1, 7, graph1); - add_edge(2, 4, graph1); add_edge(2, 5, graph1); add_edge(2, 6, graph1); - add_edge(3, 4, graph1); - // reversed edges - add_edge(6, 0, graph1); add_edge(7, 0, graph1); - add_edge(5, 1, graph1); add_edge(7, 1, graph1); - add_edge(4, 2, graph1); add_edge(5, 2, graph1); add_edge(6, 2, graph1); - add_edge(4, 3, graph1); - - add_edge(7, 7, graph1); - add_edge(7, 7, graph1); - - - // Build graph2 - int num_vertices2 = 9; graph_bidir_t graph2(num_vertices2); - add_edge(0, 6, graph2); add_edge(0, 8, graph2); - add_edge(1, 5, graph2); add_edge(1, 7, graph2); - add_edge(2, 4, graph2); add_edge(2, 7, graph2); add_edge(2, 8, graph2); - add_edge(3, 4, graph2); add_edge(3, 5, graph2); add_edge(3, 6, graph2); - // reversed edges - add_edge(6, 0, graph2); add_edge(8, 0, graph2); - add_edge(5, 1, graph2); add_edge(7, 1, graph2); - add_edge(4, 2, graph2); add_edge(7, 2, graph2); add_edge(8, 2, graph2); - add_edge(4, 3, graph2); add_edge(5, 3, graph2); add_edge(6, 3, graph2); - - add_edge(5, 5, graph2); - add_edge(5, 5, graph2); - - // Build graph3 - typedef adjacency_list graph_undir_t; - - int num_vertices3 = 9; graph_undir_t graph3(num_vertices3); - add_edge(0, 6, graph3); add_edge(0, 8, graph3); - add_edge(1, 5, graph3); add_edge(1, 7, graph3); - add_edge(2, 4, graph3); add_edge(2, 7, graph3); add_edge(2, 8, graph3); - add_edge(3, 4, graph3); add_edge(3, 5, graph3); add_edge(3, 6, graph3); - - add_edge(5, 5, graph3); - - // true instructs callback to verify a map using - // verify_vf2_sub_graph_iso - vf2_print_callback callback12(graph1, graph2, true); - - bool ret = vf2_sub_graph_iso(graph1, graph2, callback12); - std::cout << std::endl; - std::cout << std::endl; - - vf2_print_callback callback13(graph1, graph3, true); - ret = vf2_sub_graph_iso(graph1, graph3, callback13); - (void)ret; - - return 0; -} diff --git a/include/boost/graph/vf2_sub_graph_iso.hpp b/include/boost/graph/vf2_sub_graph_iso.hpp index 6e469c074..349be2b5c 100755 --- a/include/boost/graph/vf2_sub_graph_iso.hpp +++ b/include/boost/graph/vf2_sub_graph_iso.hpp @@ -24,7 +24,9 @@ #include #include #include +#include // for always_equivalent #include +#include #include #include #include @@ -36,73 +38,23 @@ #endif namespace boost { - - // Utility functions (analogue to mcgregor_common_subgraphs) - // Returns binary predicate function object that compares vertices or edges - // between graphs using property maps - template - struct property_map_compatible { - - property_map_compatible(const PropertyMap1 property_map1, - const PropertyMap2 property_map2) - : property_map1_(property_map1), property_map2_(property_map2) {} - - template - bool operator()(const Item1 item1, const Item2 item2) const { - return (get(property_map1_, item1) == get(property_map2_, item2)); - } - - private: - const PropertyMap1 property_map1_; - const PropertyMap2 property_map2_; - }; - - // Returns a property_map_compatible object that compares the values - // of property_map1 and property_map2. - template - property_map_compatible - make_property_map_compatible(const PropertyMap1 property_map1, - const PropertyMap2 property_map2) { - return property_map_compatible - (property_map1, property_map2); - } - - // Binary function object that always returns true. Used when - // vertices or edges are always compatible (i.e. have no labels). - struct always_compatible { - template - bool operator()(const Item1&, const Item2&) const { - return true; - } - }; - // Default print_callback template struct vf2_print_callback { - vf2_print_callback(const Graph1& graph1, const Graph2& graph2, - bool verify = false) - : graph1_(graph1), graph2_(graph2), verify_(verify) {} + vf2_print_callback(const Graph1& graph1, const Graph2& graph2) + : graph1_(graph1), graph2_(graph2) {} template bool operator()(CorrespondenceMap1To2 f, CorrespondenceMap2To1) const { - if (verify_) - std::cout << "Verify: " << std::boolalpha - << verify_vf2_sub_graph_iso(graph1_, graph2_, f) - << std::endl; - - // Print sub graph isomorphism map + // Print (sub)graph isomorphism map BGL_FORALL_VERTICES_T(v, graph1_, Graph1) - std::cout << '(' << get(vertex_index, graph1_, v) << ", " - << get(vertex_index, graph1_, get(f, v)) << ") "; + std::cout << '(' << get(vertex_index_t(), graph1_, v) << ", " + << get(vertex_index_t(), graph1_, get(f, v)) << ") "; std::cout << std::endl; @@ -112,8 +64,6 @@ namespace boost { private: const Graph1& graph1_; const Graph2& graph2_; - - const bool verify_; }; namespace detail { @@ -332,25 +282,44 @@ namespace boost { }; + // Used for bookkeeping of matched edges in equivalent_edge_exists + // (when dealing with multi-graphs) + template + struct memory { + void store(Item item) { items_.push_back(item); } + bool exists(Item item) const { + return (std::find(items_.begin(), items_.end(), item) != items_.end()); + } + + std::vector items_; + }; + + + template + struct memory >::type> { + void store(Item item) { items_.insert(item); } + bool exists(Item item) const { + return (items_.find(item) != items_.end()); + } + + std::set items_; + }; + + // Function object that checks whether a valid edge // exists. For multi-graphs matched edges are excluded template - struct compatible_edge_exists { - - compatible_edge_exists() {}; - - typedef typename boost::graph_traits::out_edge_iterator edge_iterator_type; + struct equivalent_edge_exists { + typedef typename boost::graph_traits::edge_descriptor edge_type; template bool operator()(typename graph_traits::vertex_descriptor s, typename graph_traits::vertex_descriptor t, EdgePredicate is_valid_edge, const Graph& g) { - edge_iterator_type ei, ei_end; - for (boost::tie(ei, ei_end) = out_edges(s, g); ei != ei_end; ++ei) { - if ((target(*ei, g) == t) && is_valid_edge(*ei) && - (matched_edges_.find(ei) == matched_edges_.end())) { - matched_edges_.insert(ei); + BGL_FORALL_OUTEDGES_T(s, e, g, Graph) { + if ((target(e, g) == t) && is_valid_edge(e) && !edge_memory_.exists(e)) { + edge_memory_.store(e); return true; } } @@ -360,14 +329,11 @@ namespace boost { private: - std::set matched_edges_; + memory edge_memory_; }; template - struct compatible_edge_exists >::type> { - - compatible_edge_exists() {}; - + struct equivalent_edge_exists >::type> { template bool operator()(typename graph_traits::vertex_descriptor s, typename graph_traits::vertex_descriptor t, @@ -391,18 +357,18 @@ namespace boost { // fixed edge e2 template + typename EdgeEquivalencePredicate> struct edge1_predicate { - edge1_predicate(EdgeCompatibilityPredicate edge_comp, + edge1_predicate(EdgeEquivalencePredicate edge_comp, typename graph_traits::edge_descriptor e2) : edge_comp_(edge_comp), e2_(e2) {} - bool operator()(typename graph_traits::edge_descriptor e1) const { + bool operator()(typename graph_traits::edge_descriptor e1) { return edge_comp_(e1, e2_); } - EdgeCompatibilityPredicate edge_comp_; + EdgeEquivalencePredicate edge_comp_; typename graph_traits::edge_descriptor e2_; }; @@ -411,32 +377,32 @@ namespace boost { // fixed edge e1 template + typename EdgeEquivalencePredicate> struct edge2_predicate { - edge2_predicate(EdgeCompatibilityPredicate edge_comp, + edge2_predicate(EdgeEquivalencePredicate edge_comp, typename graph_traits::edge_descriptor e1) : edge_comp_(edge_comp), e1_(e1) {} - bool operator()(typename graph_traits::edge_descriptor e2) const { + bool operator()(typename graph_traits::edge_descriptor e2) { return edge_comp_(e1_, e2); } - EdgeCompatibilityPredicate edge_comp_; + EdgeEquivalencePredicate edge_comp_; typename graph_traits::edge_descriptor e1_; }; - enum problem_selector { sub_graph_iso, isomorphism }; + enum problem_selector { subgraph_iso, isomorphism }; // The actual state associated with both graphs template class state { @@ -454,8 +420,8 @@ namespace boost { IndexMap1 index_map1_; - EdgeCompatibilityPredicate edge_comp_; - VertexCompatibilityPredicate vertex_comp_; + EdgeEquivalencePredicate edge_comp_; + VertexEquivalencePredicate vertex_comp_; base_state state1_; base_state state2_; @@ -465,7 +431,7 @@ namespace boost { // - graph sub-graph isomorphism, or inline bool comp_term_sets(graph1_size_type a, graph2_size_type b, - boost::mpl::int_) const { + boost::mpl::int_) const { return a <= b; } @@ -484,8 +450,8 @@ namespace boost { state(const Graph1& graph1, const Graph2& graph2, IndexMap1 index_map1, IndexMap2 index_map2, - EdgeCompatibilityPredicate edge_comp, - VertexCompatibilityPredicate vertex_comp) + EdgeEquivalencePredicate edge_comp, + VertexEquivalencePredicate vertex_comp) : graph1_(graph1), graph2_(graph2), index_map1_(index_map1), edge_comp_(edge_comp), vertex_comp_(vertex_comp), @@ -514,7 +480,7 @@ namespace boost { graph1_size_type term_in1_count = 0, term_out1_count = 0, rest1_count = 0; { - compatible_edge_exists edge2_exists; + equivalent_edge_exists edge2_exists; BGL_FORALL_INEDGES_T(v_new, e1, graph1_, Graph1) { vertex1_type v = source(e1, graph1_); @@ -524,7 +490,7 @@ namespace boost { if (v != v_new) w = state1_.core(v); if (!edge2_exists(w, w_new, - edge2_predicate(edge_comp_, e1), + edge2_predicate(edge_comp_, e1), graph2_)) return false; @@ -540,7 +506,7 @@ namespace boost { } { - compatible_edge_exists edge2_exists; + equivalent_edge_exists edge2_exists; BGL_FORALL_OUTEDGES_T(v_new, e1, graph1_, Graph1) { vertex1_type v = target(e1, graph1_); @@ -550,7 +516,7 @@ namespace boost { w = state1_.core(v); if (!edge2_exists(w_new, w, - edge2_predicate(edge_comp_, e1), + edge2_predicate(edge_comp_, e1), graph2_)) return false; @@ -569,7 +535,7 @@ namespace boost { graph2_size_type term_out2_count = 0, term_in2_count = 0, rest2_count = 0; { - compatible_edge_exists edge1_exists; + equivalent_edge_exists edge1_exists; BGL_FORALL_INEDGES_T(w_new, e2, graph2_, Graph2) { vertex2_type w = source(e2, graph2_); @@ -579,7 +545,7 @@ namespace boost { v = state2_.core(w); if (!edge1_exists(v, v_new, - edge1_predicate(edge_comp_, e2), + edge1_predicate(edge_comp_, e2), graph1_)) return false; @@ -595,7 +561,7 @@ namespace boost { } { - compatible_edge_exists edge1_exists; + equivalent_edge_exists edge1_exists; BGL_FORALL_OUTEDGES_T(w_new, e2, graph2_, Graph2) { vertex2_type w = target(e2, graph2_); @@ -605,7 +571,7 @@ namespace boost { v = state2_.core(w); if (!edge1_exists(v_new, v, - edge1_predicate(edge_comp_, e2), + edge1_predicate(edge_comp_, e2), graph1_)) return false; @@ -676,7 +642,7 @@ namespace boost { } // Calls the user_callback with a graph (sub)graph mapping - bool call_back(SubGraphIsoMapCallBack user_callback) const { + bool call_back(SubGraphIsoMapCallback user_callback) const { return user_callback(state1_.get_map(), state2_.get_map()); } @@ -705,15 +671,15 @@ namespace boost { typename IndexMap1, typename IndexMap2, typename VertexOrder1, - typename EdgeCompatibilityPredicate, - typename VertexCompatibilityPredicate, - typename SubGraphIsoMapCallBack, + typename EdgeEquivalencePredicate, + typename VertexEquivalencePredicate, + typename SubGraphIsoMapCallback, problem_selector problem_selection> bool match(const Graph1& graph1, const Graph2& graph2, - SubGraphIsoMapCallBack user_callback, const VertexOrder1& vertex_order1, + SubGraphIsoMapCallback user_callback, const VertexOrder1& vertex_order1, state& s) { + EdgeEquivalencePredicate, VertexEquivalencePredicate, + SubGraphIsoMapCallback, problem_selection>& s) { typename VertexOrder1::const_iterator graph1_verts_iter; @@ -783,20 +749,19 @@ namespace boost { // lexicographical comparison return std::make_pair(in_degree(v, graph_), out_degree(v, graph_)) < std::make_pair(in_degree(w, graph_), out_degree(w, graph_)); - } - const Graph graph_; + const Graph& graph_; }; - // Used to sort nodes by frequency/degrees + // Used to sort nodes by multiplicity of in/out degrees template struct vertex_frequency_degree_cmp { typedef typename graph_traits::vertex_descriptor vertex_type; - vertex_frequency_degree_cmp(const Graph& graph, const FrequencyMap& freq) + vertex_frequency_degree_cmp(const Graph& graph, FrequencyMap freq) : graph_(graph), freq_(freq) {} bool operator()(const vertex_type& v, const vertex_type& w) const { @@ -807,17 +772,17 @@ namespace boost { } const Graph& graph_; - const FrequencyMap& freq_; + FrequencyMap freq_; }; - // Sorts vertices of a graph by frequency/degree + // Sorts vertices of a graph by multiplicity of in/out degrees template void sort_vertices(const Graph& graph, const IndexMap index_map, VertexOrder& order) { typedef typename graph_traits::vertices_size_type size_type; - + boost::range::sort(order, vertex_in_out_degree_cmp(graph)); std::vector freq_vec(num_vertices(graph), 0); @@ -849,6 +814,19 @@ namespace boost { } // namespace detail + + // Returns vertex order (vertices sorted by multiplicity of in/out degrees) + template + std::vector::vertex_descriptor> + vertex_order_by_mult(const Graph& graph) { + + std::vector::vertex_descriptor> vertex_order; + std::copy(vertices(graph).first, vertices(graph).second, std::back_inserter(vertex_order)); + + detail::sort_vertices(graph, get(vertex_index, graph), vertex_order); + return vertex_order; + } + // Enumerates all graph sub-graph isomorphism mappings between graphs // graph_small and graph_large. Continues until user_callback returns true or the @@ -858,15 +836,15 @@ namespace boost { typename IndexMapSmall, typename IndexMapLarge, typename VertexOrderSmall, - typename EdgeCompatibilityPredicate, - typename VertexCompatibilityPredicate, - typename SubGraphIsoMapCallBack> - bool vf2_sub_graph_iso(const GraphSmall& graph_small, const GraphLarge& graph_large, - SubGraphIsoMapCallBack user_callback, - IndexMapSmall index_map_small, IndexMapLarge index_map_large, - const VertexOrderSmall& vertex_order_small, - EdgeCompatibilityPredicate edge_comp, - VertexCompatibilityPredicate vertex_comp) { + typename EdgeEquivalencePredicate, + typename VertexEquivalencePredicate, + typename SubGraphIsoMapCallback> + bool vf2_subgraph_iso(const GraphSmall& graph_small, const GraphLarge& graph_large, + SubGraphIsoMapCallback user_callback, + IndexMapSmall index_map_small, IndexMapLarge index_map_large, + const VertexOrderSmall& vertex_order_small, + EdgeEquivalencePredicate edge_comp, + VertexEquivalencePredicate vertex_comp) { // Graph requirements BOOST_CONCEPT_ASSERT(( BidirectionalGraphConcept )); @@ -894,14 +872,14 @@ namespace boost { typedef typename property_traits::value_type IndexMapLargeValue; BOOST_STATIC_ASSERT(( is_convertible::value )); - // Edge & vertex compatibility requirements + // Edge & vertex requirements typedef typename graph_traits::edge_descriptor edge_small_type; typedef typename graph_traits::edge_descriptor edge_large_type; - BOOST_CONCEPT_ASSERT(( BinaryPredicateConcept )); - BOOST_CONCEPT_ASSERT(( BinaryPredicateConcept )); // Vertex order requirements @@ -927,60 +905,54 @@ namespace boost { return true; detail::state + EdgeEquivalencePredicate, VertexEquivalencePredicate, + SubGraphIsoMapCallback, detail::subgraph_iso> s(graph_small, graph_large, index_map_small, index_map_large, edge_comp, vertex_comp); return detail::match(graph_small, graph_large, user_callback, vertex_order_small, s); } - // All default interface for vf2_sub_graph_iso + // All default interface for vf2_subgraph_iso template - bool vf2_sub_graph_iso(const GraphSmall& graph_small, const GraphLarge& graph_large, - SubGraphIsoMapCallBack user_callback) { + typename SubGraphIsoMapCallback> + bool vf2_subgraph_iso(const GraphSmall& graph_small, const GraphLarge& graph_large, + SubGraphIsoMapCallback user_callback) { typedef typename graph_traits::vertex_descriptor vertex_small_type; - std::vector vertex_order_small; - BGL_FORALL_VERTICES_T(v, graph_small, GraphSmall) - vertex_order_small.push_back(v); - - detail::sort_vertices(graph_small, get(vertex_index, graph_small), vertex_order_small); - - return vf2_sub_graph_iso(graph_small, graph_large, user_callback, - get(vertex_index, graph_small), get(vertex_index, graph_large), - vertex_order_small, - always_compatible(), always_compatible()); + return vf2_subgraph_iso(graph_small, graph_large, user_callback, + get(vertex_index, graph_small), get(vertex_index, graph_large), + vertex_order_by_mult(graph_small), + always_equivalent(), always_equivalent()); } - // Named parameter interface of vf2_sub_graph_iso + // Named parameter interface of vf2_subgraph_iso template - bool vf2_sub_graph_iso(const GraphSmall& graph_small, const GraphLarge& graph_large, - SubGraphIsoMapCallBack user_callback, - const VertexOrderSmall& vertex_order_small, - const bgl_named_params& params) { + bool vf2_subgraph_iso(const GraphSmall& graph_small, const GraphLarge& graph_large, + SubGraphIsoMapCallback user_callback, + const VertexOrderSmall& vertex_order_small, + const bgl_named_params& params) { - return vf2_sub_graph_iso(graph_small, graph_large, user_callback, - choose_const_pmap(get_param(params, vertex_index1), - graph_small, vertex_index), - choose_const_pmap(get_param(params, vertex_index2), - graph_large, vertex_index), - vertex_order_small, - choose_param(get_param(params, edges_equivalent_t()), - always_compatible()), - choose_param(get_param(params, vertices_equivalent_t()), - always_compatible()) - ); + return vf2_subgraph_iso(graph_small, graph_large, user_callback, + choose_const_pmap(get_param(params, vertex_index1), + graph_small, vertex_index), + choose_const_pmap(get_param(params, vertex_index2), + graph_large, vertex_index), + vertex_order_small, + choose_param(get_param(params, edges_equivalent_t()), + always_equivalent()), + choose_param(get_param(params, vertices_equivalent_t()), + always_equivalent()) + ); } @@ -993,15 +965,15 @@ namespace boost { typename IndexMap1, typename IndexMap2, typename VertexOrder1, - typename EdgeCompatibilityPredicate, - typename VertexCompatibilityPredicate, - typename GraphIsoMapCallBack> + typename EdgeEquivalencePredicate, + typename VertexEquivalencePredicate, + typename GraphIsoMapCallback> bool vf2_graph_iso(const Graph1& graph1, const Graph2& graph2, - GraphIsoMapCallBack user_callback, + GraphIsoMapCallback user_callback, IndexMap1 index_map1, IndexMap2 index_map2, const VertexOrder1& vertex_order1, - EdgeCompatibilityPredicate edge_comp, - VertexCompatibilityPredicate vertex_comp) { + EdgeEquivalencePredicate edge_comp, + VertexEquivalencePredicate vertex_comp) { // Graph requirements BOOST_CONCEPT_ASSERT(( BidirectionalGraphConcept )); @@ -1030,14 +1002,14 @@ namespace boost { typedef typename property_traits::value_type IndexMap2Value; BOOST_STATIC_ASSERT(( is_convertible::value )); - // Edge & vertex compatibility requirements + // Edge & vertex requirements typedef typename graph_traits::edge_descriptor edge1_type; typedef typename graph_traits::edge_descriptor edge2_type; - BOOST_CONCEPT_ASSERT(( BinaryPredicateConcept )); - BOOST_CONCEPT_ASSERT(( BinaryPredicateConcept )); // Vertex order requirements @@ -1046,7 +1018,6 @@ namespace boost { BOOST_STATIC_ASSERT(( is_same::value )); BOOST_ASSERT( num_vertices(graph1) == vertex_order1.size() ); - if (num_vertices(graph1) != num_vertices(graph2)) return false; @@ -1064,8 +1035,8 @@ namespace boost { return true; detail::state + EdgeEquivalencePredicate, VertexEquivalencePredicate, + GraphIsoMapCallback, detail::isomorphism> s(graph1, graph2, index_map1, index_map2, edge_comp, vertex_comp); return detail::match(graph1, graph2, user_callback, vertex_order1, s); @@ -1075,22 +1046,16 @@ namespace boost { // All default interface for vf2_graph_iso template + typename GraphIsoMapCallback> bool vf2_graph_iso(const Graph1& graph1, const Graph2& graph2, - GraphIsoMapCallBack user_callback) { + GraphIsoMapCallback user_callback) { typedef typename graph_traits::vertex_descriptor vertex1_type; - std::vector vertex_order1; - BGL_FORALL_VERTICES_T(v, graph1, Graph1) - vertex_order1.push_back(v); - - detail::sort_vertices(graph1, get(vertex_index, graph1), vertex_order1); - return vf2_graph_iso(graph1, graph2, user_callback, get(vertex_index, graph1), get(vertex_index, graph2), - vertex_order1, - always_compatible(), always_compatible()); + vertex_order_by_mult(graph1), + always_equivalent(), always_equivalent()); } @@ -1098,12 +1063,12 @@ namespace boost { template bool vf2_graph_iso(const Graph1& graph1, const Graph2& graph2, - GraphIsoMapCallBack user_callback, + GraphIsoMapCallback user_callback, const VertexOrder1& vertex_order1, const bgl_named_params& params) { @@ -1114,9 +1079,9 @@ namespace boost { graph2, vertex_index), vertex_order1, choose_param(get_param(params, edges_equivalent_t()), - always_compatible()), + always_equivalent()), choose_param(get_param(params, vertices_equivalent_t()), - always_compatible()) + always_equivalent()) ); } @@ -1126,17 +1091,17 @@ namespace boost { template - inline bool verify_vf2_sub_graph_iso(const Graph1& graph1, const Graph2& graph2, - const CorresponenceMap1To2 f, - EdgeCompatibilityPredicate edge_comp, - VertexCompatibilityPredicate vertex_comp) { + typename EdgeEquivalencePredicate, + typename VertexEquivalencePredicate> + inline bool verify_vf2_subgraph_iso(const Graph1& graph1, const Graph2& graph2, + const CorresponenceMap1To2 f, + EdgeEquivalencePredicate edge_comp, + VertexEquivalencePredicate vertex_comp) { BOOST_CONCEPT_ASSERT(( EdgeListGraphConcept )); BOOST_CONCEPT_ASSERT(( AdjacencyMatrixConcept )); - detail::compatible_edge_exists edge2_exists; + detail::equivalent_edge_exists edge2_exists; BGL_FORALL_EDGES_T(e1, graph1, Graph1) { typename graph_traits::vertex_descriptor s1, t1; @@ -1151,7 +1116,7 @@ namespace boost { typename graph_traits::edge_descriptor e2; if (!edge2_exists(s2, t2, - detail::edge2_predicate(edge_comp, e1), + detail::edge2_predicate(edge_comp, e1), graph2)) return false; @@ -1160,14 +1125,14 @@ namespace boost { return true; } - // Variant of verify_sub_graph_iso with all default parameters + // Variant of verify_subgraph_iso with all default parameters template - inline bool verify_vf2_sub_graph_iso(const Graph1& graph1, const Graph2& graph2, - const CorresponenceMap1To2 f) { - return verify_vf2_sub_graph_iso(graph1, graph2, f, - always_compatible(), always_compatible()); + inline bool verify_vf2_subgraph_iso(const Graph1& graph1, const Graph2& graph2, + const CorresponenceMap1To2 f) { + return verify_vf2_subgraph_iso(graph1, graph2, f, + always_equivalent(), always_equivalent()); } diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 32eec8fed..99eb25407 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -125,6 +125,7 @@ test-suite graph_test : [ run graphml_test.cpp ../build//boost_graph : : "graphml_test.xml" ] [ run stoer_wagner_test.cpp ../../test/build//boost_unit_test_framework/static : $(TEST_DIR) ] [ compile filtered_graph_properties_dijkstra.cpp ] + [ run vf2_sub_graph_iso_test.cpp ] ; # Run SDB tests only when -sSDB= is set. diff --git a/test/vf2_sub_graph_iso_test.cpp b/test/vf2_sub_graph_iso_test.cpp new file mode 100644 index 000000000..7ad653e83 --- /dev/null +++ b/test/vf2_sub_graph_iso_test.cpp @@ -0,0 +1,293 @@ +//======================================================================= +// Boost.Graph library vf2_sub_graph_iso test +// Adapted from isomorphism.cpp and mcgregor_subgraphs_test.cpp +// +// Copyright (C) 2012 Flavio De Lorenzi (fdlorenzi@gmail.com) +// +// 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) +//======================================================================= + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace boost; + + +template +struct random_functor { + random_functor(Generator& g) : g(g) { } + std::size_t operator()(std::size_t n) { + boost::uniform_int distrib(0, n-1); + boost::variate_generator > + x(g, distrib); + return x(); + } + Generator& g; +}; + + +template +void randomly_permute_graph(Graph1& g1, const Graph2& g2) { + BOOST_REQUIRE(num_vertices(g1) <= num_vertices(g2)); + BOOST_REQUIRE(num_edges(g1) == 0); + + typedef typename graph_traits::vertex_descriptor vertex1; + typedef typename graph_traits::vertex_descriptor vertex2; + typedef typename graph_traits::vertex_iterator vertex_iterator; + typedef typename graph_traits::edge_iterator edge_iterator; + + boost::mt19937 gen; + random_functor rand_fun(gen); + + // Decide new order + std::vector orig_vertices; + std::copy(vertices(g2).first, vertices(g2).second, std::back_inserter(orig_vertices)); + std::random_shuffle(orig_vertices.begin(), orig_vertices.end(), rand_fun); + std::map vertex_map; + + std::size_t i = 0; + for (vertex_iterator vi = vertices(g1).first; + vi != vertices(g1).second; ++i, ++vi) { + vertex_map[orig_vertices[i]] = *vi; + put(vertex_name_t(), g1, *vi, get(vertex_name_t(), g2, orig_vertices[i])); + } + + for (edge_iterator ei = edges(g2).first; ei != edges(g2).second; ++ei) { + typename std::map::iterator si = vertex_map.find(source(*ei, g2)), + ti = vertex_map.find(target(*ei, g2)); + if ((si != vertex_map.end()) && (ti != vertex_map.end())) + add_edge(si->second, ti->second, get(edge_name_t(), g2, *ei), g1); + } +} + + +template +void generate_random_digraph(Graph& g, double edge_probability, + int max_parallel_edges, double parallel_edge_probability, + int max_edge_name, int max_vertex_name) { + + BOOST_REQUIRE((0 <= edge_probability) && (edge_probability <= 1)); + BOOST_REQUIRE((0 <= parallel_edge_probability) && (parallel_edge_probability <= 1)); + BOOST_REQUIRE(0 <= max_parallel_edges); + BOOST_REQUIRE(0 <= max_edge_name); + BOOST_REQUIRE(0 <= max_vertex_name); + + typedef typename graph_traits::vertex_iterator vertex_iterator; + boost::mt19937 random_gen; + boost::uniform_real dist_real(0.0, 1.0); + boost::variate_generator > + random_real_dist(random_gen, dist_real); + + for (vertex_iterator u = vertices(g).first; u != vertices(g).second; ++u) { + for (vertex_iterator v = vertices(g).first; v != vertices(g).second; ++v) { + if (random_real_dist() <= edge_probability) { + add_edge(*u, *v, g); + for (int i = 0; i < max_parallel_edges; ++i) { + if (random_real_dist() <= parallel_edge_probability) + add_edge(*u, *v, g); + } + } + } + } + + { + boost::uniform_int dist_int(0, max_edge_name); + boost::variate_generator > + random_int_dist(random_gen, dist_int); + randomize_property(g, random_int_dist); + } + + { + boost::uniform_int dist_int(0, max_vertex_name); + boost::variate_generator > + random_int_dist(random_gen, dist_int); + + randomize_property(g, random_int_dist); + } + +} + + +template +struct test_callback { + + test_callback(const Graph1& graph1, const Graph2& graph2, + EdgeEquivalencePredicate edge_comp, + VertexEquivalencePredicate vertex_comp, bool output) + : graph1_(graph1), graph2_(graph2), edge_comp_(edge_comp), vertex_comp_(vertex_comp), + output_(output) {} + + template + bool operator()(CorrespondenceMap1To2 f, CorrespondenceMap2To1) { + + bool verified; + BOOST_CHECK(verified = verify_vf2_subgraph_iso(graph1_, graph2_, f, edge_comp_, vertex_comp_)); + + // Output (sub)graph isomorphism map + if (!verified || output_) { + std::cout << "Verfied: " << std::boolalpha << verified << std::endl; + std::cout << "Num vertices: " << num_vertices(graph1_) << ' ' << num_vertices(graph2_) << std::endl; + BGL_FORALL_VERTICES_T(v, graph1_, Graph1) + std::cout << '(' << get(vertex_index_t(), graph1_, v) << ", " + << get(vertex_index_t(), graph2_, get(f, v)) << ") "; + + std::cout << std::endl; + } + + return true; + } + +private: + const Graph1& graph1_; + const Graph2& graph2_; + EdgeEquivalencePredicate edge_comp_; + VertexEquivalencePredicate vertex_comp_; + bool output_; +}; + + +void test_vf2_sub_graph_iso(int n1, int n2, double edge_probability, + int max_parallel_edges, double parallel_edge_probability, + int max_edge_name, int max_vertex_name, bool output) { + + typedef property edge_property; + typedef property > vertex_property; + + typedef adjacency_list graph1; + typedef adjacency_list graph2; + + graph1 g1(n1); + graph2 g2(n2); + generate_random_digraph(g2, edge_probability, max_parallel_edges, parallel_edge_probability, + max_edge_name, max_vertex_name); + randomly_permute_graph(g1, g2); + + int v_idx = 0; + for (graph_traits::vertex_iterator vi = vertices(g1).first; + vi != vertices(g1).second; ++vi) { + put(vertex_index_t(), g1, *vi, v_idx++); + } + + + // Create vertex and edge predicates + typedef property_map::type vertex_name_map1; + typedef property_map::type vertex_name_map2; + + typedef property_map_equivalent vertex_predicate; + vertex_predicate vertex_comp = + make_property_map_equivalent(get(vertex_name, g1), get(vertex_name, g2)); + + typedef property_map::type edge_name_map1; + typedef property_map::type edge_name_map2; + + typedef property_map_equivalent edge_predicate; + edge_predicate edge_comp = + make_property_map_equivalent(get(edge_name, g1), get(edge_name, g2)); + + + std::clock_t start = std::clock(); + + // Create callback + test_callback + callback(g1, g2, edge_comp, vertex_comp, output); + + std::cout << std::endl; + BOOST_CHECK(vf2_subgraph_iso(g1, g2, callback, vertex_order_by_mult(g1), + edges_equivalent(edge_comp).vertices_equivalent(vertex_comp))); + + std::clock_t end1 = std::clock(); + std::cout << "vf2_subgraph_iso: elapsed time (clock cycles): " << (end1 - start) << std::endl; + + if (num_vertices(g1) == num_vertices(g2)) { + std::cout << std::endl; + BOOST_CHECK(vf2_graph_iso(g1, g2, callback, vertex_order_by_mult(g1), + edges_equivalent(edge_comp).vertices_equivalent(vertex_comp))); + + std::clock_t end2 = std::clock(); + std::cout << "vf2_graph_iso: elapsed time (clock cycles): " << (end2 - end1) << std::endl; + } + + if (output) { + std::fstream file_graph1("graph1.dot", std::fstream::out); + write_graphviz(file_graph1, g1, + make_label_writer(get(boost::vertex_name, g1)), + make_label_writer(get(boost::edge_name, g1))); + + std::fstream file_graph2("graph2.dot", std::fstream::out); + write_graphviz(file_graph2, g2, + make_label_writer(get(boost::vertex_name, g2)), + make_label_writer(get(boost::edge_name, g2))); + } +} + +int test_main(int argc, char* argv[]) { + + int num_vertices_g1 = 10; + int num_vertices_g2 = 20; + double edge_probability = 0.4; + int max_parallel_edges = 2; + double parallel_edge_probability = 0.4; + int max_edge_name = 5; + int max_vertex_name = 5; + bool output = false; + + if (argc > 1) { + num_vertices_g1 = boost::lexical_cast(argv[1]); + } + + if (argc > 2) { + num_vertices_g2 = boost::lexical_cast(argv[2]); + } + + if (argc > 3) { + edge_probability = boost::lexical_cast(argv[3]); + } + + if (argc > 4) { + max_parallel_edges = boost::lexical_cast(argv[4]); + } + + if (argc > 5) { + parallel_edge_probability = boost::lexical_cast(argv[5]); + } + + if (argc > 6) { + max_edge_name = boost::lexical_cast(argv[6]); + } + + if (argc > 7) { + max_vertex_name = boost::lexical_cast(argv[7]); + } + + if (argc > 8) { + output = boost::lexical_cast(argv[8]); + } + + test_vf2_sub_graph_iso(num_vertices_g1, num_vertices_g2, edge_probability, + max_parallel_edges, parallel_edge_probability, + max_edge_name, max_vertex_name, output); + + return 0; +} From 8a1913f804b1ec966e3055273a9f2e91fcba8498 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Sun, 16 Dec 2012 05:16:47 +0000 Subject: [PATCH 252/333] Trying to fix property map ambiguities with distributed graphs on Intel compiler [SVN r82010] --- include/boost/graph/adjacency_list.hpp | 1 + .../graph/compressed_sparse_row_graph.hpp | 15 ++++++----- .../graph/detail/is_distributed_selector.hpp | 26 +++++++++++++++++++ include/boost/graph/properties.hpp | 2 +- 4 files changed, 37 insertions(+), 7 deletions(-) create mode 100644 include/boost/graph/detail/is_distributed_selector.hpp diff --git a/include/boost/graph/adjacency_list.hpp b/include/boost/graph/adjacency_list.hpp index 21b7500d2..6738fa22c 100644 --- a/include/boost/graph/adjacency_list.hpp +++ b/include/boost/graph/adjacency_list.hpp @@ -188,6 +188,7 @@ namespace boost { } // namespace detail + template struct is_distributed_selector: mpl::false_ {}; //=========================================================================== diff --git a/include/boost/graph/compressed_sparse_row_graph.hpp b/include/boost/graph/compressed_sparse_row_graph.hpp index 42e2419aa..33c267254 100644 --- a/include/boost/graph/compressed_sparse_row_graph.hpp +++ b/include/boost/graph/compressed_sparse_row_graph.hpp @@ -37,7 +37,9 @@ #include #include #include +#include #include +#include #include #include #include @@ -1322,8 +1324,9 @@ struct csr_property_map_helper { typedef transform_value_property_map, all_const_type> const_type; }; +// disable_if isn't truly necessary but required to avoid ambiguity with specializations below template -struct property_map: +struct property_map >::type>: csr_property_map_helper< BOOST_CSR_GRAPH_TYPE, Tag, @@ -1370,35 +1373,35 @@ put(Tag tag, } template -struct property_map +struct property_map >::type> { typedef typed_identity_property_map type; typedef type const_type; }; template -struct property_map +struct property_map >::type> { typedef detail::csr_edge_index_map type; typedef type const_type; }; template -struct property_map +struct property_map >::type> { typedef typename BOOST_CSR_GRAPH_TYPE::inherited_vertex_properties::vertex_map_type type; typedef typename BOOST_CSR_GRAPH_TYPE::inherited_vertex_properties::const_vertex_map_type const_type; }; template -struct property_map +struct property_map >::type> { typedef typename BOOST_CSR_GRAPH_TYPE::forward_type::inherited_edge_properties::edge_map_type type; typedef typename BOOST_CSR_GRAPH_TYPE::forward_type::inherited_edge_properties::const_edge_map_type const_type; }; template -struct property_map +struct property_map >::type> { typedef boost::ref_property_map type; typedef boost::ref_property_map const_type; diff --git a/include/boost/graph/detail/is_distributed_selector.hpp b/include/boost/graph/detail/is_distributed_selector.hpp new file mode 100644 index 000000000..4319d9d89 --- /dev/null +++ b/include/boost/graph/detail/is_distributed_selector.hpp @@ -0,0 +1,26 @@ +// Copyright 2012 The 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) + +// Authors: Jeremiah Willcock +// Andrew Lumsdaine + +// Selector to determine whether a selector is distributedS (can only be true +// if has been included) so that we can +// disable various sequential-graph-only traits specializations for distributed +// graphs. + +#ifndef BOOST_GRAPH_DETAIL_IS_DISTRIBUTED_SELECTOR_HPP +#define BOOST_GRAPH_DETAIL_IS_DISTRIBUTED_SELECTOR_HPP + +#include + +namespace boost { + namespace detail { + template struct is_distributed_selector: boost::mpl::false_ {}; + } +} + +#endif // BOOST_GRAPH_DETAIL_IS_DISTRIBUTED_SELECTOR_HPP diff --git a/include/boost/graph/properties.hpp b/include/boost/graph/properties.hpp index 31257ca2f..d540439ef 100644 --- a/include/boost/graph/properties.hpp +++ b/include/boost/graph/properties.hpp @@ -224,7 +224,7 @@ namespace boost { {}; } // namespace detail - template + template struct property_map: mpl::if_< is_same::type, edge_property_tag>, From ebd636bfc093cfe4b76d1ccc99bef7ba7db7bae1 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Mon, 17 Dec 2012 17:11:02 +0000 Subject: [PATCH 253/333] Added VF2 updates from Flavio De Lorenzi [SVN r82050] --- doc/vf2_sub_graph_iso.html | 375 +++++++++++--------- example/vf2_sub_graph_iso_multi_example.cpp | 2 +- include/boost/graph/vf2_sub_graph_iso.hpp | 38 +- 3 files changed, 226 insertions(+), 189 deletions(-) diff --git a/doc/vf2_sub_graph_iso.html b/doc/vf2_sub_graph_iso.html index a1667ffea..ae24e908c 100755 --- a/doc/vf2_sub_graph_iso.html +++ b/doc/vf2_sub_graph_iso.html @@ -1,21 +1,23 @@ - + + --> - Boost Graph Library: VF2 (Sub)Graph Isomorphism + + Boost Graph Library: VF2 (Sub)Graph Isomorphism - C++ Boost -
      +

      C++ Boost

      vf2_subgraph_iso

      -// all defaults interface
      +// All defaults interface
       template <typename GraphSmall,
                 typename GraphLarge,
                 typename SubGraphIsoMapCallback>
      @@ -46,7 +47,7 @@ 

      SubGraphIsoMapCallback user_callback) -// named parameter version +// Named parameter version template <typename GraphSmall, typename GraphLarge, typename VertexOrderSmall, @@ -61,7 +62,7 @@

      const bgl_named_params<Param, Tag, Rest>& params) -// non-named parameter version +// Non-named parameter version template <typename GraphSmall, typename GraphLarge, typename IndexMapSmall, @@ -84,7 +85,7 @@

      and G2=(V2, E2) is a bijective mapping M of the vertices of one graph to vertices of the other graph that preserves the edge structure of the graphs. M is said to be a - graph-subgraph isomorphism iff M is an isomorphism between + graph-subgraph isomorphism if and only if M is an isomorphism between G1 and a subgraph of G2.

      @@ -96,158 +97,188 @@

      returns true if a graph-subgraph isomorphism exists and false otherwise. EdgeEquivalencePredicate and VertexEquivalencePredicate predicates are used to test whether - edges and vertices are equivalent. To use property maps for equivalence, - look at the + edges and vertices are equivalent. To use property maps for equivalence, + see - make_property_map_equivalent + make_property_map_equivalent function. By default - always_equivalent is used, which returns + always_equivalent is used, which returns true for any pair of vertices or edges.

      The current implementation is based on the VF2 algorithm, introduced by Cordella et al. An in-depth description of the algorithm is - given in [1] and [2] - and references therein. In brief, the process of finding a mapping between - the two graphs G1 and G2 determines - the isomorphism mapping M, which associates vertices - G1 with vertices of G2 and vice - versa. It can be described by means of a state space representation, which - is explored by the algorithm according to a depth-first strategy. Each - state s of the matching process can be associated with a partial - mapping M(s). At each level, the algorithm computes the set of - the vertex pairs that are candidates to be added to the current state - s. If a pair of vertices (v, w) is feasible, the mapping - is extended and the associated successor state s' is computed. + given in [1] and [2] + and references therein. The original code by P. Foggia and collaborators can + be found at [3]. In brief, the process of + finding a mapping between the two graphs G1 and + G2 determines the isomorphism mapping M, + which associates vertices G1 with vertices of + G2 and vice versa. It can be described by means of a + state space representation which is created by the algorithm + while exploring the search graph in depth-first fashion. + Each state s of the matching process + can be associated with a partial mapping M(s). At each level, + the algorithm computes the set of the vertex pairs that are candidates to + be added to the current state s. If a pair of vertices + (v, w) is feasible, the mapping is extended and the associated + successor state s' is computed. The whole procedure is then repeated for state s'.

      Where Defined

      - boost/graph/vf2_sub_graph_iso.hpp

      + + boost/graph/vf2_sub_graph_iso.hpp
      All functions are defined in the boost namespace.

      Parameters

      - - IN: const GraphSmall& graph_small + +

      IN: const GraphSmall& graph_small

      - The (first) smaller graph (fewer vertices) of the pair to be tested for - isomorphism. The type GraphSmall must be a - model of - Vertex List Graph, - Edge List Graph, - Bidirectional Graph and - Adjacency Matrix. +

      + The (first) smaller graph (fewer vertices) of the pair to be tested for + isomorphism. The type GraphSmall must be a + model of + Vertex List Graph, + Edge List Graph, + Bidirectional Graph and + Adjacency Matrix. + The edge descriptors graph_traits<GraphSmall>::edge_descriptor + must be + LessThan Comparable, cf. also the remark below. +

      - IN: const GraphLarge& graph_large +

      IN: const GraphLarge& graph_large

      - The (second) larger graph to be tested. - Type GraphLarge must be a model of - Vertex List Graph, - Edge List Graph, - Bidirectional Graph and - Adjacency Matrix. +

      + The (second) larger graph to be tested. + Type GraphLarge must be a model of + Vertex List Graph, + Edge List Graph, + Bidirectional Graph and + Adjacency Matrix. + The edge descriptors graph_traits<GraphLarge>::edge_descriptor + must be + LessThan Comparable, cf. also the remark below. +

      - OUT: SubGraphIsoMapCallback user_callback +

      OUT: SubGraphIsoMapCallback user_callback

      - A function object to be called when a graph-subgraph isomorphism has been discovered. The - operator() must have following form: +

      + A function object to be called when a graph-subgraph isomorphism has been discovered. The + operator() must have following form: +

       template <typename CorrespondenceMap1To2,
                 typename CorrespondenceMap2To1>
       bool operator()(CorrespondenceMap1To2 f, CorrespondenceMap2To1 g) const
             
      - Both the CorrespondenceMap1To2 - and CorresondenceMap2To1 types are models - of Readable - Property Map and map equivalent vertices across the two - graphs given to vf2_subgraph_iso (or vf2_graph_iso. For - instance, if v is - from graph_small, w is from graph_large, - and the vertices can be considered equivalent, - then get(f, v) will be w and get(g, w) - will be v. If any vertex, say v in graph_small, - does not match a vertex in graph_large , - then get(f, v) will be graph_traits<GraphLarge>::null_vertex(). - Likewise for any un-matched vertices from graph_large, - get(g, w) will be graph_traits<GraphSmall>::null_vertex(). - - Returning false from the callback will abort the search immediately. Otherwise, - the entire search space will be explored. A "default" print callback - is provided as a utility function. +

      + Both the CorrespondenceMap1To2 + and CorresondenceMap2To1 types are models + of Readable + Property Map and map equivalent vertices across the two + graphs given to vf2_subgraph_iso (or vf2_graph_iso). For + instance, if v is + from graph_small, w is from graph_large, + and the vertices can be considered equivalent, + then get(f, v) will be w and get(g, w) + will be v. If any vertex, say v in graph_small, + does not match a vertex in graph_large , + then get(f, v) will be graph_traits<GraphLarge>::null_vertex(). + Likewise for any unmatched vertices from graph_large, + get(g, w) will be graph_traits<GraphSmall>::null_vertex(). + + Returning false from the callback will abort the search immediately. Otherwise, + the entire search space will be explored. A "default" print callback + is provided as a utility function. +

      - IN: const VertexOrderSmall& vertex_order_small +

      IN: const VertexOrderSmall& vertex_order_small

      - The ordered vertices of the smaller (first) graph graph_small. - During the matching process the vertices are examined in the order given by - vertex_order_small. Type VertexOrderSmall must be a model - of ContainerConcept - with value type - graph_traits<GraphSmall>::vertex_descriptor. -
      - Default The vertices are ordered by multiplicity of in/out degrees. +

      + The ordered vertices of the smaller (first) graph graph_small. + During the matching process the vertices are examined in the order given by + vertex_order_small. Type VertexOrderSmall must be a model + of ContainerConcept + with value type + graph_traits<GraphSmall>::vertex_descriptor. +
      + Default The vertices are ordered by multiplicity of + in/out degrees. +

      Named Parameters

      - IN: vertex_index1(IndexMapSmall index_map_small) +

      IN: vertex_index1(IndexMapSmall index_map_small)

      - This maps each vertex to an integer in the range [0, num_vertices(graph_small)). - Type IndexMapSmall must be a model of - Readable Property Map. -
      - Default: get(vertex_index, graph_small) +

      + This maps each vertex to an integer in the range [0, num_vertices(graph_small)). + Type IndexMapSmall must be a model of + Readable Property Map. +
      + Default: get(vertex_index, graph_small) +

      - IN: vertex_index2(IndexMapLarge index_map_large) +

      IN: vertex_index2(IndexMapLarge index_map_large)

      - This maps each vertex to an integer in the range [0, num_vertices(graph_large)). - Type IndexMapLarge must be a model of - Readable Property Map. -
      - Default: get(vertex_index, graph_large) +

      + This maps each vertex to an integer in the range [0, num_vertices(graph_large)). + Type IndexMapLarge must be a model of + Readable Property Map. +
      + Default: get(vertex_index, graph_large) +

      - IN: edges_equivalent(EdgeEquivalencePredicate edge_comp) +

      IN: edges_equivalent(EdgeEquivalencePredicate edge_comp)

      - This function object is used to determine if edges between the two graphs - graph_small and graph_large are equivalent. - Type EdgeEquivalencePredicate must be a model of - Binary - Predicate and have argument types of - graph_traits<GraphSmall>::edge_descriptor and - graph_traits<GraphLarge>::edge_descriptor. A return value of true - indicates that the edges are equivalent. -
      - Default: always_equivalent +

      + This function object is used to determine if edges between the two graphs + graph_small and graph_large are equivalent. + Type EdgeEquivalencePredicate must be a model of + Binary + Predicate and have argument types of + graph_traits<GraphSmall>::edge_descriptor and + graph_traits<GraphLarge>::edge_descriptor. + The edge descriptors must be + LessThan Comparable. A return value of true indicates that the edges are equivalent. +
      + Default: + always_equivalent +

      - IN: vertices_equivalent(VertexEquivalencePredicate vertex_comp) +

      IN: vertices_equivalent(VertexEquivalencePredicate vertex_comp)

      - This function object is used to determine if vertices between the two graphs - graph_small and graph_large are equivalent. - Type VertexEquivalencePredicate must be a model of - Binary Predicate - and have argument types of - graph_traits<GraphSmall>::vertex_descriptor and - graph_traits<GraphLarge>::vertex_descriptor. A return value of true - indicates that the vertices are equivalent. -
      - Default: always_equivalent +

      + This function object is used to determine if vertices between the two graphs + graph_small and graph_large are equivalent. + Type VertexEquivalencePredicate must be a model of + Binary Predicate + and have argument types of + graph_traits<GraphSmall>::vertex_descriptor and + graph_traits<GraphLarge>::vertex_descriptor. A return value of true + indicates that the vertices are equivalent. +
      + Default: + always_equivalent +

      - +

      Related Functions

      Non-named parameter, named-parameter and all default parameter versions of function

      - -vf2_graph_iso(...) - +

      vf2_graph_iso(...)

      for isomorphism testing take the same parameters as the corresponding functions vf2_subgraph_iso for subgraph isomorphism testing. @@ -258,19 +289,23 @@

      Related Functions

      EdgeEquivalencePredicate and VertexEquivalencePredicate predicates are used to test whether edges and vertices are equivalent. By default - always_equivalent as used. + always_equivalent is used.

      - +

      Utility Functions and Structs

      +

      template<typename Graph1, typename Graph2> struct vf2_print_callback +

      - Callback function object that prints out the correspondences between vertices - of Graph1 and Graph2. The constructor takes the two graphs G1 - and G2. +

      + Callback function object that prints out the correspondences between vertices + of Graph1 and Graph2. The constructor takes + the two graphs G1 and G2. +

      @@ -279,7 +314,10 @@ 

      Utility Functions and Structs

      vertex_order_by_mult(const Graph& graph)
      - Returns a vector containing the vertices of a graph, sorted by multiplicity of in/out degrees. +

      + Returns a vector containing the vertices of a graph, sorted + by multiplicity of in/out degrees. +

      @@ -303,8 +341,11 @@ 

      Utility Functions and Structs

      VertexEquivalencePredicate vertex_comp)
      -This function can be used to verify a (sub)graph isomorphism mapping f. The parameters are -analogous to function vf2_subgraph_iso (vf2_graph_iso). +

      + This function can be used to verify a (sub)graph isomorphism + mapping f. The parameters are analogous to + function vf2_subgraph_iso (vf2_graph_iso). +

      @@ -351,17 +392,16 @@

      Example 1

      // Vertices and edges are assumed to be always equivalent. vf2_subgraph_iso(graph1, graph2, callback);
      -

      -The complete example can be found under -examples/vf2_sub_graph_iso_example.cpp. -
      -

      - +

      + The complete example can be found under + examples/vf2_sub_graph_iso_example.cpp. +
      +

      Example 2

      - In this example, the subgraph isomorphism mappings between multi-graphs are computed. The vertices - and edges of the multi-graphs are differentiated using property maps. + In this example, the subgraph isomorphism mappings between multi-graphs are computed. The vertices + and edges of the multi-graphs are distinguished using property maps.

       // Define edge and vertex properties
      @@ -387,12 +427,12 @@ 

      Example 2

      ... add_edge(0, 1, edge_property('a'), graph2); ... -
      +

      - To differentiate vertices and edges with property maps, binary predicates are created using the - - make_property_map_equivalent function: + To distinguish vertices and edges with property maps, binary predicates are created using the + + make_property_map_equivalent function:

      @@ -410,8 +450,8 @@ 

      Example 2

      - Finally, a callback function object is created and the subgraph isomorphism mappings are - computed: + Finally, a callback function object is created and the subgraph isomorphism mappings are + computed:

       // Create callback
      @@ -420,39 +460,58 @@ 

      Example 2

      // Print out all subgraph isomorphism mappings between graph1 and graph2. // Function vertex_order_by_mult is used to compute the order of -// vertices of graph1. That's the order in which the vertices are examined +// vertices of graph1. This is the order in which the vertices are examined // during the matching process. vf2_subgraph_iso(graph1, graph2, callback, vertex_order_by_mult(graph1), edges_equivalent(edge_comp).vertices_equivalent(vertex_comp));
      -

      -For the complete example, see -examples/vf2_sub_graph_iso_multi_example.cpp. -
      -

      +

      + For the complete example, see + + examples/vf2_sub_graph_iso_multi_example.cpp. +
      +

      +

      Notes

      +

      + If the EdgeList allows for parallel edges, e.g. vecS, the + algorithm does some bookkeeping of already identified edges. Matched edges + are temporarily stored using std::set as container, requiring that + edge_descriptor are + LessThan Comparable. In contrast, if instead you enforce the absence of + parallel edges, e.g. by using setS, the lookup function falls back + to edge() without performing any bookkeeping. +

      Bibliography

      -

      1 -
      - L. P. Cordella, P. Foggia, C. Sansone, and M. Vento. -
      An improved algorithm for matching large graphs. -
      In: 3rd IAPR-TC15 Workshop on Graph-based Representations in Pattern Recognition, pp. 149-159, Cuen, 2001. -
      -

      2 -
      - L. P. Cordella, P. Foggia, C. Sansone, and M. Vento. -
      A (Sub)Graph Isomorphism Algorithm for Matching Large Graphs. -
      IEEE Trans. Pattern Anal. Mach. Intell., vol. 26, no. 10, pp. 1367-1372, 2004. -
      +
      1
      +
      + L. P. Cordella, P. Foggia, C. Sansone, and M. Vento. +
      An improved algorithm for matching large graphs. +
      In: 3rd IAPR-TC15 Workshop on Graph-based Representations in Pattern Recognition, pp. 149-159, Cuen, 2001. +

      +
      +
      2
      +
      + L. P. Cordella, P. Foggia, C. Sansone, and M. Vento. +
      A (Sub)Graph Isomorphism Algorithm for Matching Large Graphs. +
      IEEE Trans. Pattern Anal. Mach. Intell., vol. 26, no. 10, pp. 1367-1372, 2004. +

      +
      +
      3
      +
      + + http://www.cs.sunysb.edu/~algorith/implement/vflib/implement.shtml +

      +
      - -
      - Copyright © 2012, Flavio De Lorenzi - (fdlorenzi@gmail.com) - +
      +

      + Copyright © 2012, Flavio De Lorenzi + (fdlorenzi@gmail.com) +

      diff --git a/example/vf2_sub_graph_iso_multi_example.cpp b/example/vf2_sub_graph_iso_multi_example.cpp index 8654d4a34..6f9e34a2a 100755 --- a/example/vf2_sub_graph_iso_multi_example.cpp +++ b/example/vf2_sub_graph_iso_multi_example.cpp @@ -80,7 +80,7 @@ int main() { // Print out all subgraph isomorphism mappings between graph1 and graph2. // Function vertex_order_by_mult is used to compute the order of - // vertices of graph1. That's the order in which the vertices are examined + // vertices of graph1. This is the order in which the vertices are examined // during the matching process. vf2_subgraph_iso(graph1, graph2, callback, vertex_order_by_mult(graph1), edges_equivalent(edge_comp).vertices_equivalent(vertex_comp)); diff --git a/include/boost/graph/vf2_sub_graph_iso.hpp b/include/boost/graph/vf2_sub_graph_iso.hpp index 349be2b5c..89784dfe4 100755 --- a/include/boost/graph/vf2_sub_graph_iso.hpp +++ b/include/boost/graph/vf2_sub_graph_iso.hpp @@ -282,44 +282,23 @@ namespace boost { }; - // Used for bookkeeping of matched edges in equivalent_edge_exists - // (when dealing with multi-graphs) - template - struct memory { - void store(Item item) { items_.push_back(item); } - bool exists(Item item) const { - return (std::find(items_.begin(), items_.end(), item) != items_.end()); - } - - std::vector items_; - }; - - - template - struct memory >::type> { - void store(Item item) { items_.insert(item); } - bool exists(Item item) const { - return (items_.find(item) != items_.end()); - } - - std::set items_; - }; - - // Function object that checks whether a valid edge // exists. For multi-graphs matched edges are excluded template struct equivalent_edge_exists { typedef typename boost::graph_traits::edge_descriptor edge_type; - + + BOOST_CONCEPT_ASSERT(( LessThanComparable )); + template bool operator()(typename graph_traits::vertex_descriptor s, typename graph_traits::vertex_descriptor t, EdgePredicate is_valid_edge, const Graph& g) { BGL_FORALL_OUTEDGES_T(s, e, g, Graph) { - if ((target(e, g) == t) && is_valid_edge(e) && !edge_memory_.exists(e)) { - edge_memory_.store(e); + if ((target(e, g) == t) && is_valid_edge(e) && + (matched_edges_.find(e) == matched_edges_.end())) { + matched_edges_.insert(e); return true; } } @@ -329,7 +308,7 @@ namespace boost { private: - memory edge_memory_; + std::set matched_edges_; }; template @@ -768,7 +747,6 @@ namespace boost { // lexicographical comparison return std::make_pair(freq_[v], in_degree(v, graph_)+out_degree(v, graph_)) < std::make_pair(freq_[w], in_degree(w, graph_)+out_degree(w, graph_)); - } const Graph& graph_; @@ -780,7 +758,7 @@ namespace boost { template - void sort_vertices(const Graph& graph, const IndexMap index_map, VertexOrder& order) { + void sort_vertices(const Graph& graph, IndexMap index_map, VertexOrder& order) { typedef typename graph_traits::vertices_size_type size_type; boost::range::sort(order, vertex_in_out_degree_cmp(graph)); From 31cf899da97afeb88d51772100619260b924dfa1 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Mon, 17 Dec 2012 17:37:39 +0000 Subject: [PATCH 254/333] Trying to fix defaults for StoredEdge; refs #7801 [SVN r82052] --- include/boost/graph/detail/adjacency_list.hpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/include/boost/graph/detail/adjacency_list.hpp b/include/boost/graph/detail/adjacency_list.hpp index fa3989890..619593675 100644 --- a/include/boost/graph/detail/adjacency_list.hpp +++ b/include/boost/graph/detail/adjacency_list.hpp @@ -309,14 +309,16 @@ namespace boost { public: typedef Property property_type; inline stored_ra_edge_iter() { } - inline stored_ra_edge_iter(Vertex v, Iter i = Iter(), - EdgeVec* edge_vec = 0) + inline explicit stored_ra_edge_iter(Vertex v) // Only used for comparisons + : stored_edge(v), m_i(0), m_vec(0){ } + inline stored_ra_edge_iter(Vertex v, Iter i, EdgeVec* edge_vec) : stored_edge(v), m_i(i - edge_vec->begin()), m_vec(edge_vec){ } - inline Property& get_property() { return (*m_vec)[m_i].get_property(); } + inline Property& get_property() { BOOST_ASSERT ((m_vec != 0)); return (*m_vec)[m_i].get_property(); } inline const Property& get_property() const { + BOOST_ASSERT ((m_vec != 0)); return (*m_vec)[m_i].get_property(); } - inline Iter get_iter() const { return m_vec->begin() + m_i; } + inline Iter get_iter() const { BOOST_ASSERT ((m_vec != 0)); return m_vec->begin() + m_i; } protected: std::size_t m_i; EdgeVec* m_vec; From 086cd12a7ec2113d694b9252a14f4fd56d290973 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Fri, 4 Jan 2013 19:29:27 +0000 Subject: [PATCH 255/333] Applied variant of patch from #7845; fixes #7845 [SVN r82358] --- include/boost/graph/isomorphism.hpp | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/include/boost/graph/isomorphism.hpp b/include/boost/graph/isomorphism.hpp index 99055f35c..225cd2051 100644 --- a/include/boost/graph/isomorphism.hpp +++ b/include/boost/graph/isomorphism.hpp @@ -222,7 +222,7 @@ namespace boost { recur: if (iter != ordered_edges.end()) { i = source(*iter, G1); - j = target(*iter, G2); + j = target(*iter, G1); if (dfs_num[i] > dfs_num_k) { G2_verts = vertices(G2); while (G2_verts.first != G2_verts.second) { @@ -310,8 +310,8 @@ fi_adj_loop_k:++fi_adj.first; if (k.empty()) return false; const match_continuation& this_k = k.back(); switch (this_k.position) { - case match_continuation::pos_G2_vertex_loop: {G2_verts = this_k.G2_verts; iter = this_k.iter; dfs_num_k = this_k.dfs_num_k; k.pop_back(); in_S[*G2_verts.first] = false; i = source(*iter, G1); j = target(*iter, G2); goto G2_loop_k;} - case match_continuation::pos_fi_adj_loop: {fi_adj = this_k.fi_adj; iter = this_k.iter; dfs_num_k = this_k.dfs_num_k; k.pop_back(); in_S[*fi_adj.first] = false; i = source(*iter, G1); j = target(*iter, G2); goto fi_adj_loop_k;} + case match_continuation::pos_G2_vertex_loop: {G2_verts = this_k.G2_verts; iter = this_k.iter; dfs_num_k = this_k.dfs_num_k; k.pop_back(); in_S[*G2_verts.first] = false; i = source(*iter, G1); j = target(*iter, G1); goto G2_loop_k;} + case match_continuation::pos_fi_adj_loop: {fi_adj = this_k.fi_adj; iter = this_k.iter; dfs_num_k = this_k.dfs_num_k; k.pop_back(); in_S[*fi_adj.first] = false; i = source(*iter, G1); j = target(*iter, G1); goto fi_adj_loop_k;} case match_continuation::pos_dfs_num: {k.pop_back(); goto return_point_false;} default: { BOOST_ASSERT(!"Bad position"); @@ -378,6 +378,14 @@ fi_adj_loop_k:++fi_adj.first; const Graph& m_g; }; + // Count actual number of vertices, even in filtered graphs. + template + size_t count_vertices(const Graph& g) + { + size_t n = 0; + BGL_FORALL_VERTICES_T(v, g, Graph) {(void)v; ++n;} + return n; + } template )); BOOST_CONCEPT_ASSERT(( EdgeListGraphConcept )); BOOST_CONCEPT_ASSERT(( VertexListGraphConcept )); - BOOST_CONCEPT_ASSERT(( BidirectionalGraphConcept )); + //BOOST_CONCEPT_ASSERT(( BidirectionalGraphConcept )); typedef typename graph_traits::vertex_descriptor vertex1_t; typedef typename graph_traits::vertex_descriptor vertex2_t; @@ -407,7 +415,7 @@ fi_adj_loop_k:++fi_adj.first; // Property map requirements BOOST_CONCEPT_ASSERT(( ReadWritePropertyMapConcept )); typedef typename property_traits::value_type IsoMappingValue; - BOOST_STATIC_ASSERT((is_same::value)); + BOOST_STATIC_ASSERT((is_convertible::value)); BOOST_CONCEPT_ASSERT(( ReadablePropertyMapConcept )); typedef typename property_traits::value_type IndexMap1Value; @@ -417,9 +425,9 @@ fi_adj_loop_k:++fi_adj.first; typedef typename property_traits::value_type IndexMap2Value; BOOST_STATIC_ASSERT((is_convertible::value)); - if (num_vertices(G1) != num_vertices(G2)) + if (count_vertices(G1) != count_vertices(G2)) return false; - if (num_vertices(G1) == 0 && num_vertices(G2) == 0) + if (count_vertices(G1) == 0 && count_vertices(G2) == 0) return true; detail::isomorphism_algo Date: Thu, 10 Jan 2013 22:14:46 +0000 Subject: [PATCH 256/333] Added more examples to Jamfile [SVN r82438] --- example/Jamfile.v2 | 3 +++ 1 file changed, 3 insertions(+) diff --git a/example/Jamfile.v2 b/example/Jamfile.v2 index 6d7d62f6a..1785b8778 100644 --- a/example/Jamfile.v2 +++ b/example/Jamfile.v2 @@ -35,6 +35,9 @@ exe stoer_wagner : stoer_wagner.cpp ; exe bfs-example : bfs-example.cpp ; exe bfs-example2 : bfs-example2.cpp ; exe dfs-example : dfs-example.cpp ; +exe dijkstra-example : dijkstra-example.cpp ; +exe dijkstra-example-listS : dijkstra-example-listS.cpp ; +exe dijkstra-no-color-map-example : dijkstra-no-color-map-example.cpp ; exe adjacency_list_io : adjacency_list_io.cpp ; exe undirected_adjacency_list : undirected_adjacency_list.cpp ; exe directed_graph : directed_graph.cpp ; From f10ad0650ad947e3e8db7b56201a3c4cc662a0fa Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Thu, 10 Jan 2013 22:49:10 +0000 Subject: [PATCH 257/333] Changed to iterator_property_map; fixes #7877 [SVN r82439] --- example/dijkstra-example.cpp | 24 ++++-------------------- 1 file changed, 4 insertions(+), 20 deletions(-) diff --git a/example/dijkstra-example.cpp b/example/dijkstra-example.cpp index 6a77ddedb..5f1ef4bd1 100644 --- a/example/dijkstra-example.cpp +++ b/example/dijkstra-example.cpp @@ -12,6 +12,7 @@ #include #include #include +#include using namespace boost; @@ -32,32 +33,15 @@ main(int, char *[]) }; int weights[] = { 1, 2, 1, 2, 7, 3, 1, 1, 1 }; int num_arcs = sizeof(edge_array) / sizeof(Edge); -#if defined(BOOST_MSVC) && BOOST_MSVC <= 1300 - graph_t g(num_nodes); - property_map::type weightmap = get(edge_weight, g); - for (std::size_t j = 0; j < num_arcs; ++j) { - edge_descriptor e; bool inserted; - boost::tie(e, inserted) = add_edge(edge_array[j].first, edge_array[j].second, g); - weightmap[e] = weights[j]; - } -#else graph_t g(edge_array, edge_array + num_arcs, weights, num_nodes); property_map::type weightmap = get(edge_weight, g); -#endif std::vector p(num_vertices(g)); std::vector d(num_vertices(g)); vertex_descriptor s = vertex(A, g); -#if defined(BOOST_MSVC) && BOOST_MSVC <= 1300 - // VC++ has trouble with the named parameters mechanism - property_map::type indexmap = get(vertex_index, g); - dijkstra_shortest_paths(g, s, &p[0], &d[0], weightmap, indexmap, - std::less(), closed_plus(), - (std::numeric_limits::max)(), 0, - default_dijkstra_visitor()); -#else - dijkstra_shortest_paths(g, s, predecessor_map(&p[0]).distance_map(&d[0])); -#endif + dijkstra_shortest_paths(g, s, + predecessor_map(boost::make_iterator_property_map(p.begin(), get(boost::vertex_index, g))). + distance_map(boost::make_iterator_property_map(d.begin(), get(boost::vertex_index, g)))); std::cout << "distances and parents:" << std::endl; graph_traits < graph_t >::vertex_iterator vi, vend; From 8caf6fc368ed4174d8889e97f535e3cc398b7e81 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Thu, 10 Jan 2013 22:50:14 +0000 Subject: [PATCH 258/333] Removed obsolete workaround [SVN r82440] --- example/dijkstra-example-listS.cpp | 26 -------------------------- 1 file changed, 26 deletions(-) diff --git a/example/dijkstra-example-listS.cpp b/example/dijkstra-example-listS.cpp index 1c9342072..d02e93478 100644 --- a/example/dijkstra-example-listS.cpp +++ b/example/dijkstra-example-listS.cpp @@ -38,25 +38,8 @@ main(int, char *[]) int num_arcs = sizeof(edge_array) / sizeof(Edge); graph_traits::vertex_iterator i, iend; -#if defined(BOOST_MSVC) && BOOST_MSVC <= 1300 - graph_t g(num_nodes); - property_map::type weightmap = get(edge_weight, g); - - std::vector msvc_vertices; - for (boost::tie(i, iend) = vertices(g); i != iend; ++i) - msvc_vertices.push_back(*i); - - for (std::size_t j = 0; j < num_arcs; ++j) { - edge_descriptor e; bool inserted; - boost::tie(e, inserted) = add_edge(msvc_vertices[edge_array[j].first], - msvc_vertices[edge_array[j].second], g); - weightmap[e] = weights[j]; - } - -#else graph_t g(edge_array, edge_array + num_arcs, weights, num_nodes); property_map::type weightmap = get(edge_weight, g); -#endif // Manually intialize the vertex index and name maps property_map::type indexmap = get(vertex_index, g); @@ -73,16 +56,7 @@ main(int, char *[]) d = get(vertex_distance, g); property_map::type p = get(vertex_predecessor, g); -#if defined(BOOST_MSVC) && BOOST_MSVC <= 1300 - // VC++ has trouble with the named parameters mechanism - property_map::type indexmap = get(vertex_index, g); - dijkstra_shortest_paths(g, s, p, d, weightmap, indexmap, - std::less(), closed_plus(), - (std::numeric_limits::max)(), 0, - default_dijkstra_visitor()); -#else dijkstra_shortest_paths(g, s, predecessor_map(p).distance_map(d)); -#endif std::cout << "distances and parents:" << std::endl; graph_traits < graph_t >::vertex_iterator vi, vend; From 7ea637336902961931969c160e36e21f642cf1aa Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Thu, 10 Jan 2013 22:51:53 +0000 Subject: [PATCH 259/333] Removed obsolete workarounds and changed to iterator_property_map; refs #7877 [SVN r82441] --- example/dijkstra-no-color-map-example.cpp | 25 ++++------------------- 1 file changed, 4 insertions(+), 21 deletions(-) diff --git a/example/dijkstra-no-color-map-example.cpp b/example/dijkstra-no-color-map-example.cpp index cc89ab4fd..9a1a1c3ee 100644 --- a/example/dijkstra-no-color-map-example.cpp +++ b/example/dijkstra-no-color-map-example.cpp @@ -16,6 +16,7 @@ #include #include #include +#include using namespace boost; @@ -36,33 +37,15 @@ main(int, char *[]) }; int weights[] = { 1, 2, 1, 2, 7, 3, 1, 1, 1 }; int num_arcs = sizeof(edge_array) / sizeof(Edge); -#if defined(BOOST_MSVC) && BOOST_MSVC <= 1300 - graph_t g(num_nodes); - property_map::type weightmap = get(edge_weight, g); - for (std::size_t j = 0; j < num_arcs; ++j) { - edge_descriptor e; bool inserted; - boost::tie(e, inserted) = add_edge(edge_array[j].first, edge_array[j].second, g); - weightmap[e] = weights[j]; - } -#else graph_t g(edge_array, edge_array + num_arcs, weights, num_nodes); property_map::type weightmap = get(edge_weight, g); -#endif std::vector p(num_vertices(g)); std::vector d(num_vertices(g)); vertex_descriptor s = vertex(A, g); -#if defined(BOOST_MSVC) && BOOST_MSVC <= 1300 - // VC++ has trouble with the named parameters mechanism - property_map::type indexmap = get(vertex_index, g); - dijkstra_shortest_paths_no_color_map(g, s, &p[0], &d[0], weightmap, - indexmap, std::less(), - closed_plus(), - (std::numeric_limits::max)(), 0, - default_dijkstra_visitor()); -#else - dijkstra_shortest_paths_no_color_map(g, s, predecessor_map(&p[0]).distance_map(&d[0])); -#endif + dijkstra_shortest_paths_no_color_map(g, s, + predecessor_map(boost::make_iterator_property_map(p.begin(), get(boost::vertex_index, g))). + distance_map(boost::make_iterator_property_map(d.begin(), get(boost::vertex_index, g)))); std::cout << "distances and parents:" << std::endl; graph_traits < graph_t >::vertex_iterator vi, vend; From 1c54f431cae95819851c900be128e5884be16325 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Fri, 11 Jan 2013 03:05:08 +0000 Subject: [PATCH 260/333] Changed loop header to avoid GCC warning from -Wunsafe-loop-optimizations [SVN r82445] --- include/boost/graph/detail/histogram_sort.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/boost/graph/detail/histogram_sort.hpp b/include/boost/graph/detail/histogram_sort.hpp index ca6266a52..54d4449e1 100644 --- a/include/boost/graph/detail/histogram_sort.hpp +++ b/include/boost/graph/detail/histogram_sort.hpp @@ -69,7 +69,7 @@ count_starts // m_rowstart EdgeIndex start_of_this_row = 0; starts[0] = start_of_this_row; - for (vertices_size_type i = 1; i <= numkeys; ++i) { + for (vertices_size_type i = 1; i < numkeys + 1; ++i) { start_of_this_row += starts[i]; starts[i] = start_of_this_row; } From e41d96177f1896aa356b74ac7d4967007c0c424e Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Mon, 14 Jan 2013 21:03:48 +0000 Subject: [PATCH 261/333] Added check to prevent use of remove_vertex on named adjacency list graphs with vecS vertex container (since it does not work and could not be made to work efficiently); refs #7863 [SVN r82498] --- include/boost/graph/detail/adjacency_list.hpp | 5 +++-- include/boost/graph/named_graph.hpp | 16 ++++++++++++---- 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/include/boost/graph/detail/adjacency_list.hpp b/include/boost/graph/detail/adjacency_list.hpp index 619593675..f6d794817 100644 --- a/include/boost/graph/detail/adjacency_list.hpp +++ b/include/boost/graph/detail/adjacency_list.hpp @@ -17,6 +17,7 @@ #include #include #include +#include #include #include #include @@ -1903,7 +1904,7 @@ namespace boost { { typedef typename Config::stored_vertex stored_vertex; Derived& g = static_cast(g_); - g.removing_vertex(u); + g.removing_vertex(u, boost::graph_detail::iterator_stability(g_.m_vertices)); stored_vertex* su = (stored_vertex*)u; g.m_vertices.erase(su->m_position); delete su; @@ -2203,7 +2204,7 @@ namespace boost { { typedef typename Config::directed_category Cat; Graph& g = static_cast(g_); - g.removing_vertex(v); + g.removing_vertex(v, boost::graph_detail::iterator_stability(g_.m_vertices)); detail::remove_vertex_dispatch(g, v, Cat()); } // O(1) diff --git a/include/boost/graph/named_graph.hpp b/include/boost/graph/named_graph.hpp index 4c687a086..d82807f32 100644 --- a/include/boost/graph/named_graph.hpp +++ b/include/boost/graph/named_graph.hpp @@ -11,6 +11,7 @@ #define BOOST_GRAPH_NAMED_GRAPH_HPP #include +#include #include #include #include @@ -19,9 +20,11 @@ #include #include #include // for boost::lookup_one_property +#include #include #include // for boost::make_tuple #include +#include #include #include #include @@ -253,7 +256,8 @@ class named_graph /// Notify the named_graph that we are removing the given /// vertex. The name of the vertex will be removed from the mapping. - void removing_vertex(Vertex vertex); + template + void removing_vertex(Vertex vertex, VertexIterStability); /// Notify the named_graph that we are clearing the graph. /// This will clear out all of the name->vertex mappings @@ -308,8 +312,10 @@ inline void BGL_NAMED_GRAPH::added_vertex(Vertex vertex) } template -inline void BGL_NAMED_GRAPH::removing_vertex(Vertex vertex) +template +inline void BGL_NAMED_GRAPH::removing_vertex(Vertex vertex, VertexIterStability) { + BOOST_STATIC_ASSERT_MSG ((boost::is_base_of::value), "Named graphs cannot use vecS as vertex container and remove vertices; the lack of vertex descriptor stability (which iterator stability is a proxy for) means that the name -> vertex mapping would need to be completely rebuilt after each deletion. See https://svn.boost.org/trac/boost/ticket/7863 for more information and a test case."); typedef typename BGL_NAMED_GRAPH::vertex_name_type vertex_name_type; const vertex_name_type& vertex_name = extract_name(derived()[vertex]); named_vertices.erase(vertex_name); @@ -486,7 +492,8 @@ struct maybe_named_graph /// Notify the named_graph that we are removing the given /// vertex. This is a no-op. - void removing_vertex(Vertex) { } + template + void removing_vertex(Vertex, VertexIterStability) { } /// Notify the named_graph that we are clearing the graph. This is a /// no-op. @@ -517,7 +524,8 @@ struct maybe_named_graph /// Notify the named_graph that we are removing the given /// vertex. This is a no-op. - void removing_vertex(Vertex) { } + template + void removing_vertex(Vertex, VertexIterStability) { } /// Notify the named_graph that we are clearing the graph. This is a /// no-op. From afd2ee41bd98116b8c9ffab3aa0089f30b99ff51 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Thu, 7 Feb 2013 21:13:56 +0000 Subject: [PATCH 262/333] Removed uses of check_is_close which seems to be broken now [SVN r82779] --- include/boost/graph/rmat_graph_generator.hpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/include/boost/graph/rmat_graph_generator.hpp b/include/boost/graph/rmat_graph_generator.hpp index 8a7726514..15f7c25e8 100644 --- a/include/boost/graph/rmat_graph_generator.hpp +++ b/include/boost/graph/rmat_graph_generator.hpp @@ -22,7 +22,7 @@ #include #include #include -#include +// #include using boost::shared_ptr; using boost::uniform_01; @@ -156,7 +156,7 @@ namespace boost { { this->gen.reset(new uniform_01(gen)); - BOOST_ASSERT(boost::test_tools::check_is_close(a + b + c + d, 1., 1.e-5)); + // BOOST_ASSERT(boost::test_tools::check_is_close(a + b + c + d, 1., 1.e-5)); if (permute_vertices) generate_permutation_vector(gen, vertexPermutation, n); @@ -266,7 +266,7 @@ namespace boost { values(sort_pair()), done(false) { - BOOST_ASSERT(boost::test_tools::check_is_close(a + b + c + d, 1., 1.e-5)); + // BOOST_ASSERT(boost::test_tools::check_is_close(a + b + c + d, 1., 1.e-5)); this->gen.reset(new uniform_01(gen)); @@ -367,7 +367,7 @@ namespace boost { : gen(), done(false) { - BOOST_ASSERT(boost::test_tools::check_is_close(a + b + c + d, 1., 1.e-5)); + // BOOST_ASSERT(boost::test_tools::check_is_close(a + b + c + d, 1., 1.e-5)); this->gen.reset(new uniform_01(gen)); @@ -480,7 +480,7 @@ namespace boost { values(sort_pair()), done(false) { - BOOST_ASSERT(boost::test_tools::check_is_close(a + b + c + d, 1., 1.e-5)); + // BOOST_ASSERT(boost::test_tools::check_is_close(a + b + c + d, 1., 1.e-5)); this->gen.reset(new uniform_01(gen)); From e8eba95d4a0224248582aadfc7dbffe3cde57033 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Thu, 21 Feb 2013 19:51:54 +0000 Subject: [PATCH 263/333] Fixed typo in tag [SVN r83067] --- doc/r_c_shortest_paths.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/r_c_shortest_paths.html b/doc/r_c_shortest_paths.html index f33f8acc7..069d4c714 100755 --- a/doc/r_c_shortest_paths.html +++ b/doc/r_c_shortest_paths.html @@ -466,7 +466,7 @@

      Parameters

      IN: Label_Allocator la
      -An object of type Label_Allocator specifying a strategy for the memory management of the labels. It must offer the same interface as std::allocator. There is a default type default_r_c_shortest_paths_allocator for this parameter using the STL standard allocator. If the third or the fourth overload of the function is used, an object of this type is used as Label_Allocator parameter. If the first or the second overload is used, one must specify both a Label_Allocator and a Visitor parameter. If one wants to develop a user-defined type only for Visitor, one can use default_r_c_shortest_paths_allocator as Label_Allocator parameter. If one wants to use a specialized allocator, one can specify an arbitrary type as template parameter for the value type to the allocator; it is rebound to the correct type. +An object of type Label_Allocator specifying a strategy for the memory management of the labels. It must offer the same interface as std::allocator<r_c_shortest_paths_label<Graph, Resource_Container> >. There is a default type default_r_c_shortest_paths_allocator for this parameter using the STL standard allocator. If the third or the fourth overload of the function is used, an object of this type is used as Label_Allocator parameter. If the first or the second overload is used, one must specify both a Label_Allocator and a Visitor parameter. If one wants to develop a user-defined type only for Visitor, one can use default_r_c_shortest_paths_allocator as Label_Allocator parameter. If one wants to use a specialized allocator, one can specify an arbitrary type as template parameter for the value type to the allocator; it is rebound to the correct type.
      IN: Visitor vis
      From 51a28ac04bce1c7f7f586c35c5e51e9254f39f30 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Wed, 27 Feb 2013 22:04:17 +0000 Subject: [PATCH 264/333] Fixed handling of const graphs and property maps; fixes #8192 [SVN r83191] --- include/boost/graph/reverse_graph.hpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/include/boost/graph/reverse_graph.hpp b/include/boost/graph/reverse_graph.hpp index 7985e97f0..e9027e3cf 100644 --- a/include/boost/graph/reverse_graph.hpp +++ b/include/boost/graph/reverse_graph.hpp @@ -109,6 +109,8 @@ class reverse_graph { // Constructor reverse_graph(GraphRef g) : m_g(g) {} + // Conversion from reverse_graph on non-const reference to one on const reference + reverse_graph(const reverse_graph& o): m_g(o.m_g) {} // Graph requirements typedef typename Traits::vertex_descriptor vertex_descriptor; @@ -364,7 +366,12 @@ namespace detail { template struct property_map, Property> { typedef boost::is_same::type, edge_property_tag> is_edge_prop; - typedef typename property_map::type orig_type; + typedef boost::is_const::type> is_ref_const; + typedef typename boost::mpl::if_< + is_ref_const, + typename property_map::const_type, + typename property_map::type>::type + orig_type; typedef typename property_map::const_type orig_const_type; typedef typename boost::mpl::if_, orig_type>::type type; typedef typename boost::mpl::if_, orig_const_type>::type const_type; From 057a718a39e26ae901c744c9290721820276a172 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Fri, 1 Mar 2013 18:17:34 +0000 Subject: [PATCH 265/333] Added new versions of VF2 from Jakob Lykke Andersen; fixes #8166; some test cases for the new functionality would be appreciated as a separate patch. [SVN r83233] --- doc/vf2_sub_graph_iso.html | 36 ++- include/boost/graph/vf2_sub_graph_iso.hpp | 293 +++++++++++++++------- 2 files changed, 228 insertions(+), 101 deletions(-) diff --git a/doc/vf2_sub_graph_iso.html b/doc/vf2_sub_graph_iso.html index ae24e908c..69e0086bf 100755 --- a/doc/vf2_sub_graph_iso.html +++ b/doc/vf2_sub_graph_iso.html @@ -87,13 +87,16 @@

      graph that preserves the edge structure of the graphs. M is said to be a graph-subgraph isomorphism if and only if M is an isomorphism between G1 and a subgraph of G2. + An induced subgraph of a graph G = (V, E) is a normal subgraph + G' = (V', E') with the extra condition that all edges of G + which have both endpoints in V' are in E'.

      - This function finds all graph-subgraph isomorphism mappings between + This function finds all induced subgraph isomorphisms between graphs graph_small and graph_large and outputs them to user_callback. It continues until user_callback - returns true or the search space has been fully explored. vf2_subgraph_iso + returns false or the search space has been fully explored. vf2_subgraph_iso returns true if a graph-subgraph isomorphism exists and false otherwise. EdgeEquivalencePredicate and VertexEquivalencePredicate predicates are used to test whether @@ -182,8 +185,8 @@

      Parameters

      and CorresondenceMap2To1 types are models of Readable Property Map and map equivalent vertices across the two - graphs given to vf2_subgraph_iso (or vf2_graph_iso). For - instance, if v is + graphs given to vf2_subgraph_iso (or vf2_graph_iso or + vf2_subgraph_mono). For instance, if v is from graph_small, w is from graph_large, and the vertices can be considered equivalent, then get(f, v) will be w and get(g, w) @@ -279,13 +282,22 @@

      Related Functions

      function

      vf2_graph_iso(...)

      +

      vf2_subgraph_mono(...)

      - for isomorphism testing take the same parameters as the corresponding - functions vf2_subgraph_iso for subgraph isomorphism testing. - The algorithm finds all isomorphism mappings between graphs - graph1 and graph2 and outputs them to - user_callback. It continues until user_callback - returns true or the search space has been fully explored. As before, + for isomorphism and (not necessarily induced) subgraph isomorphism testing, + taking the same parameters as the corresponding functions vf2_subgraph_iso + for induced subgraph isomorphism testing. + For vf2_graph_iso the algorithm finds all isomorphism mappings between + graphs graph1 and graph2 and outputs them to + user_callback. + For vf2_graph_mono the algorithm finds all mappings of graph_small + to subgraphs of graph_large. + Note that, as opposed to vf2_subgraph_iso, + these subgraphs need not to be induced subgraphs. +

      +

      + Both algorithms continues until user_callback + returns false or the search space has been fully explored. As before, EdgeEquivalencePredicate and VertexEquivalencePredicate predicates are used to test whether edges and vertices are equivalent. By default @@ -511,7 +523,9 @@

      Bibliography


      Copyright © 2012, Flavio De Lorenzi - (fdlorenzi@gmail.com) + (fdlorenzi@gmail.com)
      + Copyright © 2013, Jakob Lykke Andersen, University of Southern Denmark + (jlandersen@imada.sdu.dk)

      diff --git a/include/boost/graph/vf2_sub_graph_iso.hpp b/include/boost/graph/vf2_sub_graph_iso.hpp index 89784dfe4..fe3b43730 100755 --- a/include/boost/graph/vf2_sub_graph_iso.hpp +++ b/include/boost/graph/vf2_sub_graph_iso.hpp @@ -1,5 +1,6 @@ //======================================================================= // Copyright (C) 2012 Flavio De Lorenzi (fdlorenzi@gmail.com) +// Copyright (C) 2013 Jakob Lykke Andersen, University of Southern Denmark (jlandersen@imada.sdu.dk) // // The algorithm implemented here is derived from original ideas by // Pasquale Foggia and colaborators. For further information see @@ -372,7 +373,7 @@ namespace boost { }; - enum problem_selector { subgraph_iso, isomorphism }; + enum problem_selector {subgraph_mono, subgraph_iso, isomorphism }; // The actual state associated with both graphs template state1_; base_state state2_; - // Two helper functions used in Feasibility and Valid functions to test + // Three helper functions used in Feasibility and Valid functions to test // terminal set counts when testing for: + // - graph sub-graph monomorphism, or + inline bool comp_term_sets(graph1_size_type a, + graph2_size_type b, + boost::mpl::int_) const { + return a <= b; + } + // - graph sub-graph isomorphism, or inline bool comp_term_sets(graph1_size_type a, graph2_size_type b, @@ -519,15 +527,16 @@ namespace boost { BGL_FORALL_INEDGES_T(w_new, e2, graph2_, Graph2) { vertex2_type w = source(e2, graph2_); if (state2_.in_core(w) || (w == w_new)) { - vertex1_type v = v_new; - if (w != w_new) - v = state2_.core(w); - - if (!edge1_exists(v, v_new, - edge1_predicate(edge_comp_, e2), - graph1_)) - return false; + if (problem_selection != subgraph_mono) { + vertex1_type v = v_new; + if (w != w_new) + v = state2_.core(w); + if (!edge1_exists(v, v_new, + edge1_predicate(edge_comp_, e2), + graph1_)) + return false; + } } else { if (0 < state2_.in_depth(w)) ++term_in2_count; @@ -545,15 +554,16 @@ namespace boost { BGL_FORALL_OUTEDGES_T(w_new, e2, graph2_, Graph2) { vertex2_type w = target(e2, graph2_); if (state2_.in_core(w) || (w == w_new)) { - vertex1_type v = v_new; - if (w != w_new) - v = state2_.core(w); - - if (!edge1_exists(v_new, v, - edge1_predicate(edge_comp_, e2), - graph1_)) - return false; + if (problem_selection != subgraph_mono) { + vertex1_type v = v_new; + if (w != w_new) + v = state2_.core(w); + if (!edge1_exists(v_new, v, + edge1_predicate(edge_comp_, e2), + graph1_)) + return false; + } } else { if (0 < state2_.in_depth(w)) ++term_in2_count; @@ -564,13 +574,23 @@ namespace boost { } } } - - return comp_term_sets(term_in1_count, term_in2_count, - boost::mpl::int_()) && - comp_term_sets(term_out1_count, term_out2_count, - boost::mpl::int_()) && - comp_term_sets(rest1_count, rest2_count, - boost::mpl::int_()); + + if (problem_selection != subgraph_mono) { // subgraph_iso and isomorphism + return comp_term_sets(term_in1_count, term_in2_count, + boost::mpl::int_()) && + comp_term_sets(term_out1_count, term_out2_count, + boost::mpl::int_()) && + comp_term_sets(rest1_count, rest2_count, + boost::mpl::int_()); + } else { // subgraph_mono + return comp_term_sets(term_in1_count, term_in2_count, + boost::mpl::int_()) && + comp_term_sets(term_out1_count, term_out2_count, + boost::mpl::int_()) && + comp_term_sets(term_in1_count + term_out1_count + rest1_count, + term_in2_count + term_out2_count + rest2_count, + boost::mpl::int_()); + } } // Returns true if vertex v in graph1 is a possible candidate to @@ -790,6 +810,91 @@ namespace boost { } + // Enumerates all graph sub-graph mono-/iso-morphism mappings between graphs + // graph_small and graph_large. Continues until user_callback returns true or the + // search space has been fully explored. + template + bool vf2_subgraph_morphism(const GraphSmall& graph_small, const GraphLarge& graph_large, + SubGraphIsoMapCallback user_callback, + IndexMapSmall index_map_small, IndexMapLarge index_map_large, + const VertexOrderSmall& vertex_order_small, + EdgeEquivalencePredicate edge_comp, + VertexEquivalencePredicate vertex_comp) { + + // Graph requirements + BOOST_CONCEPT_ASSERT(( BidirectionalGraphConcept )); + BOOST_CONCEPT_ASSERT(( VertexListGraphConcept )); + BOOST_CONCEPT_ASSERT(( EdgeListGraphConcept )); + BOOST_CONCEPT_ASSERT(( AdjacencyMatrixConcept )); + + BOOST_CONCEPT_ASSERT(( BidirectionalGraphConcept )); + BOOST_CONCEPT_ASSERT(( VertexListGraphConcept )); + BOOST_CONCEPT_ASSERT(( EdgeListGraphConcept )); + BOOST_CONCEPT_ASSERT(( AdjacencyMatrixConcept )); + + typedef typename graph_traits::vertex_descriptor vertex_small_type; + typedef typename graph_traits::vertex_descriptor vertex_large_type; + + typedef typename graph_traits::vertices_size_type size_type_small; + typedef typename graph_traits::vertices_size_type size_type_large; + + // Property map requirements + BOOST_CONCEPT_ASSERT(( ReadablePropertyMapConcept )); + typedef typename property_traits::value_type IndexMapSmallValue; + BOOST_STATIC_ASSERT(( is_convertible::value )); + + BOOST_CONCEPT_ASSERT(( ReadablePropertyMapConcept )); + typedef typename property_traits::value_type IndexMapLargeValue; + BOOST_STATIC_ASSERT(( is_convertible::value )); + + // Edge & vertex requirements + typedef typename graph_traits::edge_descriptor edge_small_type; + typedef typename graph_traits::edge_descriptor edge_large_type; + + BOOST_CONCEPT_ASSERT(( BinaryPredicateConcept )); + + BOOST_CONCEPT_ASSERT(( BinaryPredicateConcept )); + + // Vertex order requirements + BOOST_CONCEPT_ASSERT(( ContainerConcept )); + typedef typename VertexOrderSmall::value_type order_value_type; + BOOST_STATIC_ASSERT(( is_same::value )); + BOOST_ASSERT( num_vertices(graph_small) == vertex_order_small.size() ); + + if (num_vertices(graph_small) > num_vertices(graph_large)) + return false; + + typename graph_traits::edges_size_type num_edges_small = num_edges(graph_small); + typename graph_traits::edges_size_type num_edges_large = num_edges(graph_large); + + // Double the number of edges for undirected graphs: each edge counts as + // in-edge and out-edge + if (is_undirected(graph_small)) num_edges_small *= 2; + if (is_undirected(graph_large)) num_edges_large *= 2; + if (num_edges_small > num_edges_large) + return false; + + if ((num_vertices(graph_small) == 0) && (num_vertices(graph_large) == 0)) + return true; + + detail::state + s(graph_small, graph_large, index_map_small, index_map_large, edge_comp, vertex_comp); + + return detail::match(graph_small, graph_large, user_callback, vertex_order_small, s); + } + } // namespace detail @@ -805,6 +910,72 @@ namespace boost { return vertex_order; } + + // Enumerates all graph sub-graph monomorphism mappings between graphs + // graph_small and graph_large. Continues until user_callback returns true or the + // search space has been fully explored. + template + bool vf2_subgraph_mono(const GraphSmall& graph_small, const GraphLarge& graph_large, + SubGraphIsoMapCallback user_callback, + IndexMapSmall index_map_small, IndexMapLarge index_map_large, + const VertexOrderSmall& vertex_order_small, + EdgeEquivalencePredicate edge_comp, + VertexEquivalencePredicate vertex_comp) { + return detail::vf2_subgraph_morphism + (graph_small, graph_large, + user_callback, + index_map_small, index_map_large, + vertex_order_small, + edge_comp, + vertex_comp); + } + + + // All default interface for vf2_subgraph_iso + template + bool vf2_subgraph_mono(const GraphSmall& graph_small, const GraphLarge& graph_large, + SubGraphIsoMapCallback user_callback) { + return vf2_subgraph_mono(graph_small, graph_large, user_callback, + get(vertex_index, graph_small), get(vertex_index, graph_large), + vertex_order_by_mult(graph_small), + always_equivalent(), always_equivalent()); + } + + + // Named parameter interface of vf2_subgraph_iso + template + bool vf2_subgraph_mono(const GraphSmall& graph_small, const GraphLarge& graph_large, + SubGraphIsoMapCallback user_callback, + const VertexOrderSmall& vertex_order_small, + const bgl_named_params& params) { + return vf2_subgraph_mono(graph_small, graph_large, user_callback, + choose_const_pmap(get_param(params, vertex_index1), + graph_small, vertex_index), + choose_const_pmap(get_param(params, vertex_index2), + graph_large, vertex_index), + vertex_order_small, + choose_param(get_param(params, edges_equivalent_t()), + always_equivalent()), + choose_param(get_param(params, vertices_equivalent_t()), + always_equivalent()) + ); + } + // Enumerates all graph sub-graph isomorphism mappings between graphs // graph_small and graph_large. Continues until user_callback returns true or the @@ -823,71 +994,13 @@ namespace boost { const VertexOrderSmall& vertex_order_small, EdgeEquivalencePredicate edge_comp, VertexEquivalencePredicate vertex_comp) { - - // Graph requirements - BOOST_CONCEPT_ASSERT(( BidirectionalGraphConcept )); - BOOST_CONCEPT_ASSERT(( VertexListGraphConcept )); - BOOST_CONCEPT_ASSERT(( EdgeListGraphConcept )); - BOOST_CONCEPT_ASSERT(( AdjacencyMatrixConcept )); - - BOOST_CONCEPT_ASSERT(( BidirectionalGraphConcept )); - BOOST_CONCEPT_ASSERT(( VertexListGraphConcept )); - BOOST_CONCEPT_ASSERT(( EdgeListGraphConcept )); - BOOST_CONCEPT_ASSERT(( AdjacencyMatrixConcept )); - - typedef typename graph_traits::vertex_descriptor vertex_small_type; - typedef typename graph_traits::vertex_descriptor vertex_large_type; - - typedef typename graph_traits::vertices_size_type size_type_small; - typedef typename graph_traits::vertices_size_type size_type_large; - - // Property map requirements - BOOST_CONCEPT_ASSERT(( ReadablePropertyMapConcept )); - typedef typename property_traits::value_type IndexMapSmallValue; - BOOST_STATIC_ASSERT(( is_convertible::value )); - - BOOST_CONCEPT_ASSERT(( ReadablePropertyMapConcept )); - typedef typename property_traits::value_type IndexMapLargeValue; - BOOST_STATIC_ASSERT(( is_convertible::value )); - - // Edge & vertex requirements - typedef typename graph_traits::edge_descriptor edge_small_type; - typedef typename graph_traits::edge_descriptor edge_large_type; - - BOOST_CONCEPT_ASSERT(( BinaryPredicateConcept )); - - BOOST_CONCEPT_ASSERT(( BinaryPredicateConcept )); - - // Vertex order requirements - BOOST_CONCEPT_ASSERT(( ContainerConcept )); - typedef typename VertexOrderSmall::value_type order_value_type; - BOOST_STATIC_ASSERT(( is_same::value )); - BOOST_ASSERT( num_vertices(graph_small) == vertex_order_small.size() ); - - if (num_vertices(graph_small) > num_vertices(graph_large)) - return false; - - typename graph_traits::edges_size_type num_edges_small = num_edges(graph_small); - typename graph_traits::edges_size_type num_edges_large = num_edges(graph_large); - - // Double the number of edges for undirected graphs: each edge counts as - // in-edge and out-edge - if (is_undirected(graph_small)) num_edges_small *= 2; - if (is_undirected(graph_large)) num_edges_large *= 2; - if (num_edges_small > num_edges_large) - return false; - - if ((num_vertices(graph_small) == 0) && (num_vertices(graph_large) == 0)) - return true; - - detail::state - s(graph_small, graph_large, index_map_small, index_map_large, edge_comp, vertex_comp); - - return detail::match(graph_small, graph_large, user_callback, vertex_order_small, s); + return detail::vf2_subgraph_morphism + (graph_small, graph_large, + user_callback, + index_map_small, index_map_large, + vertex_order_small, + edge_comp, + vertex_comp); } From 3ebad4bc018a13c4c040cfc00f0d6a5251a7be58 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Fri, 1 Mar 2013 18:41:32 +0000 Subject: [PATCH 266/333] Added patch to example from Takatoshi Kondo [SVN r83234] --- example/matching_example.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/example/matching_example.cpp b/example/matching_example.cpp index 704f1df1f..de39f57c5 100644 --- a/example/matching_example.cpp +++ b/example/matching_example.cpp @@ -44,6 +44,7 @@ int main() // our vertices are stored in a vector, so we can refer to vertices // by integers in the range 0..15 + add_edge(1,2,g); add_edge(0,4,g); add_edge(1,5,g); add_edge(2,6,g); From 02aaeccae50c92148f821de2db0d796a4e95b1cb Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Fri, 8 Mar 2013 17:31:15 +0000 Subject: [PATCH 267/333] Changed difference_types to not be void [SVN r83366] --- include/boost/graph/rmat_graph_generator.hpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/include/boost/graph/rmat_graph_generator.hpp b/include/boost/graph/rmat_graph_generator.hpp index 15f7c25e8..f083fc555 100644 --- a/include/boost/graph/rmat_graph_generator.hpp +++ b/include/boost/graph/rmat_graph_generator.hpp @@ -139,7 +139,7 @@ namespace boost { typedef std::pair value_type; typedef const value_type& reference; typedef const value_type* pointer; - typedef void difference_type; + typedef std::ptrdiff_t difference_type; // Not used // No argument constructor, set to terminating condition rmat_iterator() @@ -250,7 +250,7 @@ namespace boost { typedef std::pair value_type; typedef const value_type& reference; typedef const value_type* pointer; - typedef void difference_type; + typedef std::ptrdiff_t difference_type; // Not used // No argument constructor, set to terminating condition sorted_rmat_iterator() @@ -352,7 +352,7 @@ namespace boost { typedef std::pair value_type; typedef const value_type& reference; typedef const value_type* pointer; - typedef void difference_type; + typedef std::ptrdiff_t difference_type; // Not used // No argument constructor, set to terminating condition unique_rmat_iterator() @@ -464,7 +464,7 @@ namespace boost { typedef std::pair value_type; typedef const value_type& reference; typedef const value_type* pointer; - typedef void difference_type; + typedef std::ptrdiff_t difference_type; // Not used // No argument constructor, set to terminating condition sorted_unique_rmat_iterator() From 2539ea8bcaedca551fa42a3849f426e3547772e7 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Tue, 12 Mar 2013 00:34:38 +0000 Subject: [PATCH 268/333] Changed .size() comparison against 0 to .empty() [SVN r83409] --- include/boost/graph/r_c_shortest_paths.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/boost/graph/r_c_shortest_paths.hpp b/include/boost/graph/r_c_shortest_paths.hpp index 9d395799e..834f82e9b 100644 --- a/include/boost/graph/r_c_shortest_paths.hpp +++ b/include/boost/graph/r_c_shortest_paths.hpp @@ -409,7 +409,7 @@ void r_c_shortest_paths_dispatch typename std::list::const_iterator csi = dsplabels.begin(); typename std::list::const_iterator csi_end = dsplabels.end(); // if d could be reached from o - if( dsplabels.size() ) + if( !dsplabels.empty() ) { for( ; csi != csi_end; ++csi ) { From 393c072c186f6711d1537225dc116ea1528140ac Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Tue, 12 Mar 2013 00:35:48 +0000 Subject: [PATCH 269/333] Added maximum adjacency search from Fernando Vilas; fixes #6780 [SVN r83410] --- doc/maximum_adjacency_search.html | 284 +++++++++++++++ doc/table_of_contents.html | 1 + .../boost/graph/maximum_adjacency_search.hpp | 321 +++++++++++++++++ include/boost/graph/stoer_wagner_min_cut.hpp | 339 +++++++++--------- test/Jamfile.v2 | 1 + test/mas_test.cpp | 227 ++++++++++++ 6 files changed, 1009 insertions(+), 164 deletions(-) create mode 100644 doc/maximum_adjacency_search.html create mode 100644 include/boost/graph/maximum_adjacency_search.hpp create mode 100644 test/mas_test.cpp diff --git a/doc/maximum_adjacency_search.html b/doc/maximum_adjacency_search.html new file mode 100644 index 000000000..d2aa9e801 --- /dev/null +++ b/doc/maximum_adjacency_search.html @@ -0,0 +1,284 @@ + + + +Boost Graph Library: Maximum Adjacency Search + +C++ Boost + +

      +maximum_adjacency_search +

      + +

      +

      +// named parameter versions
      +template <class Graph, class class P, class T, class R>
      +void
      +maximum_adjacency_search(const Graph& g,
      +       const bgl_named_params<P, T, R>& params);
      +
      +// non-named parameter versions
      +template <class Graph, class WeightMap, class MASVisitor>
      +void
      +maximum_adjacency_search(const Graph& g, WeightMap weights, MASVisitor vis,
      +       const typename graph_traits<Graph>::vertex_descriptor start);
      +
      +
      + +

      +The maximum_adjacency_search() function performs a traversal +of the vertices in an undirected graph. The next vertex visited is the +vertex that has the most visited neighbors at any time. In the case of +an unweighted, undirected graph, the number of visited neighbors of the +very last vertex visited in the graph is also the number of edge-disjoint +paths between that vertex and the next-to-last vertex visited. These can be +retrieved from a visitor, an example of which is in the test harness +mas_test.cpp. +

      + +

      +The maximum_adjacency_search() function invokes user-defined +actions at certain event-points within the algorithm. This provides a +mechanism for adapting the generic MAS algorithm to the many situations +in which it can be used. In the pseudo-code below, the event points +for MAS are the labels on the right. The user-defined actions must be +provided in the form of a visitor object, that is, an object whose type +meets the requirements for a MAS Visitor. +

      + + + + + + +
      +
      +MAS(G)
      +  for each vertex u in V 
      +    reach_count[u] := 0
      +  end for
      +  // for the starting vertex s
      +  reach_count[s] := 1
      +  for each unvisited vertex u in V
      +    call MAS-VISIT(G, u)
      +    remove u from the list on unvisited vertices
      +    for each out edge from u to t
      +       if t has not yet been visited
      +         increment reach_count[t]
      +       end if
      +    end for each out edge
      +    call MAS-VISIT(G, u)
      +  end for each unvisited vertex
      +
      +
      +
      +-
      +-
      +initialize vertex u
      +-
      +-
      +-
      +-
      +examine vertex u
      +-
      +examine edge (u,t)
      +-
      +-
      +-
      +-
      +finish vertex u
      +-
      +
      +
      + +

      Where Defined

      + +

      +boost/graph/maximum_adjacency_search.hpp

      + +

      Parameters

      + +IN: const UndirectedGraph& g

      +
      + A connected, directed graph. The graph type must + be a model of Incidence Graph + and Vertex List Graph.
      +
      + +

      Named Parameters

      + +

      IN: WeightMap weights

      +
      + The weight or length of each edge in the graph. The + WeightMap type must be a model of + Readable + Property Map and its value type must be + Less Than Comparable and summable. The key type of this map + needs to be the graph's edge descriptor type. + Default: get(edge_weight, g)
      +
      + +IN: visitor(MASVisitor vis)

      +
      + A visitor object that is invoked inside the algorithm at the + event-points specified by the MAS Visitor concept. The visitor + object is passed by value [1].
      + Default: mas_visitor<null_visitor>
      +
      + +IN: root_vertex(typename +graph_traits<VertexListGraph>::vertex_descriptor start)

      +
      + This specifies the vertex that the depth-first search should + originate from. The type is the type of a vertex descriptor for the + given graph.
      + Default: *vertices(g).first
      +
      + +

      Expert Parameters

      + +

      IN: vertex_index_map(VertexIndexMap vertexIndices)

      +
      + This maps each vertex to an integer in the range + [0, num_vertices(g)). This is only necessary if the default is + used for the assignment, index-in-heap, or distance maps. + VertexIndexMap must be a model of Readable Property + Map. The value type of the map must be an integer type. The + key type must be the graph's vertex descriptor type.
      + Default: get(boost::vertex_index, g) + Note: if you use this default, make sure your graph has + an internal vertex_index property. For example, + adjacency_list with VertexList=listS does + not have an internal vertex_index property. +
      + +

      UTIL: vertex_assignment_map(AssignmentMap assignments)

      +
      + AssignmentMap must be a model of Read/Write Property + Map. The key and value types must be the graph's vertex descriptor + type.
      + Default: A boost::iterator_property_map using a + std::vector of num_vertices(g) vertex descriptors and + vertexIndices for the index map. +
      + +

      UTIL: max_priority_queue(MaxPriorityQueue& pq)

      +
      + MaxPriorityQueue must be a model of Keyed Updatable Queue and a + max- + Updatable Priority Queue. The value type must be the graph's vertex + descriptor and the key type must be the weight type. + Default: A boost::d_ary_heap_indirect using a default + index-in-heap and distance map. +
      + +

      UTIL: index_in_heap_map(IndexInHeapMap indicesInHeap)

      +
      + This parameter only has an effect when the default max-priority queue is used.
      + IndexInHeapMap must be a model of Read/Write Property + Map. The key type must be the graph's vertex descriptor type. The + value type must be a size type + (typename std::vector<vertex_descriptor>::size_type).
      + Default: A boost::iterator_property_map using a + std::vector of num_vertices(g) size type objects and + vertexIndices for the index map. +
      + +

      UTIL: distance_map(DistanceMap wAs)

      +
      + This parameter only has an effect when the default max-priority queue is used.
      + DistanceMap must be a model of Read/Write Property + Map. The key type must be the graph's vertex descriptor type. The + value type must be the weight type + (typename boost::property_traits<WeightMap>::value_type). +
      + Default: A boost::iterator_property_map using a + std::vector of num_vertices(g) weight type objects + and vertexIndices for the index map. +
      + +

      Returns

      +

      void

      + +

      Throws

      + +

      bad_graph +

      + If num_vertices(g) is less than 2 +

      + +

      std::invalid_argument +

      + If a max-priority queue is given as an argument and it is not empty +
      . + +

      +Complexity +

      + +

      +The time complexity is O(E + V). +

      + +

      References

      + + +

      Visitor Event Points

      + +
        +
      • vis.initialize_vertex(s, g) is invoked on every + vertex of the graph before the start of the graph search.
      • + +
      • vis.start_vertex(s, g) is invoked on the source + vertex once before processing its out edges.
      • + +
      • vis.examine_edge(e, g) is invoked on every out-edge + of each vertex after it is started.
      • + +
      • vis.finish_vertex(u, g) is invoked on a vertex after + all of its out edges have been examined and the reach counts of the + unvisited targets have been updated.
      • +
      + +

      Notes

      + +

      [1] + Since the visitor parameter is passed by value, if your visitor + contains state then any changes to the state during the algorithm + will be made to a copy of the visitor object, not the visitor object + passed in. Therefore you may want the visitor to hold this state by + pointer or reference.

      + +
      + + +
      Copyright © 2012 +Fernando Vilas +
      + + + diff --git a/doc/table_of_contents.html b/doc/table_of_contents.html index 3bf185239..0fd36e8e2 100644 --- a/doc/table_of_contents.html +++ b/doc/table_of_contents.html @@ -287,6 +287,7 @@

      Table of Contents: the Boost Graph Library
    2. sequential_vertex_coloring
    3. is_bipartite (including two-coloring of bipartite graphs)
    4. find_odd_cycle +
    5. maximum_adjacency_search
  • diff --git a/include/boost/graph/maximum_adjacency_search.hpp b/include/boost/graph/maximum_adjacency_search.hpp new file mode 100644 index 000000000..a87c90de5 --- /dev/null +++ b/include/boost/graph/maximum_adjacency_search.hpp @@ -0,0 +1,321 @@ +// +//======================================================================= +// Copyright 2012 Fernando Vilas +// 2010 Daniel Trebbien +// +// 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) +//======================================================================= +// + +// The maximum adjacency search algorithm was originally part of the +// Stoer-Wagner min cut implementation by Daniel Trebbien. It has been +// broken out into its own file to be a public search algorithm, with +// visitor concepts. +#ifndef BOOST_GRAPH_MAXIMUM_ADJACENCY_SEARCH_H +#define BOOST_GRAPH_MAXIMUM_ADJACENCY_SEARCH_H + +/** + * This is an implementation of the maximum adjacency search on an + * undirected graph. It allows a visitor object to perform some + * operation on each vertex as that vertex is visited. + * + * The algorithm runs as follows: + * + * Initialize all nodes to be unvisited (reach count = 0) + * and call vis.initialize_vertex + * For i = number of nodes in graph downto 1 + * Select the unvisited node with the highest reach count + * The user provides the starting node to break the first tie, + * but future ties are broken arbitrarily + * Visit the node by calling vis.start_vertex + * Increment the reach count for all unvisited neighbors + * and call vis.examine_edge for each of these edges + * Mark the node as visited and call vis.finish_vertex + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +namespace boost { + template + struct MASVisitorConcept { + void constraints() { + boost::function_requires< boost::CopyConstructibleConcept >(); + vis.initialize_vertex(u, g); + vis.start_vertex(u, g); + vis.examine_edge(e, g); + vis.finish_vertex(u, g); + } + Visitor vis; + Graph g; + typename boost::graph_traits::vertex_descriptor u; + typename boost::graph_traits::edge_descriptor e; + }; + + template + class mas_visitor { + public: + mas_visitor() { } + mas_visitor(Visitors vis) : m_vis(vis) { } + + template + void + initialize_vertex(Vertex u, Graph& g) + { + invoke_visitors(m_vis, u, g, ::boost::on_initialize_vertex()); + } + + template + void + start_vertex(Vertex u, Graph& g) + { + invoke_visitors(m_vis, u, g, ::boost::on_start_vertex()); + } + + template + void + examine_edge(Edge e, Graph& g) + { + invoke_visitors(m_vis, e, g, ::boost::on_examine_edge()); + } + + template + void + finish_vertex(Vertex u, Graph& g) + { + invoke_visitors(m_vis, u, g, ::boost::on_finish_vertex()); + } + + BOOST_GRAPH_EVENT_STUB(on_initialize_vertex,mas) + BOOST_GRAPH_EVENT_STUB(on_start_vertex,mas) + BOOST_GRAPH_EVENT_STUB(on_examine_edge,mas) + BOOST_GRAPH_EVENT_STUB(on_finish_vertex,mas) + + protected: + Visitors m_vis; + }; + template + mas_visitor + make_mas_visitor(Visitors vis) { + return mas_visitor(vis); + } + typedef mas_visitor<> default_mas_visitor; + + namespace detail { + template + void + maximum_adjacency_search(const Graph& g, WeightMap weights, MASVisitor vis, const typename boost::graph_traits::vertex_descriptor start, VertexAssignmentMap assignments, KeyedUpdatablePriorityQueue pq) { + typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; + typedef typename boost::graph_traits::vertices_size_type vertices_size_type; + typedef typename boost::graph_traits::edge_descriptor edge_descriptor; + typedef typename boost::property_traits::value_type weight_type; + + std::set assignedVertices; + + // initialize `assignments` (all vertices are initially + // assigned to themselves) + BGL_FORALL_VERTICES_T(v, g, Graph) { + put(assignments, v, v); + } + + typename KeyedUpdatablePriorityQueue::key_map keys = pq.keys(); + + // set number of visited neighbors for all vertices to 0 + BGL_FORALL_VERTICES_T(v, g, Graph) { + if (v == get(assignments, v)) { // foreach u \in V do + put(keys, v, weight_type(0)); vis.initialize_vertex(v, g); + + pq.push(v); + } + } + BOOST_ASSERT(pq.size() >= 2); + + // Give the starting vertex high priority + put(keys, start, get(keys, start) + num_vertices(g) + 1); + pq.update(start); + + // start traversing the graph + //vertex_descriptor s, t; + weight_type w; + while (!pq.empty()) { // while PQ \neq {} do + const vertex_descriptor u = pq.top(); // u = extractmax(PQ) + w = get(keys, u); vis.start_vertex(u, g); + pq.pop(); // vis.start_vertex(u, g); + + BGL_FORALL_OUTEDGES_T(u, e, g, Graph) { // foreach (u, v) \in E do + vis.examine_edge(e, g); + + const vertex_descriptor v = get(assignments, target(e, g)); + + if (pq.contains(v)) { // if v \in PQ then + put(keys, v, get(keys, v) + get(weights, e)); // increasekey(PQ, v, wA(v) + w(u, v)) + pq.update(v); + } + } + + typename std::set::const_iterator assignedVertexIt, assignedVertexEnd = assignedVertices.end(); + for (assignedVertexIt = assignedVertices.begin(); assignedVertexIt != assignedVertexEnd; ++assignedVertexIt) { + const vertex_descriptor uPrime = *assignedVertexIt; + + if (get(assignments, uPrime) == u) { + BGL_FORALL_OUTEDGES_T(uPrime, e, g, Graph) { // foreach (u, v) \in E do + vis.examine_edge(e, g); + + const vertex_descriptor v = get(assignments, target(e, g)); + + if (pq.contains(v)) { // if v \in PQ then + put(keys, v, get(keys, v) + get(weights, e)); // increasekey(PQ, v, wA(v) + w(u, v)) + pq.update(v); + } + } + } + } + vis.finish_vertex(u, g); + } + } + } // end namespace detail + + template + void +maximum_adjacency_search(const Graph& g, WeightMap weights, MASVisitor vis, const typename boost::graph_traits::vertex_descriptor start, VertexAssignmentMap assignments, KeyedUpdatablePriorityQueue pq) { + BOOST_CONCEPT_ASSERT((boost::IncidenceGraphConcept)); + BOOST_CONCEPT_ASSERT((boost::VertexListGraphConcept)); + typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; + typedef typename boost::graph_traits::vertices_size_type vertices_size_type; + typedef typename boost::graph_traits::edge_descriptor edge_descriptor; + BOOST_CONCEPT_ASSERT((boost::Convertible::directed_category, boost::undirected_tag>)); + BOOST_CONCEPT_ASSERT((boost::ReadablePropertyMapConcept)); + typedef typename boost::property_traits::value_type weight_type; + boost::function_requires< MASVisitorConcept >(); + BOOST_CONCEPT_ASSERT((boost::ReadWritePropertyMapConcept)); + BOOST_CONCEPT_ASSERT((boost::Convertible::value_type>)); + BOOST_CONCEPT_ASSERT((boost::KeyedUpdatableQueueConcept)); + + vertices_size_type n = num_vertices(g); + if (n < 2) + throw boost::bad_graph("the input graph must have at least two vertices."); + else if (!pq.empty()) + throw std::invalid_argument("the max-priority queue must be empty initially."); + + detail::maximum_adjacency_search(g, weights, + vis, start, + assignments, pq); + } + + namespace graph { + namespace detail { + template + struct mas_dispatch { + typedef void result_type; + template + static result_type apply(const Graph& g, + //const bgl_named_params& params, + const ArgPack& params, + WeightMap w) { + + using namespace boost::graph::keywords; + typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; + typedef typename WeightMap::value_type weight_type; + + typedef boost::detail::make_priority_queue_from_arg_pack_gen > default_pq_gen_type; + + default_pq_gen_type pq_gen(choose_param(get_param(params, boost::distance_zero_t()), weight_type(0))); + + typename boost::result_of::type pq = pq_gen(g, params); + + boost::maximum_adjacency_search + (g, + w, + params [ _visitor | make_mas_visitor(null_visitor())], + params [ _root_vertex | *vertices(g).first], + params [ _vertex_assignment_map | boost::detail::make_property_map_from_arg_pack_gen(vertex_descriptor())(g, params)], + pq + ); + } + }; + + template <> + struct mas_dispatch { + typedef void result_type; + + template + static result_type apply(const Graph& g, + const ArgPack& params, + param_not_found) { + + using namespace boost::graph::keywords; + typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; + + // get edge_weight_t as the weight type + typedef typename boost::property_map WeightMap; + typedef typename WeightMap::value_type weight_type; + + typedef boost::detail::make_priority_queue_from_arg_pack_gen > default_pq_gen_type; + + default_pq_gen_type pq_gen(choose_param(get_param(params, boost::distance_zero_t()), weight_type(0))); + + typename boost::result_of::type pq = pq_gen(g, params); + + boost::maximum_adjacency_search + (g, + get(edge_weight, g), + params [ _visitor | make_mas_visitor(null_visitor())], + params [ _root_vertex | *vertices(g).first], + params [ _vertex_assignment_map | boost::detail::make_property_map_from_arg_pack_gen(vertex_descriptor())(g, params)], + pq + ); + } + }; + } // end namespace detail + } // end namespace graph + + // Named parameter interface + //BOOST_GRAPH_MAKE_OLD_STYLE_PARAMETER_FUNCTION(maximum_adjacency_search, 1) + template + void + maximum_adjacency_search (const Graph& g, + const bgl_named_params& params) { + + typedef bgl_named_params params_type; + BOOST_GRAPH_DECLARE_CONVERTED_PARAMETERS(params_type, params) + + // do the dispatch based on WeightMap + typedef typename get_param_type >::type W; + graph::detail::mas_dispatch::apply(g, arg_pack, get_param(params, edge_weight)); + } + + namespace graph { + namespace detail { + template + struct maximum_adjacency_search_impl { + typedef void result_type; + + template + void + operator() (const Graph& g, const ArgPack arg_pack) const { + // call the function that does the dispatching + typedef typename get_param_type::type W; + graph::detail::mas_dispatch::apply(g, arg_pack, get_param(arg_pack, edge_weight)); + } + }; + } // end namespace detail + BOOST_GRAPH_MAKE_FORWARDING_FUNCTION(maximum_adjacency_search,1,5) + } // end namespace graph + +} // end namespace boost + +#include + +#endif // BOOST_GRAPH_MAXIMUM_ADJACENCY_SEARCH_H diff --git a/include/boost/graph/stoer_wagner_min_cut.hpp b/include/boost/graph/stoer_wagner_min_cut.hpp index 060f51b4a..c868c0c83 100644 --- a/include/boost/graph/stoer_wagner_min_cut.hpp +++ b/include/boost/graph/stoer_wagner_min_cut.hpp @@ -15,104 +15,96 @@ #include #include #include -#include +#include #include +#include #include #include #include #include +#include namespace boost { - + namespace detail { - - /** - * \brief Performs a phase of the Stoer-Wagner min-cut algorithm - * - * Performs a phase of the Stoer-Wagner min-cut algorithm. - * - * As described by Stoer & Wagner (1997), a phase is simply a maximum adjacency search - * (also called a maximum cardinality search), which results in the selection of two vertices - * \em s and \em t, and, as a side product, a minimum s-t cut of - * the input graph. Here, the input graph is basically \p g, but some vertices are virtually - * assigned to others as a way of viewing \p g as a graph with some sets of - * vertices merged together. - * - * This implementation is a translation of pseudocode by Professor Uri Zwick, - * School of Computer Science, Tel Aviv University. - * - * \pre \p g is a connected, undirected graph - * \param[in] g the input graph - * \param[in] assignments a read/write property map from each vertex to the vertex that it is assigned to - * \param[in] assignedVertices a list of vertices that are assigned to others - * \param[in] weights a readable property map from each edge to its weight (a non-negative value) - * \param[out] pq a keyed, updatable max-priority queue - * \returns a tuple (\em s, \em t, \em w) of the "s" and "t" - * of the minimum s-t cut and the cut weight \em w - * of the minimum s-t cut. - * \see http://www.cs.tau.ac.il/~zwick/grad-algo-08/gmc.pdf - * - * \author Daniel Trebbien - * \date 2010-09-11 - */ - template - boost::tuple::vertex_descriptor, typename boost::graph_traits::vertex_descriptor, typename boost::property_traits::value_type> - stoer_wagner_phase(const UndirectedGraph& g, VertexAssignmentMap assignments, const std::set::vertex_descriptor>& assignedVertices, WeightMap weights, KeyedUpdatablePriorityQueue& pq) { - typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; + template < typename ParityMap, typename WeightMap, typename IndexMap > + class mas_min_cut_visitor : public boost::default_mas_visitor { + typedef one_bit_color_map InternalParityMap; typedef typename boost::property_traits::value_type weight_type; - - BOOST_ASSERT(pq.empty()); - typename KeyedUpdatablePriorityQueue::key_map keys = pq.keys(); - - BGL_FORALL_VERTICES_T(v, g, UndirectedGraph) { - if (v == get(assignments, v)) { // foreach u \in V do - put(keys, v, weight_type(0)); - - pq.push(v); - } + public: + template < typename Graph > + mas_min_cut_visitor(const Graph& g, + ParityMap parity, + weight_type& cutweight, + WeightMap weight_map, + IndexMap index_map) + : m_bestParity(parity), + m_parity(make_one_bit_color_map(num_vertices(g), index_map)), + m_bestWeight(cutweight), + m_cutweight(0), + m_visited(0), + m_weightMap(weight_map) + { + // set here since the init list sets the reference + m_bestWeight = (std::numeric_limits::max)(); } - - BOOST_ASSERT(pq.size() >= 2); - - vertex_descriptor s = boost::graph_traits::null_vertex(); - vertex_descriptor t = boost::graph_traits::null_vertex(); - weight_type w; - while (!pq.empty()) { // while PQ \neq {} do - const vertex_descriptor u = pq.top(); // u = extractmax(PQ) - w = get(keys, u); - pq.pop(); - - s = t; t = u; - - BGL_FORALL_OUTEDGES_T(u, e, g, UndirectedGraph) { // foreach (u, v) \in E do - const vertex_descriptor v = get(assignments, target(e, g)); - - if (pq.contains(v)) { // if v \in PQ then - put(keys, v, get(keys, v) + get(weights, e)); // increasekey(PQ, v, wA(v) + w(u, v)) - pq.update(v); - } + + template < typename Vertex, typename Graph > + void initialize_vertex(Vertex u, const Graph & g) + { + typedef typename boost::property_traits::value_type parity_type; + typedef typename boost::property_traits::value_type internal_parity_type; + + put(m_parity, u, internal_parity_type(0)); + put(m_bestParity, u, parity_type(0)); + } + + template < typename Edge, typename Graph > + void examine_edge(Edge e, const Graph & g) + { + weight_type w = get(m_weightMap, e); + + // if the target of e is already marked then decrease cutweight + // otherwise, increase it + if (get(m_parity, boost::target(e, g))) { + m_cutweight -= w; + } else { + m_cutweight += w; } - - typename std::set::const_iterator assignedVertexIt, assignedVertexEnd = assignedVertices.end(); - for (assignedVertexIt = assignedVertices.begin(); assignedVertexIt != assignedVertexEnd; ++assignedVertexIt) { - const vertex_descriptor uPrime = *assignedVertexIt; - - if (get(assignments, uPrime) == u) { - BGL_FORALL_OUTEDGES_T(uPrime, e, g, UndirectedGraph) { // foreach (u, v) \in E do - const vertex_descriptor v = get(assignments, target(e, g)); - - if (pq.contains(v)) { // if v \in PQ then - put(keys, v, get(keys, v) + get(weights, e)); // increasekey(PQ, v, wA(v) + w(u, v)) - pq.update(v); - } - } + } + + template < typename Vertex, typename Graph > + void finish_vertex(Vertex u, const Graph & g) + { + typedef typename boost::property_traits::value_type parity_type; + typedef typename boost::property_traits::value_type internal_parity_type; + + ++m_visited; + put(m_parity, u, internal_parity_type(1)); + + if (m_cutweight < m_bestWeight && m_visited < num_vertices(g)) { + m_bestWeight = m_cutweight; + BGL_FORALL_VERTICES_T(i, g, Graph) { + put(m_bestParity,i, get(m_parity,i)); } } } - - return boost::make_tuple(s, t, w); - } - + + inline void clear() { + m_bestWeight = (std::numeric_limits::max)(); + m_visited = 0; + m_cutweight = 0; + } + + private: + ParityMap m_bestParity; + InternalParityMap m_parity; + weight_type& m_bestWeight; + weight_type m_cutweight; + unsigned m_visited; + const WeightMap& m_weightMap; + }; + /** * \brief Computes a min-cut of the input graph * @@ -135,9 +127,57 @@ namespace boost { * \author Daniel Trebbien * \date 2010-09-11 */ - template + template typename boost::property_traits::value_type - stoer_wagner_min_cut(const UndirectedGraph& g, WeightMap weights, ParityMap parities, VertexAssignmentMap assignments, KeyedUpdatablePriorityQueue& pq) { + stoer_wagner_min_cut(const UndirectedGraph& g, WeightMap weights, ParityMap parities, VertexAssignmentMap assignments, KeyedUpdatablePriorityQueue& pq, IndexMap index_map) { + typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; + typedef typename boost::graph_traits::vertices_size_type vertices_size_type; + typedef typename boost::graph_traits::edge_descriptor edge_descriptor; + typedef typename boost::property_traits::value_type weight_type; + typedef typename boost::property_traits::value_type parity_type; + + typename graph_traits::vertex_iterator u_iter, u_end; + + weight_type bestW = (std::numeric_limits::max)(); + weight_type bestThisTime = (std::numeric_limits::max)(); + vertex_descriptor bestStart; + + detail::mas_min_cut_visitor + vis(g, parities, bestThisTime, weights, index_map); + + // for each node in the graph, + for (boost::tie(u_iter, u_end) = vertices(g); u_iter != u_end; ++u_iter) { + // run the MAS and find the min cut + vis.clear(); + boost::maximum_adjacency_search(g, + boost::weight_map(weights). + visitor(vis). + root_vertex(*u_iter). + vertex_assignment_map(assignments). + max_priority_queue(pq)); + if (bestThisTime < bestW) { + bestW = bestThisTime; + bestStart = *u_iter; + } + } + + // Run one more time, starting from the best start location, to + // ensure the visitor has the best values. + vis.clear(); + boost::maximum_adjacency_search(g, + boost::vertex_assignment_map(assignments). + weight_map(weights). + visitor(vis). + root_vertex(bestStart). + max_priority_queue(pq)); + + return bestW; + } + } // end `namespace detail` within `namespace boost` + + template + typename boost::property_traits::value_type + stoer_wagner_min_cut(const UndirectedGraph& g, WeightMap weights, ParityMap parities, VertexAssignmentMap assignments, KeyedUpdatablePriorityQueue& pq, IndexMap index_map) { BOOST_CONCEPT_ASSERT((boost::IncidenceGraphConcept)); BOOST_CONCEPT_ASSERT((boost::VertexListGraphConcept)); typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; @@ -151,91 +191,62 @@ namespace boost { BOOST_CONCEPT_ASSERT((boost::ReadWritePropertyMapConcept)); BOOST_CONCEPT_ASSERT((boost::Convertible::value_type>)); BOOST_CONCEPT_ASSERT((boost::KeyedUpdatableQueueConcept)); - + vertices_size_type n = num_vertices(g); if (n < 2) throw boost::bad_graph("the input graph must have at least two vertices."); else if (!pq.empty()) throw std::invalid_argument("the max-priority queue must be empty initially."); - - std::set assignedVertices; - - // initialize `assignments` (all vertices are initially assigned to themselves) - BGL_FORALL_VERTICES_T(v, g, UndirectedGraph) { - put(assignments, v, v); - } - - vertex_descriptor s, t; - weight_type bestW; - - boost::tie(s, t, bestW) = boost::detail::stoer_wagner_phase(g, assignments, assignedVertices, weights, pq); - BOOST_ASSERT(s != t); - BGL_FORALL_VERTICES_T(v, g, UndirectedGraph) { - put(parities, v, parity_type(v == t ? 1 : 0)); - } - put(assignments, t, s); - assignedVertices.insert(t); - --n; - - for (; n >= 2; --n) { - weight_type w; - boost::tie(s, t, w) = boost::detail::stoer_wagner_phase(g, assignments, assignedVertices, weights, pq); - BOOST_ASSERT(s != t); - - if (w < bestW) { - BGL_FORALL_VERTICES_T(v, g, UndirectedGraph) { - put(parities, v, parity_type(get(assignments, v) == t ? 1 : 0)); - - if (get(assignments, v) == t) // all vertices that were assigned to t are now assigned to s - put(assignments, v, s); - } - - bestW = w; - } else { - BGL_FORALL_VERTICES_T(v, g, UndirectedGraph) { - if (get(assignments, v) == t) // all vertices that were assigned to t are now assigned to s - put(assignments, v, s); - } - } - put(assignments, t, s); - assignedVertices.insert(t); - } - - BOOST_ASSERT(pq.empty()); - - return bestW; + + return detail::stoer_wagner_min_cut(g, weights, + parities, assignments, pq, index_map); } - - } // end `namespace detail` within `namespace boost` - - template - inline typename boost::property_traits::value_type - stoer_wagner_min_cut(const UndirectedGraph& g, WeightMap weights, const boost::bgl_named_params& params) { - typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; - typedef typename std::vector::size_type heap_container_size_type; - typedef typename boost::property_traits::value_type weight_type; - - typedef boost::bgl_named_params params_type; - BOOST_GRAPH_DECLARE_CONVERTED_PARAMETERS(params_type, params) - - typedef boost::detail::make_priority_queue_from_arg_pack_gen > gen_type; - gen_type gen(choose_param(get_param(params, boost::distance_zero_t()), weight_type(0))); - typename boost::result_of::type pq = gen(g, arg_pack); - - return boost::detail::stoer_wagner_min_cut(g, - weights, - choose_param(get_param(params, boost::parity_map_t()), boost::dummy_property_map()), - boost::detail::make_property_map_from_arg_pack_gen(vertex_descriptor())(g, arg_pack), - pq - ); - } - - template - inline typename boost::property_traits::value_type - stoer_wagner_min_cut(const UndirectedGraph& g, WeightMap weights) { - return boost::stoer_wagner_min_cut(g, weights, boost::vertex_index_map(get(boost::vertex_index, g))); + +namespace graph { + namespace detail { + template + struct stoer_wagner_min_cut_impl { + typedef typename boost::property_traits::value_type result_type; + template + result_type operator() (const UndirectedGraph& g, WeightMap weights, const ArgPack& arg_pack) const { + using namespace boost::graph::keywords; + typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; + typedef typename boost::property_traits::value_type weight_type; + + typedef typename boost::detail::make_priority_queue_from_arg_pack_gen > gen_type; + + gen_type gen(choose_param(get_param(arg_pack, boost::distance_zero_t()), weight_type(0))); + + typename boost::result_of::type pq = gen(g, arg_pack); + + return boost::stoer_wagner_min_cut(g, + weights, + arg_pack [_parity_map | boost::dummy_property_map()], + boost::detail::make_property_map_from_arg_pack_gen(vertex_descriptor())(g, arg_pack), + pq, + boost::detail::override_const_property(arg_pack, _vertex_index_map, g, vertex_index) + ); + } + }; } - + BOOST_GRAPH_MAKE_FORWARDING_FUNCTION(stoer_wagner_min_cut,2,4) +} + + // Named parameter interface + BOOST_GRAPH_MAKE_OLD_STYLE_PARAMETER_FUNCTION(stoer_wagner_min_cut, 2) +namespace graph { + // version without IndexMap kept for backwards compatibility + // (but requires vertex_index_t to be defined in the graph) + // Place after the macro to avoid compilation errors + template + typename boost::property_traits::value_type + stoer_wagner_min_cut(const UndirectedGraph& g, WeightMap weights, ParityMap parities, VertexAssignmentMap assignments, KeyedUpdatablePriorityQueue& pq) { + + return stoer_wagner_min_cut(g, weights, + parities, assignments, pq, + get(vertex_index, g)); + } +} // end `namespace graph` } // end `namespace boost` #include diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 99eb25407..88d824608 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -123,6 +123,7 @@ test-suite graph_test : [ run two_graphs_common_spanning_trees_test.cpp ] [ run random_spanning_tree_test.cpp ../build//boost_graph ] [ run graphml_test.cpp ../build//boost_graph : : "graphml_test.xml" ] + [ run mas_test.cpp ../../test/build//boost_unit_test_framework/static : $(TEST_DIR) ] [ run stoer_wagner_test.cpp ../../test/build//boost_unit_test_framework/static : $(TEST_DIR) ] [ compile filtered_graph_properties_dijkstra.cpp ] [ run vf2_sub_graph_iso_test.cpp ] diff --git a/test/mas_test.cpp b/test/mas_test.cpp new file mode 100644 index 000000000..9fefdd228 --- /dev/null +++ b/test/mas_test.cpp @@ -0,0 +1,227 @@ +// Copyright Fernando Vilas 2012. +// Based on stoer_wagner_test.cpp by Daniel Trebbien. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or the copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +typedef boost::adjacency_list > undirected_graph; +typedef boost::property_map::type weight_map_type; +typedef boost::property_traits::value_type weight_type; + +typedef boost::adjacency_list undirected_unweighted_graph; + +std::string test_dir; + +boost::unit_test::test_suite* init_unit_test_suite( int argc, char* argv[] ) { + if (argc != 2) { + std::cerr << "Usage: " << argv[0] << " path-to-libs-graph-test" << std::endl; + throw boost::unit_test::framework::setup_error("Invalid command line arguments"); + } + test_dir = argv[1]; + return 0; +} + +struct edge_t +{ + unsigned long first; + unsigned long second; +}; + +template +class mas_edge_connectivity_visitor : public boost::default_mas_visitor { + public: + typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; + typedef typename KeyedUpdatablePriorityQueue::key_type weight_type; +#if 0 + mas_edge_connectivity_visitor(const mas_edge_connectivity_visitor& r) + : m_pq(r.m_pq), m_curr(r.m_curr), m_prev(r.m_prev), + m_reach_weight(r.m_reach_weight) { + BOOST_TEST_MESSAGE( "COPY CTOR" ); + } +#endif + explicit mas_edge_connectivity_visitor(KeyedUpdatablePriorityQueue& pq) + : m_pq(pq), + m_curr(new vertex_descriptor(0)), m_prev(new vertex_descriptor(0)), + m_reach_weight(new weight_type(0)) { + // BOOST_TEST_MESSAGE( "CTOR" ); + } + + void clear() { + *m_curr = 0; + *m_prev = 0; + *m_reach_weight = 0; + } + + //template //, typename Graph> + //void start_vertex(Vertex u, const Graph& g) { + void start_vertex(vertex_descriptor u, const Graph& g) { + *m_prev = *m_curr; + *m_curr = u; + //BOOST_TEST_MESSAGE( "Initializing Vertex(weight): " << u << "(" << *m_reach_weight << ")" ); + *m_reach_weight = get(m_pq.keys(), u); + } + + vertex_descriptor curr() const { return *m_curr; } + vertex_descriptor prev() const { return *m_prev; } + weight_type reach_weight() const { return *m_reach_weight; } + + private: + + const KeyedUpdatablePriorityQueue& m_pq; + boost::shared_ptr m_curr, m_prev; + boost::shared_ptr m_reach_weight; +}; + + +// the example from Stoer & Wagner (1997) +// Check various implementations of the ArgPack where +// the weights are provided in it, and one case where +// they are not. +BOOST_AUTO_TEST_CASE(test0) +{ + typedef boost::graph_traits::vertex_descriptor vertex_descriptor; + typedef boost::graph_traits::edge_descriptor edge_descriptor; + + edge_t edges[] = {{0, 1}, {1, 2}, {2, 3}, + {0, 4}, {1, 4}, {1, 5}, {2, 6}, {3, 6}, {3, 7}, {4, 5}, {5, 6}, {6, 7}}; + weight_type ws[] = {2, 3, 4, 3, 2, 2, 2, 2, 2, 3, 1, 3}; + undirected_graph g(edges, edges + 12, ws, 8, 12); + + weight_map_type weights = get(boost::edge_weight, g); + + std::map assignment; + boost::associative_property_map > assignments(assignment); + + typedef boost::shared_array_property_map::const_type> distances_type; + distances_type distances = boost::make_shared_array_property_map(num_vertices(g), weight_type(0), get(boost::vertex_index, g)); + typedef std::vector::size_type index_in_heap_type; + typedef boost::shared_array_property_map::const_type> indicesInHeap_type; + indicesInHeap_type indicesInHeap = boost::make_shared_array_property_map(num_vertices(g), index_in_heap_type(-1), get(boost::vertex_index, g)); + boost::d_ary_heap_indirect > pq(distances, indicesInHeap); + + mas_edge_connectivity_visitor > > test_vis(pq); + + boost::maximum_adjacency_search(g, + boost::weight_map(weights). + visitor(test_vis). + root_vertex(*vertices(g).first). + vertex_assignment_map(assignments). + max_priority_queue(pq)); + + BOOST_CHECK_EQUAL(test_vis.curr(), vertex_descriptor(7)); + BOOST_CHECK_EQUAL(test_vis.prev(), vertex_descriptor(6)); + BOOST_CHECK_EQUAL(test_vis.reach_weight(), 5); + + test_vis.clear(); + boost::maximum_adjacency_search(g, + boost::weight_map(weights). + visitor(test_vis). + root_vertex(*vertices(g).first). + max_priority_queue(pq)); + + BOOST_CHECK_EQUAL(test_vis.curr(), vertex_descriptor(7)); + BOOST_CHECK_EQUAL(test_vis.prev(), vertex_descriptor(6)); + BOOST_CHECK_EQUAL(test_vis.reach_weight(), 5); + + test_vis.clear(); + boost::maximum_adjacency_search(g, + boost::weight_map(weights). + visitor(test_vis). + max_priority_queue(pq)); + + BOOST_CHECK_EQUAL(test_vis.curr(), vertex_descriptor(7)); + BOOST_CHECK_EQUAL(test_vis.prev(), vertex_descriptor(6)); + BOOST_CHECK_EQUAL(test_vis.reach_weight(), 5); + + boost::maximum_adjacency_search(g, + boost::weight_map(weights). + visitor(boost::make_mas_visitor(boost::null_visitor()))); + + boost::maximum_adjacency_search(g, + boost::weight_map(weights)); + + boost::maximum_adjacency_search(g, + boost::root_vertex(*vertices(g).first)); + + test_vis.clear(); + boost::maximum_adjacency_search(g, + boost::weight_map(boost::make_constant_property(weight_type(1))). + visitor(test_vis). + max_priority_queue(pq)); + BOOST_CHECK_EQUAL(test_vis.curr(), vertex_descriptor(7)); + BOOST_CHECK_EQUAL(test_vis.prev(), vertex_descriptor(3)); + BOOST_CHECK_EQUAL(test_vis.reach_weight(), 2); + +} + +// Check the unweighted case +// with and without providing a weight_map +BOOST_AUTO_TEST_CASE(test1) +{ + typedef boost::graph_traits::vertex_descriptor vertex_descriptor; + typedef boost::graph_traits::edge_descriptor edge_descriptor; + + edge_t edge_list[] = {{0, 1}, {1, 2}, {2, 3}, + {0, 4}, {1, 4}, {1, 5}, {2, 6}, {3, 6}, {3, 7}, {4, 5}, {5, 6}, {6, 7}}; + undirected_unweighted_graph g(edge_list, edge_list + 12, 8); + + std::map assignment; + boost::associative_property_map > assignments(assignment); + + typedef unsigned weight_type; + typedef boost::shared_array_property_map::const_type> distances_type; + distances_type distances = boost::make_shared_array_property_map(num_vertices(g), weight_type(0), get(boost::vertex_index, g)); + typedef std::vector::size_type index_in_heap_type; + typedef boost::shared_array_property_map::const_type> indicesInHeap_type; + indicesInHeap_type indicesInHeap = boost::make_shared_array_property_map(num_vertices(g), index_in_heap_type(-1), get(boost::vertex_index, g)); + boost::d_ary_heap_indirect > pq(distances, indicesInHeap); + + mas_edge_connectivity_visitor > > test_vis(pq); + + boost::maximum_adjacency_search(g, + boost::weight_map(boost::make_constant_property(weight_type(1))).visitor(test_vis).max_priority_queue(pq)); + + BOOST_CHECK_EQUAL(test_vis.curr(), vertex_descriptor(7)); + BOOST_CHECK_EQUAL(test_vis.prev(), vertex_descriptor(3)); + BOOST_CHECK_EQUAL(test_vis.reach_weight(), weight_type(2)); + + weight_type ws[] = {2, 3, 4, 3, 2, 2, 2, 2, 2, 3, 1, 3}; + std::map wm; + + weight_type i = 0; + BGL_FORALL_EDGES_T(e, g, undirected_unweighted_graph) { + wm[e] = ws[i]; + ++i; + } + boost::associative_property_map > ws_map(wm); + + boost::maximum_adjacency_search(g, boost::weight_map(ws_map).visitor(test_vis).max_priority_queue(pq)); + BOOST_CHECK_EQUAL(test_vis.curr(), vertex_descriptor(7)); + BOOST_CHECK_EQUAL(test_vis.prev(), vertex_descriptor(6)); + BOOST_CHECK_EQUAL(test_vis.reach_weight(), weight_type(5)); + +} + +#include + From 0e4f022d9d6fc28faece3fe357870ca95fb46539 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Fri, 5 Apr 2013 18:25:33 +0000 Subject: [PATCH 270/333] Changed test for negative edges per #8398; fixes #8398 [SVN r83772] --- include/boost/graph/dijkstra_shortest_paths.hpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/include/boost/graph/dijkstra_shortest_paths.hpp b/include/boost/graph/dijkstra_shortest_paths.hpp index be0f97ea7..45bac7df3 100644 --- a/include/boost/graph/dijkstra_shortest_paths.hpp +++ b/include/boost/graph/dijkstra_shortest_paths.hpp @@ -159,7 +159,11 @@ namespace boost { void examine_vertex(Vertex u, Graph& g) { m_vis.examine_vertex(u, g); } template void examine_edge(Edge e, Graph& g) { - if (m_compare(get(m_weight, e), m_zero)) + // Comparison needs to be more complicated because distance and weight + // types may not be the same; see bug 8398 + // (https://svn.boost.org/trac/boost/ticket/8398) + D source_dist = get(m_distance, source(e, g)); + if (m_compare(m_combine(source_dist, get(m_weight, e)), source_dist)) boost::throw_exception(negative_edge()); m_vis.examine_edge(e, g); } From 4f3e758c9c086a4e972f9481ea07556f77f9ea0c Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Sun, 7 Apr 2013 19:37:29 +0000 Subject: [PATCH 271/333] Fixed example for C++11 mode [SVN r83798] --- example/astar-cities.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/example/astar-cities.cpp b/example/astar-cities.cpp index c594afa7d..c18cd41e8 100644 --- a/example/astar-cities.cpp +++ b/example/astar-cities.cpp @@ -171,7 +171,7 @@ int main(int argc, char **argv) // pick random start/goal - mt19937 gen(time(0)); + boost::mt19937 gen(time(0)); vertex start = random_vertex(g, gen); vertex goal = random_vertex(g, gen); From 3e770e171ec8da49f4a70f93b359f1feb74a1dd8 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Wed, 10 Apr 2013 17:03:21 +0000 Subject: [PATCH 272/333] Added patches from Flavio De Lorenzi; fixed HTML typo in VF2 documentation [SVN r83832] --- doc/vf2_sub_graph_iso.html | 2 +- include/boost/graph/vf2_sub_graph_iso.hpp | 5 ++++- test/vf2_sub_graph_iso_test.cpp | 5 ++++- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/doc/vf2_sub_graph_iso.html b/doc/vf2_sub_graph_iso.html index 69e0086bf..95ea9496b 100755 --- a/doc/vf2_sub_graph_iso.html +++ b/doc/vf2_sub_graph_iso.html @@ -87,7 +87,7 @@

    graph that preserves the edge structure of the graphs. M is said to be a graph-subgraph isomorphism if and only if M is an isomorphism between G1 and a subgraph of G2. - An induced subgraph of a graph G = (V, E) is a normal subgraph + An induced subgraph of a graph G = (V, E) is a normal subgraph G' = (V', E') with the extra condition that all edges of G which have both endpoints in V' are in E'.

    diff --git a/include/boost/graph/vf2_sub_graph_iso.hpp b/include/boost/graph/vf2_sub_graph_iso.hpp index fe3b43730..a316f7813 100755 --- a/include/boost/graph/vf2_sub_graph_iso.hpp +++ b/include/boost/graph/vf2_sub_graph_iso.hpp @@ -11,6 +11,9 @@ // http://www.boost.org/LICENSE_1_0.txt) //======================================================================= +// Revision History: +// 8 April 2013: Fixed a typo in vf2_print_callback. (Flavio De Lorenzi) + #ifndef BOOST_VF2_SUB_GRAPH_ISO_HPP #define BOOST_VF2_SUB_GRAPH_ISO_HPP @@ -55,7 +58,7 @@ namespace boost { // Print (sub)graph isomorphism map BGL_FORALL_VERTICES_T(v, graph1_, Graph1) std::cout << '(' << get(vertex_index_t(), graph1_, v) << ", " - << get(vertex_index_t(), graph1_, get(f, v)) << ") "; + << get(vertex_index_t(), graph2_, get(f, v)) << ") "; std::cout << std::endl; diff --git a/test/vf2_sub_graph_iso_test.cpp b/test/vf2_sub_graph_iso_test.cpp index 7ad653e83..21ef97ee1 100644 --- a/test/vf2_sub_graph_iso_test.cpp +++ b/test/vf2_sub_graph_iso_test.cpp @@ -9,6 +9,9 @@ // http://www.boost.org/LICENSE_1_0.txt) //======================================================================= +// Revision History: +// 8 April 2013: Fixed a typo in random_functor. (Flavio De Lorenzi) + #include #include #include @@ -36,7 +39,7 @@ struct random_functor { random_functor(Generator& g) : g(g) { } std::size_t operator()(std::size_t n) { boost::uniform_int distrib(0, n-1); - boost::variate_generator > + boost::variate_generator > x(g, distrib); return x(); } From f9dbc3ffb38a41e38e034df762d2c738d1fec3b9 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Wed, 10 Apr 2013 20:42:27 +0000 Subject: [PATCH 273/333] Removed unnecessary requirement; fixes #8427 [SVN r83837] --- doc/johnson_all_pairs_shortest.html | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/doc/johnson_all_pairs_shortest.html b/doc/johnson_all_pairs_shortest.html index 8e95b05a3..3e39cb00a 100644 --- a/doc/johnson_all_pairs_shortest.html +++ b/doc/johnson_all_pairs_shortest.html @@ -90,8 +90,7 @@

    Named Parameters

    The type WeightMap must be a model of Readable Property Map. The edge descriptor type of the graph needs to be usable as the key type for the weight - map. The value type for the map must be - Addable with the value type of the distance map.
    + map.
    Default: get(edge_weight, g) From 44912cc2be5998b320c1acd47f8af7dad8db48d6 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Thu, 11 Apr 2013 17:14:28 +0000 Subject: [PATCH 274/333] Fixed some typos; not a fix to #8428 yet [SVN r83844] --- doc/johnson_all_pairs_shortest.html | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/doc/johnson_all_pairs_shortest.html b/doc/johnson_all_pairs_shortest.html index 3e39cb00a..8e429146a 100644 --- a/doc/johnson_all_pairs_shortest.html +++ b/doc/johnson_all_pairs_shortest.html @@ -15,7 +15,7 @@
    -

    +

    johnson_all_pairs_shortest_paths

    @@ -75,8 +75,8 @@

    Parameters

    OUT: DistanceMatrix& D
    The length of the shortest path between each pair of vertices -u,v in the graph is stored in D[u][v]. The set of -types {DistanceMatrix, vertices_size_type, D} must be a model +u,v in the graph is stored in D[u][v]. The tuple of +types (DistanceMatrix, vertices_size_type, D) must be a model of BasicMatrix where D is the value type of the DistanceMap.
    @@ -86,7 +86,7 @@

    Named Parameters

    IN: weight_map(WeightMap w_map)
    - The weight or ``length'' of each edge in the graph. + The weight or "length" of each edge in the graph. The type WeightMap must be a model of Readable Property Map. The edge descriptor type of the graph needs to be usable as the key type for the weight @@ -127,7 +127,8 @@

    Named Parameters

    This function is use to compare distances to determine which vertex is closer to the source vertex. The CompareFunction type must be a model of - \stlconcept{BinaryPredicate} and have argument types that + Binary Predicate + and have argument types that match the value type of the WeightMap property map.
    Default: std::less<DT> with DT=typename property_traits<WeightMap>::value_type @@ -151,7 +152,7 @@

    Named Parameters

    This value is used to initialize the distance for each vertex before the start of the algorithm. - The type DT must be the value type of the WeigthMap.
    + The type DT must be the value type of the WeightMap.
    Default: std::numeric_limits::max()
    @@ -159,7 +160,7 @@

    Named Parameters

    This value is used to initialize the distance for the source vertex before the start of the algorithm. The type DT - must be the value type of the WeigthMap.
    + must be the value type of the WeightMap.
    Default: 0
    From 65c9ef22c6850ed489da321da23610b4822aa116 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Thu, 11 Apr 2013 17:19:38 +0000 Subject: [PATCH 275/333] Flipped arguments to combine calls to match documentation; refs #8428 [SVN r83845] --- include/boost/graph/johnson_all_pairs_shortest.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/boost/graph/johnson_all_pairs_shortest.hpp b/include/boost/graph/johnson_all_pairs_shortest.hpp index b8da0fe19..1e703791d 100644 --- a/include/boost/graph/johnson_all_pairs_shortest.hpp +++ b/include/boost/graph/johnson_all_pairs_shortest.hpp @@ -113,7 +113,7 @@ namespace boost { for (boost::tie(e, e_end) = edges(g2); e != e_end; ++e) { typename Traits2::vertex_descriptor a = source(*e, g2), b = target(*e, g2); - put(w_hat, *e, combine(get(w, *e), (get(h, a) - get(h, b)))); + put(w_hat, *e, combine((get(h, a) - get(h, b)), get(w, *e))); } for (boost::tie(u, u_end) = vertices(g2); u != u_end; ++u) { dijkstra_visitor<> dvis; @@ -121,7 +121,7 @@ namespace boost { (g2, *u, pred, d, w_hat, id2, compare, combine, inf, zero,dvis); for (boost::tie(v, v_end) = vertices(g2); v != v_end; ++v) { if (*u != s && *v != s) { - D[get(id2, *u)-1][get(id2, *v)-1] = combine(get(d, *v), (get(h, *v) - get(h, *u))); + D[get(id2, *u)-1][get(id2, *v)-1] = combine((get(h, *v) - get(h, *u)), get(d, *v)); } } } From 32fa162931ec8db14d7ea23be90ec3c9688fd084 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Fri, 12 Apr 2013 19:54:31 +0000 Subject: [PATCH 276/333] Fixed documentation to be correct; fixes #8428 [SVN r83857] --- doc/johnson_all_pairs_shortest.html | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/doc/johnson_all_pairs_shortest.html b/doc/johnson_all_pairs_shortest.html index 8e429146a..716bf5761 100644 --- a/doc/johnson_all_pairs_shortest.html +++ b/doc/johnson_all_pairs_shortest.html @@ -78,7 +78,9 @@

    Parameters

    u,v in the graph is stored in D[u][v]. The tuple of types (DistanceMatrix, vertices_size_type, D) must be a model of BasicMatrix where D is the -value type of the DistanceMap. +value type of the DistanceMap. There must be implicit conversions +between the value type of the distance matrix and the value type of the weight +map.
    @@ -90,7 +92,7 @@

    Named Parameters

    The type WeightMap must be a model of Readable Property Map. The edge descriptor type of the graph needs to be usable as the key type for the weight - map.
    + map. The value type of the weight map must support a subtraction operation.
    Default: get(edge_weight, g) @@ -111,7 +113,7 @@

    Named Parameters

    Default: get(vertex_index, g) Note: if you use this default, make sure your graph has an internal vertex_index property. For example, - adjacenty_list with VertexList=listS does + adjacency_list with VertexList=listS does not have an internal vertex_index property.
    @@ -139,11 +141,8 @@

    Named Parameters

    This function is used to combine distances to compute the distance of a path. The CombineFunction type must be a model of Binary - Function. The first argument type of the binary function must - match the value type of the DistanceMap property map and - the second argument type must match the value type of the - WeightMap property map. The result type must be the same - type as the distance value type.
    + Function. Both argument types and the return type of the binary function + must match the value type of the WeightMap property map. This operation is required to act as the sum operation for the weight type; in particular, it must be the inverse of the binary - operator on that type.
    Default: std::plus<DT> with DT=typename property_traits<WeightMap>::value_type From c40a5223627b5e497512e9c1f90f7a907b396aad Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Sat, 13 Apr 2013 18:20:16 +0000 Subject: [PATCH 277/333] Fixed 32/64-bit size issues; fixes #8434 [SVN r83877] --- include/boost/graph/sloan_ordering.hpp | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/include/boost/graph/sloan_ordering.hpp b/include/boost/graph/sloan_ordering.hpp index 781e9c9f4..88ad1b297 100644 --- a/include/boost/graph/sloan_ordering.hpp +++ b/include/boost/graph/sloan_ordering.hpp @@ -46,9 +46,9 @@ namespace boost { // ///////////////////////////////////////////////////////////////////////// template - unsigned RLS_depth(Distance& d) + typename Distance::value_type RLS_depth(Distance& d) { - unsigned h_s = 0; + typename Distance::value_type h_s = 0; typename Distance::iterator iter; for (iter = d.begin(); iter != d.end(); ++iter) @@ -70,14 +70,16 @@ namespace boost { // ///////////////////////////////////////////////////////////////////////// template - unsigned RLS_max_width(Distance& d, my_int depth) + typename Distance::value_type RLS_max_width(Distance& d, my_int depth) { + + typedef typename Distance::value_type Degree; //Searching for the maximum width of a level - std::vector dummy_width(depth+1, 0); - std::vector::iterator my_it; + std::vector dummy_width(depth+1, 0); + typename std::vector::iterator my_it; typename Distance::iterator iter; - unsigned w_max = 0; + Degree w_max = 0; for (iter = d.begin(); iter != d.end(); ++iter) { @@ -117,10 +119,10 @@ namespace boost { s = *(vertices(G).first); Vertex e = s; Vertex i; - unsigned my_degree = get(degree, s ); - unsigned dummy, h_i, h_s, w_i, w_e; + Degree my_degree = get(degree, s ); + Degree dummy, h_i, h_s, w_i, w_e; bool new_start = true; - unsigned maximum_degree = 0; + Degree maximum_degree = 0; //Creating a std-vector for storing the distance from the start vertex in dist std::vector::vertices_size_type> dist(num_vertices(G), 0); @@ -196,7 +198,7 @@ namespace boost { // step 5 // Initializing w - w_e = (std::numeric_limits::max)(); + w_e = (std::numeric_limits::max)(); //end 5 @@ -290,7 +292,7 @@ namespace boost { typename property_map::type index_map = get(vertex_index, g); //Sets the color and priority to their initial status - unsigned cdeg; + Degree cdeg; typename graph_traits::vertex_iterator ui, ui_end; for (boost::tie(ui, ui_end) = vertices(g); ui != ui_end; ++ui) { From 535e5938109265d1f7ca222a4c923e4c1c699c33 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Sat, 13 Apr 2013 18:20:45 +0000 Subject: [PATCH 278/333] Added sloan_ordering example to build list [SVN r83878] --- example/Jamfile.v2 | 1 + 1 file changed, 1 insertion(+) diff --git a/example/Jamfile.v2 b/example/Jamfile.v2 index 1785b8778..ce155c676 100644 --- a/example/Jamfile.v2 +++ b/example/Jamfile.v2 @@ -49,4 +49,5 @@ exe subgraph : subgraph.cpp ; exe subgraph_properties : subgraph_properties.cpp ; exe vf2_sub_graph_iso_example : vf2_sub_graph_iso_example.cpp ; exe vf2_sub_graph_iso_multi_example : vf2_sub_graph_iso_multi_example.cpp ; +exe sloan_ordering : sloan_ordering.cpp ; From 7e9b77f5fb49eb6063c828897a1c3d8f8a7c9726 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Sun, 14 Apr 2013 03:49:56 +0000 Subject: [PATCH 279/333] Fixed VC++ error [SVN r83893] --- test/mas_test.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/mas_test.cpp b/test/mas_test.cpp index 9fefdd228..3553d65fe 100644 --- a/test/mas_test.cpp +++ b/test/mas_test.cpp @@ -210,7 +210,7 @@ BOOST_AUTO_TEST_CASE(test1) std::map wm; weight_type i = 0; - BGL_FORALL_EDGES_T(e, g, undirected_unweighted_graph) { + BGL_FORALL_EDGES(e, g, undirected_unweighted_graph) { wm[e] = ws[i]; ++i; } From 53bdf1db9c54d1225d667c9a98dc7086a70736ee Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Thu, 18 Apr 2013 20:21:39 +0000 Subject: [PATCH 280/333] Applied patch from #7155 to add "graphml" as a value for "for"; fixes #7155; fixes #7016 [SVN r83961] --- src/graphml.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/graphml.cpp b/src/graphml.cpp index 30c58fe70..76ef0a292 100644 --- a/src/graphml.cpp +++ b/src/graphml.cpp @@ -71,6 +71,7 @@ class graphml_reader else if (for_ == "port") kind = port_key; else if (for_ == "endpoint") kind = endpoint_key; else if (for_ == "all") kind = all_key; + else if (for_ == "graphml") kind = graphml_key; else {BOOST_THROW_EXCEPTION(parse_error("Attribute for is not valid: " + for_));} m_keys[id] = kind; m_key_name[id] = name; @@ -132,7 +133,8 @@ class graphml_reader hyperedge_key, port_key, endpoint_key, - all_key + all_key, + graphml_key }; void From 67aacbe6efa1b4fe870b7633e9474d64bebe02fe Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Wed, 24 Apr 2013 02:19:13 +0000 Subject: [PATCH 281/333] Added support for distance types without numeric_limits specializations; changed test to use that functionality to ensure that it keeps working; fixes #8490 [SVN r84028] --- include/boost/graph/astar_search.hpp | 8 ++++---- include/boost/graph/named_function_params.hpp | 10 ++++++++++ test/astar_search_test.cpp | 19 ++++++++++++------- 3 files changed, 26 insertions(+), 11 deletions(-) diff --git a/include/boost/graph/astar_search.hpp b/include/boost/graph/astar_search.hpp index 7d6da7c3c..435ccf03b 100644 --- a/include/boost/graph/astar_search.hpp +++ b/include/boost/graph/astar_search.hpp @@ -438,7 +438,7 @@ namespace boost { typename detail::map_maker::map_type distance_map_type; typedef typename boost::property_traits::value_type D; - const D inf = arg_pack[_distance_inf | (std::numeric_limits::max)()]; + const D inf = arg_pack[_distance_inf || detail::get_max()]; astar_search (g, s, h, @@ -480,7 +480,7 @@ namespace boost { typename detail::map_maker::map_type distance_map_type; typedef typename boost::property_traits::value_type D; - const D inf = arg_pack[_distance_inf | (std::numeric_limits::max)()]; + const D inf = arg_pack[_distance_inf || detail::get_max()]; astar_search_tree (g, s, h, @@ -512,7 +512,7 @@ namespace boost { arg_pack_type, tag::weight_map, edge_weight_t, VertexListGraph>::type weight_map_type; typedef typename boost::property_traits::value_type D; - const D inf = arg_pack[_distance_inf | (std::numeric_limits::max)()]; + const D inf = arg_pack[_distance_inf || detail::get_max()]; astar_search_no_init (g, s, h, arg_pack[_visitor | make_astar_visitor(null_visitor())], @@ -545,7 +545,7 @@ namespace boost { arg_pack_type, tag::weight_map, edge_weight_t, VertexListGraph>::type weight_map_type; typedef typename boost::property_traits::value_type D; - const D inf = arg_pack[_distance_inf | (std::numeric_limits::max)()]; + const D inf = arg_pack[_distance_inf || detail::get_max()]; astar_search_no_init_tree (g, s, h, arg_pack[_visitor | make_astar_visitor(null_visitor())], diff --git a/include/boost/graph/named_function_params.hpp b/include/boost/graph/named_function_params.hpp index 3dd1a1367..4ab24f63c 100644 --- a/include/boost/graph/named_function_params.hpp +++ b/include/boost/graph/named_function_params.hpp @@ -12,6 +12,7 @@ #include #include +#include #include #include #include @@ -718,6 +719,15 @@ BOOST_BGL_DECLARE_NAMED_PARAMS result_type operator()() const {return get_default_starting_vertex(g);} }; + // Wrapper to avoid instantiating numeric_limits when users provide distance_inf value manually + template + struct get_max { + T operator()() const { + return (std::numeric_limits::max)(); + } + typedef T result_type; + }; + } // namespace detail } // namespace boost diff --git a/test/astar_search_test.cpp b/test/astar_search_test.cpp index b108bcb25..d72b91f0b 100644 --- a/test/astar_search_test.cpp +++ b/test/astar_search_test.cpp @@ -31,7 +31,12 @@ struct location { float y, x; // lat, long }; -typedef float cost; +struct my_float {float v; explicit my_float(float v = float()): v(v) {}}; +typedef my_float cost; +ostream& operator<<(ostream& o, my_float f) {return o << f.v;} +my_float operator+(my_float a, my_float b) {return my_float(a.v + b.v);} +bool operator==(my_float a, my_float b) {return a.v == b.v;} +bool operator<(my_float a, my_float b) {return a.v < b.v;} template class city_writer { @@ -80,9 +85,9 @@ class distance_heuristic : public astar_heuristic : m_location(l), m_goal(goal) {} CostType operator()(Vertex u) { - CostType dx = m_location[m_goal].x - m_location[u].x; - CostType dy = m_location[m_goal].y - m_location[u].y; - return ::sqrt(dx * dx + dy * dy); + float dx = m_location[m_goal].x - m_location[u].x; + float dy = m_location[m_goal].y - m_location[u].y; + return CostType(::sqrt(dx * dx + dy * dy)); } private: LocMap m_location; @@ -153,8 +158,8 @@ int main(int, char **) }; unsigned int num_edges = sizeof(edge_array) / sizeof(edge); cost weights[] = { // estimated travel time (mins) - 96, 134, 143, 65, 115, 133, 117, 116, 74, 56, - 84, 73, 69, 70, 116, 147, 173, 183, 74, 71, 124 + my_float(96), my_float(134), my_float(143), my_float(65), my_float(115), my_float(133), my_float(117), my_float(116), my_float(74), my_float(56), + my_float(84), my_float(73), my_float(69), my_float(70), my_float(116), my_float(147), my_float(173), my_float(183), my_float(74), my_float(71), my_float(124) }; @@ -187,7 +192,7 @@ int main(int, char **) distance_heuristic (locations, goal), predecessor_map(&p[0]).distance_map(&d[0]). - visitor(astar_goal_visitor(goal))); + visitor(astar_goal_visitor(goal)).distance_inf(my_float((std::numeric_limits::max)()))); } catch(found_goal fg) { // found a path to the goal From 2c62f35e46da2536196d05243591fabe93ec3285 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Wed, 1 May 2013 17:42:44 +0000 Subject: [PATCH 282/333] Added timeout support code from Brammert Ottens [SVN r84102] --- include/boost/graph/r_c_shortest_paths.hpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/include/boost/graph/r_c_shortest_paths.hpp b/include/boost/graph/r_c_shortest_paths.hpp index 834f82e9b..28755d872 100644 --- a/include/boost/graph/r_c_shortest_paths.hpp +++ b/include/boost/graph/r_c_shortest_paths.hpp @@ -222,7 +222,7 @@ void r_c_shortest_paths_dispatch std::vector vec_last_valid_index_for_dominance( num_vertices( g ), 0 ); std::vector b_vec_vertex_already_checked_for_dominance( num_vertices( g ), false ); - while( unprocessed_labels.size() ) + while( !unprocessed_labels.empty() && vis.on_enter_loop(unprocessed_labels, g) ) { Splabel cur_label = unprocessed_labels.top(); unprocessed_labels.pop(); @@ -458,6 +458,8 @@ struct default_r_c_shortest_paths_visitor void on_label_dominated( const Label&, const Graph& ) {} template void on_label_not_dominated( const Label&, const Graph& ) {} + template + bool on_enter_loop(const Queue& queue, const Graph& graph) {return true;} }; // default_r_c_shortest_paths_visitor From 966aa0cf481dd48eea9b2a076a33f70cb8f7ab24 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Mon, 20 May 2013 21:33:31 +0000 Subject: [PATCH 283/333] Fixed to work with self-loops [SVN r84396] --- .../boost/graph/max_cardinality_matching.hpp | 29 +++++++++++++++---- 1 file changed, 23 insertions(+), 6 deletions(-) diff --git a/include/boost/graph/max_cardinality_matching.hpp b/include/boost/graph/max_cardinality_matching.hpp index 5516bebc4..1549345a2 100644 --- a/include/boost/graph/max_cardinality_matching.hpp +++ b/include/boost/graph/max_cardinality_matching.hpp @@ -219,7 +219,12 @@ namespace boost vertex_state[u] = graph::detail::V_EVEN; out_edge_iterator_t ei, ei_end; for(boost::tie(ei,ei_end) = out_edges(u,g); ei != ei_end; ++ei) - even_edges.push_back( *ei ); + { + if (target(*ei,g) != u) + { + even_edges.push_back( *ei ); + } + } } else vertex_state[u] = graph::detail::V_UNREACHED; @@ -258,10 +263,16 @@ namespace boost if (vertex_state[w_prime] == graph::detail::V_UNREACHED) { vertex_state[w_prime] = graph::detail::V_ODD; - vertex_state[mate[w_prime]] = graph::detail::V_EVEN; + vertex_descriptor_t w_prime_mate = mate[w_prime]; + vertex_state[w_prime_mate] = graph::detail::V_EVEN; out_edge_iterator_t ei, ei_end; - for( boost::tie(ei,ei_end) = out_edges(mate[w_prime], g); ei != ei_end; ++ei) - even_edges.push_back(*ei); + for( boost::tie(ei,ei_end) = out_edges(w_prime_mate, g); ei != ei_end; ++ei) + { + if (target(*ei,g) != w_prime_mate) + { + even_edges.push_back(*ei); + } + } pred[w_prime] = v; } @@ -403,7 +414,12 @@ namespace boost bridge[v] = the_bridge; out_edge_iterator_t oei, oei_end; for(boost::tie(oei, oei_end) = out_edges(v,g); oei != oei_end; ++oei) - even_edges.push_back(*oei); + { + if (target(*oei,g) != v) + { + even_edges.push_back(*oei); + } + } } } } @@ -529,7 +545,7 @@ namespace boost vertex_descriptor_t u = source(e,g); vertex_descriptor_t v = target(e,g); - if (get(mate,u) == get(mate,v)) + if (u != v && get(mate,u) == get(mate,v)) //only way equality can hold is if // mate[u] == mate[v] == null_vertex { @@ -606,6 +622,7 @@ namespace boost edge_descriptor_t e = *ei; vertex_descriptor_t u = source(e,g); vertex_descriptor_t v = target(e,g); + if (u == v) continue; edge_list.push_back(std::make_pair(u,v)); edge_list.push_back(std::make_pair(v,u)); } From 1311d1b035908168ddc31529ff1295132ae790cb Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Fri, 24 May 2013 21:19:21 +0000 Subject: [PATCH 284/333] Chaned project1st and project2nd function objects to return copies rather than references to arguments, preventing a dangling reference when the type of the argument passed in is not exactly the same as the template argument of the projection function object [SVN r84466] --- include/boost/graph/detail/histogram_sort.hpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/include/boost/graph/detail/histogram_sort.hpp b/include/boost/graph/detail/histogram_sort.hpp index 54d4449e1..fb7073fd2 100644 --- a/include/boost/graph/detail/histogram_sort.hpp +++ b/include/boost/graph/detail/histogram_sort.hpp @@ -274,16 +274,21 @@ void split_into_separate_coords_filtered } } +// The versions of operator()() here can't return by reference because the +// actual type passed in may not match Pair, in which case the reference +// parameter is bound to a temporary that could end up dangling after the +// operator returns. + template struct project1st { typedef typename Pair::first_type result_type; - const result_type& operator()(const Pair& p) const {return p.first;} + result_type operator()(const Pair& p) const {return p.first;} }; template struct project2nd { typedef typename Pair::second_type result_type; - const result_type& operator()(const Pair& p) const {return p.second;} + result_type operator()(const Pair& p) const {return p.second;} }; } From b98f225d0d687360dac1245d2cd96d74518b94dd Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Sat, 25 May 2013 02:20:09 +0000 Subject: [PATCH 285/333] Removed unused typedefs [SVN r84471] --- include/boost/graph/compressed_sparse_row_graph.hpp | 6 ------ include/boost/graph/detail/adjacency_list.hpp | 4 ---- .../graph/detail/compressed_sparse_row_struct.hpp | 4 ---- include/boost/graph/detail/histogram_sort.hpp | 11 +++-------- src/read_graphviz_new.cpp | 1 - 5 files changed, 3 insertions(+), 23 deletions(-) diff --git a/include/boost/graph/compressed_sparse_row_graph.hpp b/include/boost/graph/compressed_sparse_row_graph.hpp index 33c267254..de3234a04 100644 --- a/include/boost/graph/compressed_sparse_row_graph.hpp +++ b/include/boost/graph/compressed_sparse_row_graph.hpp @@ -642,8 +642,6 @@ class compressed_sparse_row_graph::vertex_descriptor vertex_t; - typedef typename boost::graph_traits::vertices_size_type vertex_num; - typedef typename boost::graph_traits::edges_size_type edge_num; typedef std::vector > edge_vector_t; edge_vector_t new_edges(first, last); if (new_edges.empty()) return; @@ -666,8 +664,6 @@ class compressed_sparse_row_graph::vertex_descriptor vertex_t; - typedef typename boost::graph_traits::vertices_size_type vertex_num; - typedef typename boost::graph_traits::edges_size_type edge_num; typedef std::pair vertex_pair; typedef std::vector< boost::tuple in_edges(Vertex v, const BOOST_BIDIR_CSR_GRAPH_TYPE& g) { - typedef typename BOOST_BIDIR_CSR_GRAPH_TYPE::edge_descriptor ed; typedef typename BOOST_BIDIR_CSR_GRAPH_TYPE::in_edge_iterator it; EdgeIndex v_row_start = g.m_backward.m_rowstart[v]; EdgeIndex next_row_start = g.m_backward.m_rowstart[v + 1]; @@ -1368,7 +1363,6 @@ put(Tag tag, typename property_map::key_type k, typename lookup_one_property::plist_type, Tag>::type val) { typedef typename property_map::all_tag all_tag; - typedef typename property_map::type outer_pm; lookup_one_property::plist_type, Tag>::lookup(get(all_tag(), g, k), tag) = val; } diff --git a/include/boost/graph/detail/adjacency_list.hpp b/include/boost/graph/detail/adjacency_list.hpp index f6d794817..dd27ecd4a 100644 --- a/include/boost/graph/detail/adjacency_list.hpp +++ b/include/boost/graph/detail/adjacency_list.hpp @@ -635,7 +635,6 @@ namespace boost { directed_graph_helper& g_) { typedef typename Config::graph_type graph_type; - typedef typename Config::edge_parallel_category Cat; graph_type& g = static_cast(g_); g.out_edge_list(u).clear(); // clear() should be a req of Sequence and AssociativeContainer, @@ -782,7 +781,6 @@ namespace boost { typedef typename Graph::global_edgelist_selector EdgeListS; BOOST_STATIC_ASSERT((!is_same::value)); - typedef typename EdgeList::value_type StoredEdge; typename EdgeList::iterator i = el.begin(), end = el.end(); for (; i != end; ++i) { if ((*i).get_target() == v) { @@ -987,7 +985,6 @@ namespace boost { BOOST_STATIC_ASSERT((!is_same::value)); typedef typename Config::graph_type graph_type; - typedef typename Config::edge_parallel_category Cat; graph_type& g = static_cast(g_); while (true) { typename Config::out_edge_iterator ei, ei_end; @@ -1589,7 +1586,6 @@ namespace boost { typedef typename Config::graph_type Graph; typedef typename Config::StoredEdge StoredEdge; const Graph& cg = static_cast(g_); - typedef typename Config::out_edge_iterator out_edge_iterator; const typename Config::OutEdgeList& el = cg.out_edge_list(u); typename Config::OutEdgeList::const_iterator it = graph_detail:: find(el, StoredEdge(v)); diff --git a/include/boost/graph/detail/compressed_sparse_row_struct.hpp b/include/boost/graph/detail/compressed_sparse_row_struct.hpp index 56495f343..6e7b60d74 100644 --- a/include/boost/graph/detail/compressed_sparse_row_struct.hpp +++ b/include/boost/graph/detail/compressed_sparse_row_struct.hpp @@ -218,8 +218,6 @@ namespace detail { // the user has supplied the number of edges. edges_size_type numedges = numedges_or_zero; if (numedges == 0) { - typedef typename std::iterator_traits::iterator_category - category; numedges = boost::graph::detail::reserve_count_for_single_pass(edge_begin, edge_end); } m_column.clear(); @@ -313,7 +311,6 @@ namespace detail { inherited_edge_properties::resize(numedges); EdgeIndex current_edge = 0; typedef typename boost::graph_traits::vertex_descriptor g_vertex; - typedef typename boost::graph_traits::edge_descriptor g_edge; typedef typename boost::graph_traits::out_edge_iterator g_out_edge_iter; @@ -347,7 +344,6 @@ namespace detail { // Flip sequence BidirectionalIterator first(last_sorted); BidirectionalIterator last(first_sorted); - typedef Vertex vertex_t; typedef Vertex vertex_num; typedef EdgeIndex edge_num; edge_num new_edge_count = std::distance(first, last); diff --git a/include/boost/graph/detail/histogram_sort.hpp b/include/boost/graph/detail/histogram_sort.hpp index fb7073fd2..ef0363563 100644 --- a/include/boost/graph/detail/histogram_sort.hpp +++ b/include/boost/graph/detail/histogram_sort.hpp @@ -54,7 +54,6 @@ count_starts KeyFilter key_filter, KeyTransform key_transform) { - typedef VerticesSize vertices_size_type; typedef typename std::iterator_traits::value_type EdgeIndex; // Put the degree of each vertex v into m_rowstart[v + 1] @@ -69,7 +68,7 @@ count_starts // m_rowstart EdgeIndex start_of_this_row = 0; starts[0] = start_of_this_row; - for (vertices_size_type i = 1; i < numkeys + 1; ++i) { + for (VerticesSize i = 1; i < numkeys + 1; ++i) { start_of_this_row += starts[i]; starts[i] = start_of_this_row; } @@ -88,7 +87,6 @@ histogram_sort(KeyIterator key_begin, KeyIterator key_end, KeyFilter key_filter, KeyTransform key_transform) { - typedef NumKeys vertices_size_type; typedef typename std::iterator_traits::value_type EdgeIndex; // Histogram sort the edges by their source vertices, putting the targets @@ -99,7 +97,7 @@ histogram_sort(KeyIterator key_begin, KeyIterator key_end, Value1InputIter v1i = values1_begin; for (KeyIterator i = key_begin; i != key_end; ++i, ++v1i) { if (key_filter(*i)) { - vertices_size_type source = key_transform(*i); + NumKeys source = key_transform(*i); BOOST_ASSERT (source < numkeys); EdgeIndex insert_pos = current_insert_positions[source]; ++current_insert_positions[source]; @@ -126,7 +124,6 @@ histogram_sort(KeyIterator key_begin, KeyIterator key_end, KeyFilter key_filter, KeyTransform key_transform) { - typedef NumKeys vertices_size_type; typedef typename std::iterator_traits::value_type EdgeIndex; // Histogram sort the edges by their source vertices, putting the targets @@ -138,7 +135,7 @@ histogram_sort(KeyIterator key_begin, KeyIterator key_end, Value2InputIter v2i = values2_begin; for (KeyIterator i = key_begin; i != key_end; ++i, ++v1i, ++v2i) { if (key_filter(*i)) { - vertices_size_type source = key_transform(*i); + NumKeys source = key_transform(*i); BOOST_ASSERT (source < numkeys); EdgeIndex insert_pos = current_insert_positions[source]; ++current_insert_positions[source]; @@ -159,7 +156,6 @@ histogram_sort_inplace(KeyIterator key_begin, Value1Iter values1, KeyTransform key_transform) { - typedef NumKeys vertices_size_type; typedef typename std::iterator_traits::value_type EdgeIndex; // 1. Copy m_rowstart (except last element) to get insert positions @@ -194,7 +190,6 @@ histogram_sort_inplace(KeyIterator key_begin, Value2Iter values2, KeyTransform key_transform) { - typedef NumKeys vertices_size_type; typedef typename std::iterator_traits::value_type EdgeIndex; // 1. Copy m_rowstart (except last element) to get insert positions diff --git a/src/read_graphviz_new.cpp b/src/read_graphviz_new.cpp index 6c6608c7b..eadfa21ea 100644 --- a/src/read_graphviz_new.cpp +++ b/src/read_graphviz_new.cpp @@ -762,7 +762,6 @@ namespace read_graphviz_detail { } void translate_results_to_graph(const parser_result& r, ::boost::detail::graph::mutate_graph* mg) { - typedef boost::detail::graph::node_t vertex; typedef boost::detail::graph::edge_t edge; for (std::map::const_iterator i = r.nodes.begin(); i != r.nodes.end(); ++i) { // std::cerr << i->first << " " << props_to_string(i->second) << std::endl; From bf00bbe4f0c1cfe98567a1010bdd1dc200a60099 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Tue, 4 Jun 2013 16:07:20 +0000 Subject: [PATCH 286/333] Fixed dangling reference bug reported by Marshall Clow; other small cleanups [SVN r84632] --- include/boost/graph/stoer_wagner_min_cut.hpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/include/boost/graph/stoer_wagner_min_cut.hpp b/include/boost/graph/stoer_wagner_min_cut.hpp index c868c0c83..a777f0311 100644 --- a/include/boost/graph/stoer_wagner_min_cut.hpp +++ b/include/boost/graph/stoer_wagner_min_cut.hpp @@ -36,7 +36,7 @@ namespace boost { mas_min_cut_visitor(const Graph& g, ParityMap parity, weight_type& cutweight, - WeightMap weight_map, + const WeightMap& weight_map, IndexMap index_map) : m_bestParity(parity), m_parity(make_one_bit_color_map(num_vertices(g), index_map)), @@ -140,7 +140,7 @@ namespace boost { weight_type bestW = (std::numeric_limits::max)(); weight_type bestThisTime = (std::numeric_limits::max)(); - vertex_descriptor bestStart; + vertex_descriptor bestStart = boost::graph_traits::null_vertex(); detail::mas_min_cut_visitor vis(g, parities, bestThisTime, weights, index_map); @@ -213,7 +213,7 @@ namespace graph { typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; typedef typename boost::property_traits::value_type weight_type; - typedef typename boost::detail::make_priority_queue_from_arg_pack_gen > gen_type; + typedef boost::detail::make_priority_queue_from_arg_pack_gen > gen_type; gen_type gen(choose_param(get_param(arg_pack, boost::distance_zero_t()), weight_type(0))); From df1a183214da940c0ef0212424c19c20316b16fd Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Tue, 4 Jun 2013 16:07:45 +0000 Subject: [PATCH 287/333] Added reference in parameter type [SVN r84633] --- include/boost/graph/maximum_adjacency_search.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/boost/graph/maximum_adjacency_search.hpp b/include/boost/graph/maximum_adjacency_search.hpp index a87c90de5..58dc8695e 100644 --- a/include/boost/graph/maximum_adjacency_search.hpp +++ b/include/boost/graph/maximum_adjacency_search.hpp @@ -304,7 +304,7 @@ maximum_adjacency_search(const Graph& g, WeightMap weights, MASVisitor vis, cons template void - operator() (const Graph& g, const ArgPack arg_pack) const { + operator() (const Graph& g, const ArgPack& arg_pack) const { // call the function that does the dispatching typedef typename get_param_type::type W; graph::detail::mas_dispatch::apply(g, arg_pack, get_param(arg_pack, edge_weight)); From 61296c352ac75c0fa47acd2589c61b79cc405984 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Mon, 10 Jun 2013 14:29:39 +0000 Subject: [PATCH 288/333] Changed // comments to be non-greedy; fixes #8681 [SVN r84725] --- src/read_graphviz_new.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/read_graphviz_new.cpp b/src/read_graphviz_new.cpp index eadfa21ea..02dee38e1 100644 --- a/src/read_graphviz_new.cpp +++ b/src/read_graphviz_new.cpp @@ -144,7 +144,7 @@ namespace read_graphviz_detail { { std::string end_of_token = "(?=(?:\\W))"; std::string whitespace = "(?:\\s+)"; - std::string slash_slash_comment = "(?://.*$)"; + std::string slash_slash_comment = "(?://.*?$)"; std::string slash_star_comment = "(?:/\\*.*?\\*/)"; std::string hash_comment = "(?:^#.*?$)"; std::string backslash_newline = "(?:[\\\\][\\n])"; From ca70cdaa2c96f97215c7faf52992e91db4c9cef3 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Fri, 21 Jun 2013 20:06:45 +0000 Subject: [PATCH 289/333] Removed assertion to enable removal of non-existent edges, as suggested by comment to #4622; refs #4622 [SVN r84869] --- include/boost/graph/detail/adjacency_list.hpp | 1 - 1 file changed, 1 deletion(-) diff --git a/include/boost/graph/detail/adjacency_list.hpp b/include/boost/graph/detail/adjacency_list.hpp index dd27ecd4a..a99ec265c 100644 --- a/include/boost/graph/detail/adjacency_list.hpp +++ b/include/boost/graph/detail/adjacency_list.hpp @@ -806,7 +806,6 @@ namespace boost { typedef typename EdgeList::value_type StoredEdge; typename EdgeList::iterator i = el.find(StoredEdge(v)), end = el.end(); - BOOST_ASSERT ((i != end)); if (i != end) { g.m_edges.erase((*i).get_iter()); el.erase(i); From 37bd77709459a2f6b45998296999d939312e438d Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Fri, 28 Jun 2013 18:47:10 +0000 Subject: [PATCH 290/333] Moved distributed graph tags into graph_traits.hpp [SVN r84912] --- include/boost/graph/graph_traits.hpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/include/boost/graph/graph_traits.hpp b/include/boost/graph/graph_traits.hpp index ceb0c2ac5..38a791fcf 100644 --- a/include/boost/graph/graph_traits.hpp +++ b/include/boost/graph/graph_traits.hpp @@ -166,7 +166,12 @@ namespace boost { struct edge_list_graph_tag { }; struct adjacency_matrix_tag { }; - /** @name Taversal Category Traits + // Parallel traversal_category tags + struct distributed_graph_tag { }; + struct distributed_vertex_list_graph_tag { }; + struct distributed_edge_list_graph_tag { }; + + /** @name Traversal Category Traits * These traits classify graph types by their supported methods of * vertex and edge traversal. */ From d53729083ffea6ce568c82ae738367f51a1eddee Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Fri, 28 Jun 2013 18:47:30 +0000 Subject: [PATCH 291/333] Changed dispatching strategy for bfs_helper [SVN r84913] --- include/boost/graph/breadth_first_search.hpp | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/include/boost/graph/breadth_first_search.hpp b/include/boost/graph/breadth_first_search.hpp index 18bc24f5c..f50172e35 100644 --- a/include/boost/graph/breadth_first_search.hpp +++ b/include/boost/graph/breadth_first_search.hpp @@ -248,8 +248,7 @@ namespace boost { ColorMap color, BFSVisitor vis, const bgl_named_params& params, - BOOST_GRAPH_ENABLE_IF_MODELS(VertexListGraph, vertex_list_graph_tag, - void)* = 0) + boost::mpl::false_) { typedef graph_traits Traits; // Buffer default @@ -271,8 +270,7 @@ namespace boost { ColorMap color, BFSVisitor vis, const bgl_named_params& params, - BOOST_GRAPH_ENABLE_IF_MODELS(DistributedGraph, distributed_graph_tag, - void)* = 0); + boost::mpl::true_); #endif // BOOST_GRAPH_USE_MPI //------------------------------------------------------------------------- @@ -293,7 +291,11 @@ namespace boost { (g, s, color, choose_param(get_param(params, graph_visitor), make_bfs_visitor(null_visitor())), - params); + params, + boost::mpl::bool_< + boost::is_base_and_derived< + distributed_graph_tag, + typename graph_traits::traversal_category>::value>()); } }; @@ -316,7 +318,11 @@ namespace boost { g, vertex_index)), choose_param(get_param(params, graph_visitor), make_bfs_visitor(null_vis)), - params); + params, + boost::mpl::bool_< + boost::is_base_and_derived< + distributed_graph_tag, + typename graph_traits::traversal_category>::value>()); } }; From 73d2d7500e3fe75fe8bbebe0ef0e40de8a0a95b6 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Sat, 29 Jun 2013 19:12:52 +0000 Subject: [PATCH 292/333] Added #define to detect recent modification [SVN r84915] --- include/boost/graph/graph_traits.hpp | 1 + 1 file changed, 1 insertion(+) diff --git a/include/boost/graph/graph_traits.hpp b/include/boost/graph/graph_traits.hpp index 38a791fcf..a1c27483a 100644 --- a/include/boost/graph/graph_traits.hpp +++ b/include/boost/graph/graph_traits.hpp @@ -170,6 +170,7 @@ namespace boost { struct distributed_graph_tag { }; struct distributed_vertex_list_graph_tag { }; struct distributed_edge_list_graph_tag { }; +#define BOOST_GRAPH_SEQUENTIAL_TRAITS_DEFINES_DISTRIBUTED_TAGS // Disable these from external versions of PBGL /** @name Traversal Category Traits * These traits classify graph types by their supported methods of From a5a29bd065196735d305dffecfaf8d9b79132e9f Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Sun, 7 Jul 2013 16:50:24 +0000 Subject: [PATCH 293/333] Changed to use adjacency_list for temporary graph, avoiding ADL issues with vector_as_graph; fixes #8791 [SVN r84976] --- include/boost/graph/transitive_closure.hpp | 56 ++++++++++++---------- 1 file changed, 31 insertions(+), 25 deletions(-) diff --git a/include/boost/graph/transitive_closure.hpp b/include/boost/graph/transitive_closure.hpp index 5ba0cab7f..d40f90e4f 100644 --- a/include/boost/graph/transitive_closure.hpp +++ b/include/boost/graph/transitive_closure.hpp @@ -14,11 +14,11 @@ #include #include #include -#include #include #include #include #include +#include #include namespace boost @@ -95,7 +95,7 @@ namespace boost std::vector < std::vector < vertex > >components; build_component_lists(g, num_scc, component_number, components); - typedef std::vector > CG_t; + typedef boost::adjacency_list CG_t; CG_t CG(num_scc); for (cg_vertex s = 0; s < components.size(); ++s) { std::vector < cg_vertex > adj; @@ -113,7 +113,10 @@ namespace boost std::unique(adj.begin(), adj.end()); if (di != adj.end()) adj.erase(di, adj.end()); - CG[s] = adj; + for (typename std::vector::const_iterator i = adj.begin(); + i != adj.end(); ++i) { + add_edge(s, *i, CG); + } } std::vector topo_order; @@ -126,15 +129,20 @@ namespace boost iter != topo_order.end(); ++iter) topo_number[*iter] = n++; - for (size_type i = 0; i < num_vertices(CG); ++i) - std::sort(CG[i].begin(), CG[i].end(), + std::vector > CG_vec(num_vertices(CG)); + for (size_type i = 0; i < num_vertices(CG); ++i) { + typedef typename boost::graph_traits::adjacency_iterator cg_adj_iter; + std::pair pr = adjacent_vertices(i, CG); + CG_vec[i].assign(pr.first, pr.second); + std::sort(CG_vec[i].begin(), CG_vec[i].end(), boost::bind(std::less(), boost::bind(detail::subscript(topo_number), _1), boost::bind(detail::subscript(topo_number), _2))); + } std::vector > chains; { - std::vector in_a_chain(num_vertices(CG)); + std::vector in_a_chain(CG_vec.size()); for (typename std::vector::iterator i = topo_order.begin(); i != topo_order.end(); ++i) { cg_vertex v = *i; @@ -144,12 +152,10 @@ namespace boost for (;;) { chain.push_back(v); in_a_chain[v] = true; - typename graph_traits::adjacency_iterator adj_first, adj_last; - boost::tie(adj_first, adj_last) = adjacent_vertices(v, CG); - typename graph_traits::adjacency_iterator next - = std::find_if(adj_first, adj_last, + typename std::vector::const_iterator next + = std::find_if(CG_vec[v].begin(), CG_vec[v].end(), std::not1(detail::subscript(in_a_chain))); - if (next != adj_last) + if (next != CG_vec[v].end()) v = *next; else break; // end of chain, dead-end @@ -158,8 +164,8 @@ namespace boost } } } - std::vector chain_number(num_vertices(CG)); - std::vector pos_in_chain(num_vertices(CG)); + std::vector chain_number(CG_vec.size()); + std::vector pos_in_chain(CG_vec.size()); for (size_type i = 0; i < chains.size(); ++i) for (size_type j = 0; j < chains[i].size(); ++j) { cg_vertex v = chains[i][j]; @@ -168,14 +174,14 @@ namespace boost } cg_vertex inf = (std::numeric_limits< cg_vertex >::max)(); - std::vector > successors(num_vertices(CG), + std::vector > successors(CG_vec.size(), std::vector (chains.size(), inf)); for (typename std::vector::reverse_iterator i = topo_order.rbegin(); i != topo_order.rend(); ++i) { cg_vertex u = *i; - typename graph_traits::adjacency_iterator adj, adj_last; - for (boost::tie(adj, adj_last) = adjacent_vertices(u, CG); + typename std::vector::const_iterator adj, adj_last; + for (adj = CG_vec[u].begin(), adj_last = CG_vec[u].end(); adj != adj_last; ++adj) { cg_vertex v = *adj; if (topo_number[v] < successors[u][chain_number[v]]) { @@ -188,15 +194,15 @@ namespace boost } } - for (size_type i = 0; i < CG.size(); ++i) - CG[i].clear(); - for (size_type i = 0; i < CG.size(); ++i) + for (size_type i = 0; i < CG_vec.size(); ++i) + CG_vec[i].clear(); + for (size_type i = 0; i < CG_vec.size(); ++i) for (size_type j = 0; j < chains.size(); ++j) { size_type topo_num = successors[i][j]; if (topo_num < inf) { cg_vertex v = topo_order[topo_num]; for (size_type k = pos_in_chain[v]; k < chains[j].size(); ++k) - CG[i].push_back(chains[j][k]); + CG_vec[i].push_back(chains[j][k]); } } @@ -209,11 +215,11 @@ namespace boost g_to_tc_map[*i] = add_vertex(tc); } // Add edges between all the vertices in two adjacent SCCs - typename graph_traits::vertex_iterator si, si_end; - for (boost::tie(si, si_end) = vertices(CG); si != si_end; ++si) { - cg_vertex s = *si; - typename graph_traits::adjacency_iterator i, i_end; - for (boost::tie(i, i_end) = adjacent_vertices(s, CG); i != i_end; ++i) { + typename std::vector >::const_iterator si, si_end; + for (si = CG_vec.begin(), si_end = CG_vec.end(); si != si_end; ++si) { + cg_vertex s = si - CG_vec.begin(); + typename std::vector::const_iterator i, i_end; + for (i = CG_vec[s].begin(), i_end = CG_vec[s].end(); i != i_end; ++i) { cg_vertex t = *i; for (size_type k = 0; k < components[s].size(); ++k) for (size_type l = 0; l < components[t].size(); ++l) From be2fc043d15116c9bacf230c7acf90fc93341eb5 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Mon, 12 Aug 2013 18:14:58 +0000 Subject: [PATCH 294/333] Fixed unused typedef warnings from GCC 4.9; fixes #8877; fixes #8986 [SVN r85323] --- example/astar-cities.cpp | 1 - example/bfs-example.cpp | 1 - example/bfs-example2.cpp | 1 - example/dfs-example.cpp | 1 - example/dijkstra-example-listS.cpp | 1 - example/dijkstra-example.cpp | 1 - example/dijkstra-no-color-map-example.cpp | 1 - example/mcgregor_subgraphs_example.cpp | 4 ---- example/stoer_wagner.cpp | 1 - example/subgraph.cpp | 1 - .../boost/graph/bellman_ford_shortest_paths.hpp | 2 -- include/boost/graph/betweenness_centrality.hpp | 3 --- include/boost/graph/bipartite.hpp | 1 - include/boost/graph/breadth_first_search.hpp | 1 - include/boost/graph/chrobak_payne_drawing.hpp | 1 - include/boost/graph/closeness_centrality.hpp | 2 -- include/boost/graph/connected_components.hpp | 2 +- include/boost/graph/core_numbers.hpp | 1 - include/boost/graph/cuthill_mckee_ordering.hpp | 3 --- .../dijkstra_shortest_paths_no_color_map.hpp | 2 -- include/boost/graph/edmonds_karp_max_flow.hpp | 1 - include/boost/graph/fruchterman_reingold.hpp | 1 - include/boost/graph/graph_utility.hpp | 4 ---- include/boost/graph/gursoy_atun_layout.hpp | 4 +--- include/boost/graph/is_straight_line_drawing.hpp | 3 --- include/boost/graph/king_ordering.hpp | 5 ----- .../boost/graph/kruskal_min_spanning_tree.hpp | 1 - include/boost/graph/maximum_adjacency_search.hpp | 4 +--- .../boost/graph/mcgregor_common_subgraphs.hpp | 1 - include/boost/graph/metric_tsp_approx.hpp | 1 - .../boost/graph/planar_canonical_ordering.hpp | 2 -- include/boost/graph/random.hpp | 2 -- include/boost/graph/random_spanning_tree.hpp | 1 - include/boost/graph/read_dimacs.hpp | 1 - include/boost/graph/stoer_wagner_min_cut.hpp | 8 ++------ include/boost/graph/tiernan_all_cycles.hpp | 1 - include/boost/graph/transitive_closure.hpp | 4 ---- .../graph/two_graphs_common_spanning_trees.hpp | 7 ------- include/boost/graph/vf2_sub_graph_iso.hpp | 4 ---- include/boost/graph/write_dimacs.hpp | 4 ---- test/adj_list_loops.cpp | 4 ---- test/all_planar_input_files_test.cpp | 2 -- test/astar_search_test.cpp | 1 - test/closeness_centrality.cpp | 2 -- test/clustering_coefficient.cpp | 4 +--- test/cycle_ratio_tests.cpp | 1 - test/degree_centrality.cpp | 2 -- test/dijkstra_no_color_map_compare.cpp | 3 --- test/eccentricity.cpp | 2 -- test/graphviz_test.cpp | 3 --- test/index_graph.cpp | 1 - test/layout_test.cpp | 2 -- test/matching_test.cpp | 1 - test/mcgregor_subgraphs_test.cpp | 7 ------- test/mean_geodesic.cpp | 2 -- test/metric_tsp_approx.cpp | 2 -- test/parallel_edges_loops_test.cpp | 2 -- test/property_iter.cpp | 10 ---------- test/sequential_vertex_coloring.cpp | 1 - test/stoer_wagner_test.cpp | 16 ---------------- test/subgraph.cpp | 1 - test/test_properties.hpp | 3 --- test/tiernan_all_cycles.cpp | 2 -- 63 files changed, 6 insertions(+), 158 deletions(-) diff --git a/example/astar-cities.cpp b/example/astar-cities.cpp index c18cd41e8..a6c1eead5 100644 --- a/example/astar-cities.cpp +++ b/example/astar-cities.cpp @@ -118,7 +118,6 @@ int main(int argc, char **argv) typedef property_map::type WeightMap; typedef mygraph_t::vertex_descriptor vertex; typedef mygraph_t::edge_descriptor edge_descriptor; - typedef mygraph_t::vertex_iterator vertex_iterator; typedef std::pair edge; // specify data diff --git a/example/bfs-example.cpp b/example/bfs-example.cpp index 0f340ccf2..9ca03124d 100644 --- a/example/bfs-example.cpp +++ b/example/bfs-example.cpp @@ -54,7 +54,6 @@ main() #endif // Typedefs - typedef graph_traits < graph_t >::vertex_descriptor Vertex; typedef graph_traits < graph_t >::vertices_size_type Size; typedef Size* Iiter; diff --git a/example/bfs-example2.cpp b/example/bfs-example2.cpp index d7cb2dd23..7e6acc2b7 100644 --- a/example/bfs-example2.cpp +++ b/example/bfs-example2.cpp @@ -63,7 +63,6 @@ main() #endif // Typedefs - typedef graph_traits::vertex_descriptor Vertex; typedef graph_traits::vertices_size_type Size; typedef Size* Iiter; diff --git a/example/dfs-example.cpp b/example/dfs-example.cpp index efb2b57e5..dc7b3f777 100644 --- a/example/dfs-example.cpp +++ b/example/dfs-example.cpp @@ -59,7 +59,6 @@ main() #endif // Typedefs - typedef boost::graph_traits < graph_t >::vertex_descriptor Vertex; typedef size_type* Iiter; // discover time and finish time properties diff --git a/example/dijkstra-example-listS.cpp b/example/dijkstra-example-listS.cpp index d02e93478..500f9811b 100644 --- a/example/dijkstra-example-listS.cpp +++ b/example/dijkstra-example-listS.cpp @@ -26,7 +26,6 @@ main(int, char *[]) property > > >, property > graph_t; - typedef graph_traits::edge_descriptor edge_descriptor; typedef std::pair Edge; const int num_nodes = 5; diff --git a/example/dijkstra-example.cpp b/example/dijkstra-example.cpp index 5f1ef4bd1..269d2570c 100644 --- a/example/dijkstra-example.cpp +++ b/example/dijkstra-example.cpp @@ -22,7 +22,6 @@ main(int, char *[]) typedef adjacency_list < listS, vecS, directedS, no_property, property < edge_weight_t, int > > graph_t; typedef graph_traits < graph_t >::vertex_descriptor vertex_descriptor; - typedef graph_traits < graph_t >::edge_descriptor edge_descriptor; typedef std::pair Edge; const int num_nodes = 5; diff --git a/example/dijkstra-no-color-map-example.cpp b/example/dijkstra-no-color-map-example.cpp index 9a1a1c3ee..14d196d9f 100644 --- a/example/dijkstra-no-color-map-example.cpp +++ b/example/dijkstra-no-color-map-example.cpp @@ -26,7 +26,6 @@ main(int, char *[]) typedef adjacency_list < listS, vecS, directedS, no_property, property < edge_weight_t, int > > graph_t; typedef graph_traits < graph_t >::vertex_descriptor vertex_descriptor; - typedef graph_traits < graph_t >::edge_descriptor edge_descriptor; typedef std::pair Edge; const int num_nodes = 5; diff --git a/example/mcgregor_subgraphs_example.cpp b/example/mcgregor_subgraphs_example.cpp index 35a3b6930..543259fc7 100644 --- a/example/mcgregor_subgraphs_example.cpp +++ b/example/mcgregor_subgraphs_example.cpp @@ -76,11 +76,7 @@ int main (int argc, char *argv[]) { property >, property > Graph; - typedef graph_traits::vertex_descriptor Vertex; - typedef graph_traits::edge_descriptor Edge; - typedef property_map::type VertexNameMap; - typedef property_map::type EdgeNameMap; // Test maximum and unique variants on known graphs Graph graph_simple1, graph_simple2; diff --git a/example/stoer_wagner.cpp b/example/stoer_wagner.cpp index e710078b6..09f13006a 100644 --- a/example/stoer_wagner.cpp +++ b/example/stoer_wagner.cpp @@ -27,7 +27,6 @@ int main() typedef boost::adjacency_list > undirected_graph; - typedef boost::graph_traits::vertex_descriptor vertex_descriptor; typedef boost::property_map::type weight_map_type; typedef boost::property_traits::value_type weight_type; diff --git a/example/subgraph.cpp b/example/subgraph.cpp index a28a6cab8..289ae54d9 100644 --- a/example/subgraph.cpp +++ b/example/subgraph.cpp @@ -41,7 +41,6 @@ int main(int,char*[]) { using namespace boost; - typedef adjacency_list_traits Traits; typedef subgraph< adjacency_list, property > > Graph; diff --git a/include/boost/graph/bellman_ford_shortest_paths.hpp b/include/boost/graph/bellman_ford_shortest_paths.hpp index e102d9220..7873067a1 100644 --- a/include/boost/graph/bellman_ford_shortest_paths.hpp +++ b/include/boost/graph/bellman_ford_shortest_paths.hpp @@ -102,8 +102,6 @@ namespace boost { typedef typename GTraits::vertex_descriptor Vertex; BOOST_CONCEPT_ASSERT(( ReadWritePropertyMapConcept )); BOOST_CONCEPT_ASSERT(( ReadablePropertyMapConcept )); - typedef typename property_traits::value_type D_value; - typedef typename property_traits::value_type W_value; typename GTraits::edge_iterator i, end; diff --git a/include/boost/graph/betweenness_centrality.hpp b/include/boost/graph/betweenness_centrality.hpp index a4de17533..d596d5a28 100644 --- a/include/boost/graph/betweenness_centrality.hpp +++ b/include/boost/graph/betweenness_centrality.hpp @@ -296,7 +296,6 @@ namespace detail { namespace graph { ShortestPaths shortest_paths) { typedef typename graph_traits::vertex_iterator vertex_iterator; - typedef typename graph_traits::edge_iterator edge_iterator; typedef typename graph_traits::vertex_descriptor vertex_descriptor; // Initialize centrality @@ -421,7 +420,6 @@ namespace detail { namespace graph { VertexIndexMap vertex_index) { typedef typename graph_traits::degree_size_type degree_size_type; - typedef typename graph_traits::vertex_descriptor vertex_descriptor; typedef typename graph_traits::edge_descriptor edge_descriptor; typedef typename mpl::if_c<(is_same::value), @@ -457,7 +455,6 @@ namespace detail { namespace graph { VertexIndexMap vertex_index) { typedef typename graph_traits::degree_size_type degree_size_type; - typedef typename graph_traits::vertex_descriptor vertex_descriptor; typedef typename graph_traits::edge_descriptor edge_descriptor; typedef typename mpl::if_c<(is_same::value), diff --git a/include/boost/graph/bipartite.hpp b/include/boost/graph/bipartite.hpp index b917c607e..74316fd53 100644 --- a/include/boost/graph/bipartite.hpp +++ b/include/boost/graph/bipartite.hpp @@ -198,7 +198,6 @@ namespace boost { /// General types and variables typedef typename property_traits ::value_type partition_color_t; typedef typename graph_traits ::vertex_descriptor vertex_descriptor_t; - typedef typename graph_traits ::vertex_iterator vertex_iterator_t; /// Declare dfs visitor // detail::empty_recorder recorder; diff --git a/include/boost/graph/breadth_first_search.hpp b/include/boost/graph/breadth_first_search.hpp index f50172e35..b0d10ad5f 100644 --- a/include/boost/graph/breadth_first_search.hpp +++ b/include/boost/graph/breadth_first_search.hpp @@ -64,7 +64,6 @@ namespace boost { BOOST_CONCEPT_ASSERT(( IncidenceGraphConcept )); typedef graph_traits GTraits; typedef typename GTraits::vertex_descriptor Vertex; - typedef typename GTraits::edge_descriptor Edge; BOOST_CONCEPT_ASSERT(( BFSVisitorConcept )); BOOST_CONCEPT_ASSERT(( ReadWritePropertyMapConcept )); typedef typename property_traits::value_type ColorValue; diff --git a/include/boost/graph/chrobak_payne_drawing.hpp b/include/boost/graph/chrobak_payne_drawing.hpp index 4d026986c..0e1f05255 100644 --- a/include/boost/graph/chrobak_payne_drawing.hpp +++ b/include/boost/graph/chrobak_payne_drawing.hpp @@ -73,7 +73,6 @@ namespace boost { typedef typename graph_traits::vertex_descriptor vertex_t; - typedef typename graph_traits::edge_descriptor edge_t; typedef typename graph_traits::vertex_iterator vertex_iterator_t; typedef typename PlanarEmbedding::value_type::const_iterator edge_permutation_iterator_t; diff --git a/include/boost/graph/closeness_centrality.hpp b/include/boost/graph/closeness_centrality.hpp index 44d478ab2..3ddf284b5 100644 --- a/include/boost/graph/closeness_centrality.hpp +++ b/include/boost/graph/closeness_centrality.hpp @@ -123,7 +123,6 @@ all_closeness_centralities(const Graph& g, typedef typename property_traits::value_type DistanceMap; BOOST_CONCEPT_ASSERT(( ReadablePropertyMapConcept )); BOOST_CONCEPT_ASSERT(( WritablePropertyMapConcept )); - typedef typename property_traits::value_type Distance; typedef typename property_traits::value_type Centrality; typename graph_traits::vertex_iterator i, end; @@ -147,7 +146,6 @@ all_closeness_centralities(const Graph& g, BOOST_CONCEPT_ASSERT(( ReadablePropertyMapConcept )); typedef typename property_traits::value_type DistanceMap; BOOST_CONCEPT_ASSERT(( ReadablePropertyMapConcept )); - typedef typename property_traits::value_type Distance; typedef typename property_traits::value_type Result; all_closeness_centralities(g, dist, cent, measure_closeness(g, DistanceMap())); diff --git a/include/boost/graph/connected_components.hpp b/include/boost/graph/connected_components.hpp index 076b2a68e..9279110f1 100644 --- a/include/boost/graph/connected_components.hpp +++ b/include/boost/graph/connected_components.hpp @@ -86,7 +86,7 @@ namespace boost { typedef typename graph_traits::vertex_descriptor Vertex; BOOST_CONCEPT_ASSERT(( WritablePropertyMapConcept )); - typedef typename boost::graph_traits::directed_category directed; + // typedef typename boost::graph_traits::directed_category directed; // BOOST_STATIC_ASSERT((boost::is_same::value)); typedef typename property_traits::value_type comp_type; diff --git a/include/boost/graph/core_numbers.hpp b/include/boost/graph/core_numbers.hpp index 33764c4f4..9384f5d66 100644 --- a/include/boost/graph/core_numbers.hpp +++ b/include/boost/graph/core_numbers.hpp @@ -316,7 +316,6 @@ namespace boost { core_numbers(Graph& g, CoreMap c, EdgeWeightMap wm, VertexIndexMap vim, CoreNumVisitor vis) { - typedef typename graph_traits::vertices_size_type size_type; detail::compute_in_degree_map(g,c,wm); return detail::core_numbers_dispatch(g,c,wm,vim,vis); } diff --git a/include/boost/graph/cuthill_mckee_ordering.hpp b/include/boost/graph/cuthill_mckee_ordering.hpp index 52dc982a1..e16595c6c 100644 --- a/include/boost/graph/cuthill_mckee_ordering.hpp +++ b/include/boost/graph/cuthill_mckee_ordering.hpp @@ -75,7 +75,6 @@ namespace boost { { //create queue, visitor...don't forget namespaces! - typedef typename property_traits::value_type ds_type; typedef typename graph_traits::vertex_descriptor Vertex; typedef typename boost::sparse::sparse_ordering_queue queue; typedef typename detail::bfs_rcm_visitor Visitor; @@ -137,7 +136,6 @@ namespace boost { return permutation; typedef typename boost::graph_traits::vertex_descriptor Vertex; - typedef typename boost::graph_traits::vertex_iterator VerIter; typedef typename property_traits::value_type ColorValue; typedef color_traits Color; @@ -172,7 +170,6 @@ namespace boost { if (boost::graph::has_no_vertices(G)) return permutation; - typedef out_degree_property_map DegreeMap; std::vector colors(num_vertices(G)); return cuthill_mckee_ordering(G, permutation, make_iterator_property_map(&colors[0], diff --git a/include/boost/graph/dijkstra_shortest_paths_no_color_map.hpp b/include/boost/graph/dijkstra_shortest_paths_no_color_map.hpp index c5ce6b6d4..b1a9ef589 100644 --- a/include/boost/graph/dijkstra_shortest_paths_no_color_map.hpp +++ b/include/boost/graph/dijkstra_shortest_paths_no_color_map.hpp @@ -41,7 +41,6 @@ namespace boost { { typedef typename graph_traits::vertex_descriptor Vertex; typedef typename property_traits::value_type Distance; - typedef typename property_traits::value_type Weight; typedef indirect_cmp DistanceIndirectCompare; DistanceIndirectCompare @@ -92,7 +91,6 @@ namespace boost { } // Examine neighbors of min_vertex - typedef typename graph_traits::edge_descriptor Edge; BGL_FORALL_OUTEDGES_T(min_vertex, current_edge, graph, Graph) { visitor.examine_edge(current_edge, graph); diff --git a/include/boost/graph/edmonds_karp_max_flow.hpp b/include/boost/graph/edmonds_karp_max_flow.hpp index 8f86fb202..377e6f14d 100644 --- a/include/boost/graph/edmonds_karp_max_flow.hpp +++ b/include/boost/graph/edmonds_karp_max_flow.hpp @@ -151,7 +151,6 @@ namespace boost { const bgl_named_params& params, param_not_found) { - typedef typename graph_traits::edge_descriptor edge_descriptor; typedef typename graph_traits::vertices_size_type size_type; size_type n = is_default_param(get_param(params, vertex_color)) ? num_vertices(g) : 1; diff --git a/include/boost/graph/fruchterman_reingold.hpp b/include/boost/graph/fruchterman_reingold.hpp index bab353f33..01d080a41 100644 --- a/include/boost/graph/fruchterman_reingold.hpp +++ b/include/boost/graph/fruchterman_reingold.hpp @@ -282,7 +282,6 @@ fruchterman_reingold_force_directed_layout Cooling cool, DisplacementMap displacement) { - typedef typename Topology::point_type Point; typedef typename graph_traits::vertex_iterator vertex_iterator; typedef typename graph_traits::vertex_descriptor vertex_descriptor; typedef typename graph_traits::edge_iterator edge_iterator; diff --git a/include/boost/graph/graph_utility.hpp b/include/boost/graph/graph_utility.hpp index ba1fe3d83..e772b6406 100644 --- a/include/boost/graph/graph_utility.hpp +++ b/include/boost/graph/graph_utility.hpp @@ -237,8 +237,6 @@ namespace boost { template bool is_adj_dispatch(Graph& g, Vertex a, Vertex b, bidirectional_tag) { - typedef typename graph_traits::edge_descriptor - edge_descriptor; typename graph_traits::adjacency_iterator vi, viend, adj_found; boost::tie(vi, viend) = adjacent_vertices(a, g); @@ -265,8 +263,6 @@ namespace boost { template bool is_adj_dispatch(Graph& g, Vertex a, Vertex b, directed_tag) { - typedef typename graph_traits::edge_descriptor - edge_descriptor; typename graph_traits::adjacency_iterator vi, viend, found; boost::tie(vi, viend) = adjacent_vertices(a, g); #if defined(BOOST_MSVC) && BOOST_MSVC <= 1300 && defined(__SGI_STL_PORT) diff --git a/include/boost/graph/gursoy_atun_layout.hpp b/include/boost/graph/gursoy_atun_layout.hpp index 9269c4b06..9f050e1b3 100644 --- a/include/boost/graph/gursoy_atun_layout.hpp +++ b/include/boost/graph/gursoy_atun_layout.hpp @@ -208,9 +208,6 @@ void gursoy_atun_refine(const VertexListAndIncidenceGraph& graph, typedef typename graph_traits::vertex_iterator vertex_iterator; - typedef typename graph_traits::vertex_descriptor - vertex_descriptor; - typedef typename Topology::point_type point_type; vertex_iterator i, iend; double diameter_ratio = (double)diameter_final / diameter_initial; double learning_constant_ratio = @@ -230,6 +227,7 @@ void gursoy_atun_refine(const VertexListAndIncidenceGraph& graph, vertex_index_map); for (int round = 0; round < nsteps; ++round) { double part_done = (double)round / (nsteps - 1); + // fprintf(stderr, "%2d%% done\n", int(rint(part_done * 100.))); int diameter = (int)(diameter_initial * pow(diameter_ratio, part_done)); double learning_constant = learning_constant_initial * pow(learning_constant_ratio, part_done); diff --git a/include/boost/graph/is_straight_line_drawing.hpp b/include/boost/graph/is_straight_line_drawing.hpp index c471cde8b..a4bd8ff5f 100644 --- a/include/boost/graph/is_straight_line_drawing.hpp +++ b/include/boost/graph/is_straight_line_drawing.hpp @@ -106,11 +106,8 @@ namespace boost { typedef typename graph_traits::vertex_descriptor vertex_t; - typedef typename graph_traits::vertex_iterator vertex_iterator_t; typedef typename graph_traits::edge_descriptor edge_t; typedef typename graph_traits::edge_iterator edge_iterator_t; - typedef typename graph_traits::edges_size_type e_size_t; - typedef typename graph_traits::vertices_size_type v_size_t; typedef std::size_t x_coord_t; typedef std::size_t y_coord_t; diff --git a/include/boost/graph/king_ordering.hpp b/include/boost/graph/king_ordering.hpp index 9d9a438f3..29e7ac970 100644 --- a/include/boost/graph/king_ordering.hpp +++ b/include/boost/graph/king_ordering.hpp @@ -37,7 +37,6 @@ namespace boost { typename graph_traits::out_edge_iterator ei, ei_end; Vertex v, w; - typedef typename std::deque::iterator iterator; typedef typename std::deque::reverse_iterator reverse_iterator; reverse_iterator rend = Qptr->rend()-index_begin; @@ -86,8 +85,6 @@ namespace boost { //this function replaces pop_heap, and tracks state information template void percolate_down(int offset){ - typedef typename std::deque::reverse_iterator reverse_iterator; - int heap_last = index_begin + offset; int heap_first = Qptr->size() - 1; @@ -267,7 +264,6 @@ namespace boost { return permutation; typedef typename boost::graph_traits::vertex_descriptor Vertex; - typedef typename boost::graph_traits::vertex_iterator VerIter; typedef typename property_traits::value_type ColorValue; typedef color_traits Color; @@ -302,7 +298,6 @@ namespace boost { if (has_no_vertices(G)) return permutation; - typedef out_degree_property_map DegreeMap; std::vector colors(num_vertices(G)); return king_ordering(G, permutation, make_iterator_property_map(&colors[0], index_map, diff --git a/include/boost/graph/kruskal_min_spanning_tree.hpp b/include/boost/graph/kruskal_min_spanning_tree.hpp index 4d0c7efcd..b7e815770 100644 --- a/include/boost/graph/kruskal_min_spanning_tree.hpp +++ b/include/boost/graph/kruskal_min_spanning_tree.hpp @@ -102,7 +102,6 @@ namespace boost { { typedef typename graph_traits::vertices_size_type size_type; typedef typename graph_traits::vertex_descriptor vertex_t; - typedef typename property_map::type index_map_t; if (num_vertices(g) == 0) return; // Nothing to do in this case typename graph_traits::vertices_size_type n = num_vertices(g); diff --git a/include/boost/graph/maximum_adjacency_search.hpp b/include/boost/graph/maximum_adjacency_search.hpp index 58dc8695e..e27a7a048 100644 --- a/include/boost/graph/maximum_adjacency_search.hpp +++ b/include/boost/graph/maximum_adjacency_search.hpp @@ -118,8 +118,6 @@ namespace boost { void maximum_adjacency_search(const Graph& g, WeightMap weights, MASVisitor vis, const typename boost::graph_traits::vertex_descriptor start, VertexAssignmentMap assignments, KeyedUpdatablePriorityQueue pq) { typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; - typedef typename boost::graph_traits::vertices_size_type vertices_size_type; - typedef typename boost::graph_traits::edge_descriptor edge_descriptor; typedef typename boost::property_traits::value_type weight_type; std::set assignedVertices; @@ -197,7 +195,7 @@ maximum_adjacency_search(const Graph& g, WeightMap weights, MASVisitor vis, cons typedef typename boost::graph_traits::edge_descriptor edge_descriptor; BOOST_CONCEPT_ASSERT((boost::Convertible::directed_category, boost::undirected_tag>)); BOOST_CONCEPT_ASSERT((boost::ReadablePropertyMapConcept)); - typedef typename boost::property_traits::value_type weight_type; + // typedef typename boost::property_traits::value_type weight_type; boost::function_requires< MASVisitorConcept >(); BOOST_CONCEPT_ASSERT((boost::ReadWritePropertyMapConcept)); BOOST_CONCEPT_ASSERT((boost::Convertible::value_type>)); diff --git a/include/boost/graph/mcgregor_common_subgraphs.hpp b/include/boost/graph/mcgregor_common_subgraphs.hpp index c46f72156..987a03bf2 100644 --- a/include/boost/graph/mcgregor_common_subgraphs.hpp +++ b/include/boost/graph/mcgregor_common_subgraphs.hpp @@ -121,7 +121,6 @@ namespace boost { VertexEquivalencePredicate vertices_equivalent, bool only_connected_subgraphs) { - typedef typename graph_traits::vertex_descriptor VertexFirst; typedef typename graph_traits::vertex_descriptor VertexSecond; typedef typename graph_traits::edge_descriptor EdgeFirst; diff --git a/include/boost/graph/metric_tsp_approx.hpp b/include/boost/graph/metric_tsp_approx.hpp index dd0ff1d67..c8e7dba59 100644 --- a/include/boost/graph/metric_tsp_approx.hpp +++ b/include/boost/graph/metric_tsp_approx.hpp @@ -173,7 +173,6 @@ namespace boost // We build a custom graph in this algorithm. typedef adjacency_list MSTImpl; - typedef graph_traits::edge_descriptor Edge; typedef graph_traits::vertex_descriptor Vertex; typedef graph_traits::vertex_iterator VItr; diff --git a/include/boost/graph/planar_canonical_ordering.hpp b/include/boost/graph/planar_canonical_ordering.hpp index 86203aaf3..d470ee591 100644 --- a/include/boost/graph/planar_canonical_ordering.hpp +++ b/include/boost/graph/planar_canonical_ordering.hpp @@ -41,10 +41,8 @@ namespace boost typedef typename graph_traits::vertex_descriptor vertex_t; typedef typename graph_traits::edge_descriptor edge_t; - typedef typename graph_traits::vertex_iterator vertex_iterator_t; typedef typename graph_traits::adjacency_iterator adjacency_iterator_t; - typedef typename std::pair vertex_pair_t; typedef typename property_traits::value_type embedding_value_t; typedef typename embedding_value_t::const_iterator embedding_iterator_t; diff --git a/include/boost/graph/random.hpp b/include/boost/graph/random.hpp index f4001337a..f0153b2c4 100644 --- a/include/boost/graph/random.hpp +++ b/include/boost/graph/random.hpp @@ -86,8 +86,6 @@ namespace boost { template typename graph_traits::edge_descriptor weighted_random_out_edge(Graph& g, typename graph_traits::vertex_descriptor src, WeightMap weight, RandomNumGen& gen) { - typedef graph_traits gt; - typedef typename gt::vertex_descriptor vertex_descriptor; typedef typename property_traits::value_type weight_type; weight_type weight_sum(0); BGL_FORALL_OUTEDGES_T(src, e, g, Graph) {weight_sum += get(weight, e);} diff --git a/include/boost/graph/random_spanning_tree.hpp b/include/boost/graph/random_spanning_tree.hpp index 5ecd4f17d..76dc7f2b9 100644 --- a/include/boost/graph/random_spanning_tree.hpp +++ b/include/boost/graph/random_spanning_tree.hpp @@ -33,7 +33,6 @@ namespace boost { template void random_spanning_tree_internal(const Graph& g, typename graph_traits::vertex_descriptor s, PredMap pred, ColorMap color, NextEdge next_edge) { typedef typename graph_traits::vertex_descriptor vertex_descriptor; - typedef typename graph_traits::edge_descriptor edge_descriptor; BOOST_ASSERT (num_vertices(g) >= 1); // g must also be undirected (or symmetric) and connected diff --git a/include/boost/graph/read_dimacs.hpp b/include/boost/graph/read_dimacs.hpp index 06f1a335f..0297744c8 100644 --- a/include/boost/graph/read_dimacs.hpp +++ b/include/boost/graph/read_dimacs.hpp @@ -45,7 +45,6 @@ int read_dimacs_max_flow_internal(Graph& g, const int NODE_FIELDS = 2; /* no of fields in node line */ const int P_FIELDS = 3; /* no of fields in problem line */ - typedef typename graph_traits::vertices_size_type vertices_size_type; typedef typename graph_traits::vertex_descriptor vertex_descriptor; typedef typename graph_traits::edge_descriptor edge_descriptor; diff --git a/include/boost/graph/stoer_wagner_min_cut.hpp b/include/boost/graph/stoer_wagner_min_cut.hpp index a777f0311..eb5998c71 100644 --- a/include/boost/graph/stoer_wagner_min_cut.hpp +++ b/include/boost/graph/stoer_wagner_min_cut.hpp @@ -76,7 +76,6 @@ namespace boost { template < typename Vertex, typename Graph > void finish_vertex(Vertex u, const Graph & g) { - typedef typename boost::property_traits::value_type parity_type; typedef typename boost::property_traits::value_type internal_parity_type; ++m_visited; @@ -131,10 +130,7 @@ namespace boost { typename boost::property_traits::value_type stoer_wagner_min_cut(const UndirectedGraph& g, WeightMap weights, ParityMap parities, VertexAssignmentMap assignments, KeyedUpdatablePriorityQueue& pq, IndexMap index_map) { typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; - typedef typename boost::graph_traits::vertices_size_type vertices_size_type; - typedef typename boost::graph_traits::edge_descriptor edge_descriptor; typedef typename boost::property_traits::value_type weight_type; - typedef typename boost::property_traits::value_type parity_type; typename graph_traits::vertex_iterator u_iter, u_end; @@ -185,9 +181,9 @@ namespace boost { typedef typename boost::graph_traits::edge_descriptor edge_descriptor; BOOST_CONCEPT_ASSERT((boost::Convertible::directed_category, boost::undirected_tag>)); BOOST_CONCEPT_ASSERT((boost::ReadablePropertyMapConcept)); - typedef typename boost::property_traits::value_type weight_type; + // typedef typename boost::property_traits::value_type weight_type; BOOST_CONCEPT_ASSERT((boost::WritablePropertyMapConcept)); - typedef typename boost::property_traits::value_type parity_type; + // typedef typename boost::property_traits::value_type parity_type; BOOST_CONCEPT_ASSERT((boost::ReadWritePropertyMapConcept)); BOOST_CONCEPT_ASSERT((boost::Convertible::value_type>)); BOOST_CONCEPT_ASSERT((boost::KeyedUpdatableQueueConcept)); diff --git a/include/boost/graph/tiernan_all_cycles.hpp b/include/boost/graph/tiernan_all_cycles.hpp index 97ee89c44..d4527d552 100644 --- a/include/boost/graph/tiernan_all_cycles.hpp +++ b/include/boost/graph/tiernan_all_cycles.hpp @@ -212,7 +212,6 @@ namespace detail { BOOST_CONCEPT_ASSERT(( IncidenceGraphConcept )); typedef typename graph_traits::vertex_descriptor Vertex; - typedef typename graph_traits::edge_descriptor Edge; typedef typename graph_traits::out_edge_iterator OutIterator; // get the current vertex diff --git a/include/boost/graph/transitive_closure.hpp b/include/boost/graph/transitive_closure.hpp index d40f90e4f..4f81349bf 100644 --- a/include/boost/graph/transitive_closure.hpp +++ b/include/boost/graph/transitive_closure.hpp @@ -71,7 +71,6 @@ namespace boost if (num_vertices(g) == 0) return; typedef typename graph_traits < Graph >::vertex_descriptor vertex; - typedef typename graph_traits < Graph >::edge_descriptor edge; typedef typename graph_traits < Graph >::vertex_iterator vertex_iterator; typedef typename property_traits < VertexIndexMap >::value_type size_type; typedef typename graph_traits < @@ -208,7 +207,6 @@ namespace boost // Add vertices to the transitive closure graph - typedef typename graph_traits < GraphTC >::vertex_descriptor tc_vertex; { vertex_iterator i, i_end; for (boost::tie(i, i_end) = vertices(g); i != i_end; ++i) @@ -306,7 +304,6 @@ namespace boost template < typename G > void warshall_transitive_closure(G & g) { - typedef typename graph_traits < G >::vertex_descriptor vertex; typedef typename graph_traits < G >::vertex_iterator vertex_iterator; BOOST_CONCEPT_ASSERT(( AdjacencyMatrixConcept < G > )); @@ -332,7 +329,6 @@ namespace boost template < typename G > void warren_transitive_closure(G & g) { using namespace boost; - typedef typename graph_traits < G >::vertex_descriptor vertex; typedef typename graph_traits < G >::vertex_iterator vertex_iterator; BOOST_CONCEPT_ASSERT(( AdjacencyMatrixConcept < G > )); diff --git a/include/boost/graph/two_graphs_common_spanning_trees.hpp b/include/boost/graph/two_graphs_common_spanning_trees.hpp index 86d57ece0..48f80df17 100644 --- a/include/boost/graph/two_graphs_common_spanning_trees.hpp +++ b/include/boost/graph/two_graphs_common_spanning_trees.hpp @@ -591,17 +591,11 @@ two_graphs_common_spanning_trees typedef typename GraphTraits::edges_size_type edges_size_type; typedef typename GraphTraits::edge_iterator edge_iterator; - typedef typename Seq::const_iterator seq_const_iterator; - typedef typename Seq::difference_type seq_diff_type; typedef typename Seq::value_type seq_value_type; typedef typename Seq::size_type seq_size_type; - typedef typename Seq::iterator seq_iterator; - typedef typename Order::const_iterator order_const_iterator; - typedef typename Order::difference_type order_diff_type; typedef typename Order::value_type order_value_type; typedef typename Order::size_type order_size_type; - typedef typename Order::iterator order_iterator; BOOST_STATIC_ASSERT((is_same::value)); BOOST_CONCEPT_ASSERT((Convertible)); @@ -846,7 +840,6 @@ two_graphs_common_spanning_trees typedef graph_traits GraphTraits; typedef typename GraphTraits::edge_descriptor edge_descriptor; - typedef typename GraphTraits::edges_size_type edges_size_type; typedef typename GraphTraits::edge_iterator edge_iterator; std::vector iGO, vGO; diff --git a/include/boost/graph/vf2_sub_graph_iso.hpp b/include/boost/graph/vf2_sub_graph_iso.hpp index a316f7813..21011b516 100755 --- a/include/boost/graph/vf2_sub_graph_iso.hpp +++ b/include/boost/graph/vf2_sub_graph_iso.hpp @@ -1014,8 +1014,6 @@ namespace boost { bool vf2_subgraph_iso(const GraphSmall& graph_small, const GraphLarge& graph_large, SubGraphIsoMapCallback user_callback) { - typedef typename graph_traits::vertex_descriptor vertex_small_type; - return vf2_subgraph_iso(graph_small, graph_large, user_callback, get(vertex_index, graph_small), get(vertex_index, graph_large), vertex_order_by_mult(graph_small), @@ -1144,8 +1142,6 @@ namespace boost { bool vf2_graph_iso(const Graph1& graph1, const Graph2& graph2, GraphIsoMapCallback user_callback) { - typedef typename graph_traits::vertex_descriptor vertex1_type; - return vf2_graph_iso(graph1, graph2, user_callback, get(vertex_index, graph1), get(vertex_index, graph2), vertex_order_by_mult(graph1), diff --git a/include/boost/graph/write_dimacs.hpp b/include/boost/graph/write_dimacs.hpp index a9a890465..a4a577736 100644 --- a/include/boost/graph/write_dimacs.hpp +++ b/include/boost/graph/write_dimacs.hpp @@ -51,10 +51,6 @@ void write_dimacs_max_flow(const Graph& g, typename graph_traits::vertex_descriptor sink, std::ostream& out) { - typedef typename graph_traits::vertex_descriptor vertex_descriptor; - typedef typename graph_traits::vertices_size_type vertices_size_type; - typedef typename graph_traits::edge_descriptor edge_descriptor; - typedef typename graph_traits::edges_size_type edges_size_type; typedef typename graph_traits::edge_iterator edge_iterator; out << "c DIMACS max-flow file generated from boost::write_dimacs_max_flow" << std::endl; diff --git a/test/adj_list_loops.cpp b/test/adj_list_loops.cpp index 205f37306..cd7b0896d 100644 --- a/test/adj_list_loops.cpp +++ b/test/adj_list_loops.cpp @@ -17,7 +17,6 @@ template void test_graph_nonloop() { typedef typename graph_traits::vertex_descriptor Vertex; - typedef typename graph_traits::edge_descriptor Edge; // Build a graph with 1 edge and turn it into a loop. Graph g(5); @@ -36,7 +35,6 @@ template void test_multigraph_nonloop() { typedef typename graph_traits::vertex_descriptor Vertex; - typedef typename graph_traits::edge_descriptor Edge; // Build a graph with 1 edge and turn it into a loop. Graph g(5); @@ -55,7 +53,6 @@ template void test_graph_loop() { typedef typename graph_traits::vertex_descriptor Vertex; - typedef typename graph_traits::edge_descriptor Edge; Graph g(5); Vertex v = *next(vertices(g).first, 2); @@ -70,7 +67,6 @@ template void test_multigraph_loop() { typedef typename graph_traits::vertex_descriptor Vertex; - typedef typename graph_traits::edge_descriptor Edge; Graph g(5); Vertex v = *next(vertices(g).first, 2); diff --git a/test/all_planar_input_files_test.cpp b/test/all_planar_input_files_test.cpp index 5fec2e362..e918f1f84 100644 --- a/test/all_planar_input_files_test.cpp +++ b/test/all_planar_input_files_test.cpp @@ -122,9 +122,7 @@ int test_graph(const std::string& dimacs_filename) typedef graph_traits::edge_iterator edge_iterator_t; typedef graph_traits::vertex_iterator vertex_iterator_t; typedef graph_traits::edges_size_type e_size_t; - typedef graph_traits::vertices_size_type v_size_t; typedef graph_traits::vertex_descriptor vertex_t; - typedef std::pair vertex_pair_t; typedef edge_index_update_visitor::type> edge_visitor_t; diff --git a/test/astar_search_test.cpp b/test/astar_search_test.cpp index d72b91f0b..d5fca3f4d 100644 --- a/test/astar_search_test.cpp +++ b/test/astar_search_test.cpp @@ -122,7 +122,6 @@ int main(int, char **) typedef property_map::type WeightMap; typedef mygraph_t::vertex_descriptor vertex; typedef mygraph_t::edge_descriptor edge_descriptor; - typedef mygraph_t::vertex_iterator vertex_iterator; typedef std::pair edge; // specify data diff --git a/test/closeness_centrality.cpp b/test/closeness_centrality.cpp index 5fd16b9cc..62b65de1a 100644 --- a/test/closeness_centrality.cpp +++ b/test/closeness_centrality.cpp @@ -31,8 +31,6 @@ template void build_graph(Graph& g, typename vertex_vector::type& v) { - typedef typename graph_traits::vertex_descriptor Vertex; - // add vertices for(size_t i = 0; i < N; ++i) { v[i] = add_vertex(g); diff --git a/test/clustering_coefficient.cpp b/test/clustering_coefficient.cpp index 21eee890d..a4de0417d 100644 --- a/test/clustering_coefficient.cpp +++ b/test/clustering_coefficient.cpp @@ -27,8 +27,6 @@ struct vertex_vector template void build_graph(Graph& g, typename vertex_vector::type& v) { - typedef typename graph_traits::vertex_descriptor Vertex; - // add vertices for(size_t i = 0; i < N; ++i) { v[i] = add_vertex(g); @@ -98,7 +96,7 @@ int main(int, char *[]) { typedef undirected_graph<> Graph; - typedef directed_graph<> Digraph; + // typedef directed_graph<> Digraph; // TODO: write a test for directed clustering coefficient. diff --git a/test/cycle_ratio_tests.cpp b/test/cycle_ratio_tests.cpp index ac5f208f3..5448c87b5 100644 --- a/test/cycle_ratio_tests.cpp +++ b/test/cycle_ratio_tests.cpp @@ -331,7 +331,6 @@ int test_main(int argc, char* argv[]) { GraphMInt gm(10); typedef graph_traits::vertex_iterator VertexItM; - typedef graph_traits::edge_descriptor EdgeM; VertexItM vi1, vi2, vi_end; for (boost::tie(vi1, vi_end) = vertices(gm); vi1 != vi_end; ++vi1) { diff --git a/test/degree_centrality.cpp b/test/degree_centrality.cpp index bb6e6b39c..42adb5b11 100644 --- a/test/degree_centrality.cpp +++ b/test/degree_centrality.cpp @@ -22,8 +22,6 @@ template void build_graph(Graph& g, vector::vertex_descriptor>& v) { - typedef typename graph_traits::vertex_descriptor Vertex; - // add vertices for(size_t i = 0; i < N; ++i) { v[i] = add_vertex(g); diff --git a/test/dijkstra_no_color_map_compare.cpp b/test/dijkstra_no_color_map_compare.cpp index 5ff18c1c9..739b899e7 100644 --- a/test/dijkstra_no_color_map_compare.cpp +++ b/test/dijkstra_no_color_map_compare.cpp @@ -94,9 +94,6 @@ int test_main(int argc, char* argv[]) property, property > graph_t; - typedef graph_traits::vertex_descriptor vertex_t; - typedef graph_traits::edge_descriptor edge_t; - graph_t graph; generate_random_graph(graph, vertices_to_create, edges_to_create, generator); diff --git a/test/eccentricity.cpp b/test/eccentricity.cpp index 596f38ef5..2c04c7d63 100644 --- a/test/eccentricity.cpp +++ b/test/eccentricity.cpp @@ -31,8 +31,6 @@ template void build_graph(Graph& g, typename vertex_vector::type& v) { - typedef typename graph_traits::vertex_descriptor Vertex; - // add vertices for(size_t i = 0; i < N; ++i) { v[i] = add_vertex(g); diff --git a/test/graphviz_test.cpp b/test/graphviz_test.cpp index adc29034a..94f200a01 100644 --- a/test/graphviz_test.cpp +++ b/test/graphviz_test.cpp @@ -75,9 +75,6 @@ bool test_graph(std::istream& dotfile, graph_t& graph, MassMap mass, WeightMap weight) { - typedef typename graph_traits < graph_t >::edge_descriptor edge_t; - typedef typename graph_traits < graph_t >::vertex_descriptor vertex_t; - // Construct a graph and set up the dynamic_property_maps. dynamic_properties dp(ignore_other_properties); dp.property(node_id,name); diff --git a/test/index_graph.cpp b/test/index_graph.cpp index 3e757e82e..aaa7958bd 100644 --- a/test/index_graph.cpp +++ b/test/index_graph.cpp @@ -64,7 +64,6 @@ void test() template void build() { - typedef typename graph_traits::vertex_descriptor Vertex; typedef typename graph_traits::vertex_iterator Iterator; typedef typename property_map::type IndexMap; diff --git a/test/layout_test.cpp b/test/layout_test.cpp index 7f85614a9..4bf9e7052 100644 --- a/test/layout_test.cpp +++ b/test/layout_test.cpp @@ -78,10 +78,8 @@ template void test_circle_layout(Graph*, typename graph_traits::vertices_size_type n) { - typedef typename graph_traits::vertex_descriptor vertex; typedef typename graph_traits::vertex_iterator vertex_iterator; typedef typename graph_traits::vertices_size_type vertices_size_type; - typedef typename graph_traits::edges_size_type edges_size_type; Graph g(n); diff --git a/test/matching_test.cpp b/test/matching_test.cpp index 784fca587..f15269651 100644 --- a/test/matching_test.cpp +++ b/test/matching_test.cpp @@ -131,7 +131,6 @@ void matching_test(std::size_t num_v, const std::string& graph_name) typedef vector_property_map< typename graph_traits::vertex_descriptor, vertex_index_map_t > mate_t; typedef typename graph_traits::vertex_iterator vertex_iterator_t; typedef typename graph_traits::vertex_descriptor vertex_descriptor_t; - typedef typename graph_traits::vertices_size_type v_size_t; const std::size_t double_num_v = num_v * 2; diff --git a/test/mcgregor_subgraphs_test.cpp b/test/mcgregor_subgraphs_test.cpp index 516a32aa3..96cf4fa07 100644 --- a/test/mcgregor_subgraphs_test.cpp +++ b/test/mcgregor_subgraphs_test.cpp @@ -195,10 +195,6 @@ struct simple_callback { typedef typename boost::graph_traits::vertex_descriptor Vertex; - typedef typename boost::property_map::type VertexIndexMap; - typedef typename boost::property_map::type VertexNameMap; - typedef typename boost::property_map::type EdgeNameMap; - std::stringstream subgraph_string; BGL_FORALL_VERTICES_T(vertex1, m_graph1, Graph) { @@ -308,9 +304,6 @@ int test_main (int argc, char *argv[]) { boost::property >, boost::property > Graph; - typedef boost::graph_traits::vertex_descriptor Vertex; - typedef boost::graph_traits::edge_descriptor Edge; - typedef boost::property_map::type VertexNameMap; typedef boost::property_map::type EdgeNameMap; diff --git a/test/mean_geodesic.cpp b/test/mean_geodesic.cpp index c5b0f91f4..d78f677d7 100644 --- a/test/mean_geodesic.cpp +++ b/test/mean_geodesic.cpp @@ -31,8 +31,6 @@ struct vertex_vector template void build_graph(Graph& g, typename vertex_vector::type& v) { - typedef typename graph_traits::vertex_descriptor Vertex; - // add vertices for(size_t i = 0; i < N; ++i) { v[i] = add_vertex(g); diff --git a/test/metric_tsp_approx.cpp b/test/metric_tsp_approx.cpp index 111a8e26e..57560bd4d 100644 --- a/test/metric_tsp_approx.cpp +++ b/test/metric_tsp_approx.cpp @@ -86,7 +86,6 @@ void testScalability(unsigned numpts) property > > Graph; typedef graph_traits::vertex_descriptor Vertex; - typedef graph_traits ::edge_descriptor Edge; typedef property_map::type WeightMap; typedef set, cmpPnt > PointSet; typedef vector< Vertex > Container; @@ -199,7 +198,6 @@ int main(int argc, char* argv[]) typedef adjacency_matrix > Graph; typedef graph_traits::vertex_descriptor Vertex; - typedef graph_traits ::edge_descriptor Edge; typedef vector Container; typedef property_map::type WeightMap; typedef property_map::type VertexMap; diff --git a/test/parallel_edges_loops_test.cpp b/test/parallel_edges_loops_test.cpp index 52bb4e926..6045c37c3 100644 --- a/test/parallel_edges_loops_test.cpp +++ b/test/parallel_edges_loops_test.cpp @@ -195,9 +195,7 @@ int test_graph(const std::string& dimacs_filename) typedef graph_traits::edge_iterator edge_iterator_t; typedef graph_traits::vertex_iterator vertex_iterator_t; typedef graph_traits::edges_size_type e_size_t; - typedef graph_traits::vertices_size_type v_size_t; typedef graph_traits::vertex_descriptor vertex_t; - typedef std::pair vertex_pair_t; typedef edge_index_update_visitor::type> edge_visitor_t; diff --git a/test/property_iter.cpp b/test/property_iter.cpp index d206d2a7a..3c27f9425 100644 --- a/test/property_iter.cpp +++ b/test/property_iter.cpp @@ -109,19 +109,9 @@ int main(int, char* []) ++E; } - typedef boost::graph_property_iter_range< Graph, vertex_id_t>::const_iterator TNodeConstIterator; - typedef boost::graph_property_iter_range< Graph, vertex_id_t>::const_type TNodeConstIteratorType; - typedef boost::graph_property_iter_range< Graph, vertex_id_t>::iterator TNodeIterator; - typedef boost::graph_property_iter_range< Graph, vertex_id_t>::type TNodeIteratorType; - - typedef boost::graph_property_iter_range< Graph, edge_id_t>::const_iterator TLinkConstIterator; - typedef boost::graph_property_iter_range< Graph, edge_id_t>::const_type TLinkConstIteratorType; typedef boost::graph_property_iter_range< Graph, edge_id_t>::iterator TLinkIterator; - typedef boost::graph_property_iter_range< Graph, edge_id_t>::type TLinkIteratorType; - - typedef std::pair tLinkConstIteratorPair; TLinkIterator itEdgeBegin, itEdgeEnd; diff --git a/test/sequential_vertex_coloring.cpp b/test/sequential_vertex_coloring.cpp index 2a0775ae0..eee7d7387 100644 --- a/test/sequential_vertex_coloring.cpp +++ b/test/sequential_vertex_coloring.cpp @@ -16,7 +16,6 @@ using namespace boost; int test_main(int, char*[]) { typedef adjacency_list Graph; - typedef graph_traits::vertex_descriptor vertex_descriptor; typedef graph_traits::vertices_size_type vertices_size_type; typedef property_map::const_type vertex_index_map; diff --git a/test/stoer_wagner_test.cpp b/test/stoer_wagner_test.cpp index 034d5498f..0b7e83e20 100644 --- a/test/stoer_wagner_test.cpp +++ b/test/stoer_wagner_test.cpp @@ -45,9 +45,6 @@ struct edge_t // the example from Stoer & Wagner (1997) BOOST_AUTO_TEST_CASE(test0) { - typedef boost::graph_traits::vertex_descriptor vertex_descriptor; - typedef boost::graph_traits::edge_descriptor edge_descriptor; - edge_t edges[] = {{0, 1}, {1, 2}, {2, 3}, {0, 4}, {1, 4}, {1, 5}, {2, 6}, {3, 6}, {3, 7}, {4, 5}, {5, 6}, {6, 7}}; weight_type ws[] = {2, 3, 4, 3, 2, 2, 2, 2, 2, 3, 1, 3}; @@ -72,16 +69,12 @@ BOOST_AUTO_TEST_CASE(test0) BOOST_AUTO_TEST_CASE(test1) { { // if only one vertex, can't run `boost::stoer_wagner_min_cut` - typedef boost::graph_traits::vertex_descriptor vertex_descriptor; - typedef boost::graph_traits::edge_descriptor edge_descriptor; - undirected_graph g; add_vertex(g); BOOST_CHECK_THROW(boost::stoer_wagner_min_cut(g, get(boost::edge_weight, g)), boost::bad_graph); }{ // three vertices with one multi-edge typedef boost::graph_traits::vertex_descriptor vertex_descriptor; - typedef boost::graph_traits::edge_descriptor edge_descriptor; edge_t edges[] = {{0, 1}, {1, 2}, {1, 2}, {2, 0}}; weight_type ws[] = {3, 1, 1, 1}; @@ -104,9 +97,6 @@ BOOST_AUTO_TEST_CASE(test1) // example by Daniel Trebbien BOOST_AUTO_TEST_CASE(test2) { - typedef boost::graph_traits::vertex_descriptor vertex_descriptor; - typedef boost::graph_traits::edge_descriptor edge_descriptor; - edge_t edges[] = {{5, 2}, {0, 6}, {5, 6}, {3, 1}, {0, 1}, {6, 3}, {4, 6}, {2, 4}, {5, 3}}; weight_type ws[] = {1, 3, 4, 6, 4, 1, 2, 5, 2}; @@ -129,9 +119,6 @@ BOOST_AUTO_TEST_CASE(test2) // example by Daniel Trebbien BOOST_AUTO_TEST_CASE(test3) { - typedef boost::graph_traits::vertex_descriptor vertex_descriptor; - typedef boost::graph_traits::edge_descriptor edge_descriptor; - edge_t edges[] = {{3, 4}, {3, 6}, {3, 5}, {0, 4}, {0, 1}, {0, 6}, {0, 7}, {0, 5}, {0, 2}, {4, 1}, {1, 6}, {1, 5}, {6, 7}, {7, 5}, {5, 2}, {3, 4}}; weight_type ws[] = {0, 3, 1, 3, 1, 2, 6, 1, 8, 1, 1, 80, 2, 1, 1, 4}; @@ -196,7 +183,6 @@ BOOST_AUTO_TEST_CASE(test4) BOOST_AUTO_TEST_CASE(test_prgen_20_70_2) { typedef boost::graph_traits::vertex_descriptor vertex_descriptor; - typedef boost::graph_traits::edge_descriptor edge_descriptor; std::ifstream ifs((test_dir + "/prgen_input_graphs/prgen_20_70_2.net").c_str()); undirected_graph g; @@ -221,7 +207,6 @@ BOOST_AUTO_TEST_CASE(test_prgen_20_70_2) BOOST_AUTO_TEST_CASE(test_prgen_50_40_2) { typedef boost::graph_traits::vertex_descriptor vertex_descriptor; - typedef boost::graph_traits::edge_descriptor edge_descriptor; std::ifstream ifs((test_dir + "/prgen_input_graphs/prgen_50_40_2.net").c_str()); undirected_graph g; @@ -239,7 +224,6 @@ BOOST_AUTO_TEST_CASE(test_prgen_50_40_2) BOOST_AUTO_TEST_CASE(test_prgen_50_70_2) { typedef boost::graph_traits::vertex_descriptor vertex_descriptor; - typedef boost::graph_traits::edge_descriptor edge_descriptor; std::ifstream ifs((test_dir + "/prgen_input_graphs/prgen_50_70_2.net").c_str()); undirected_graph g; diff --git a/test/subgraph.cpp b/test/subgraph.cpp index d0154a314..b1dcdb59f 100644 --- a/test/subgraph.cpp +++ b/test/subgraph.cpp @@ -27,7 +27,6 @@ int test_main(int, char*[]) > graph_t; typedef subgraph subgraph_t; typedef graph_traits::vertex_descriptor vertex_t; - typedef graph_traits::edge_descriptor edge_t; mt19937 gen; for (int t = 0; t < 100; t += 5) { diff --git a/test/test_properties.hpp b/test/test_properties.hpp index adeb9ae10..2d71b9b28 100644 --- a/test/test_properties.hpp +++ b/test/test_properties.hpp @@ -17,9 +17,6 @@ void test_graph_bundle(Graph& g, boost::mpl::true_) { using namespace boost; std::cout << "...test_graph_bundle\n"; - typedef typename graph_property_type::type Property; - typedef typename graph_bundle_type::type Bundle; - GraphBundle& b1 = g[graph_bundle]; GraphBundle& b2 = get_property(g); ignore(b1); ignore(b2); diff --git a/test/tiernan_all_cycles.cpp b/test/tiernan_all_cycles.cpp index 39f8af84e..0e77c784c 100644 --- a/test/tiernan_all_cycles.cpp +++ b/test/tiernan_all_cycles.cpp @@ -27,8 +27,6 @@ struct cycle_validator void cycle(const Path& p, const Graph& g) { ++cycles; - typedef typename graph_traits::vertex_descriptor Vertex; - typedef typename graph_traits::edge_descriptor Edge; // Check to make sure that each of the vertices in the path // is truly connected and that the back is connected to the // front - it's not validating that we find all paths, just From 130f7129c3a2c35610c664fa6e4208ed667ce581 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Wed, 14 Aug 2013 15:34:02 +0000 Subject: [PATCH 295/333] Added MSSP support for non-named parameter versions [SVN r85348] --- .../boost/graph/dijkstra_shortest_paths.hpp | 138 +++++++++++++++--- 1 file changed, 120 insertions(+), 18 deletions(-) diff --git a/include/boost/graph/dijkstra_shortest_paths.hpp b/include/boost/graph/dijkstra_shortest_paths.hpp index 45bac7df3..fa7e76cd6 100644 --- a/include/boost/graph/dijkstra_shortest_paths.hpp +++ b/include/boost/graph/dijkstra_shortest_paths.hpp @@ -256,14 +256,14 @@ namespace boost { } // Call breadth first search with default color map. - template inline void dijkstra_shortest_paths_no_init (const Graph& g, - typename graph_traits::vertex_descriptor s, + SourceInputIter s_begin, SourceInputIter s_end, PredecessorMap predecessor, DistanceMap distance, WeightMap weight, IndexMap index_map, Compare compare, Combine combine, DistZero zero, @@ -275,16 +275,16 @@ namespace boost { typedef typename ColorMapHelper::type ColorMap; ColorMap color = ColorMapHelper::build(g, index_map); - dijkstra_shortest_paths_no_init( g, s, predecessor, distance, weight, + dijkstra_shortest_paths_no_init( g, s_begin, s_end, predecessor, distance, weight, index_map, compare, combine, zero, vis, color); } - // Call breadth first search + // Call breadth first search with default color map. template + class DistZero> inline void dijkstra_shortest_paths_no_init (const Graph& g, @@ -292,6 +292,25 @@ namespace boost { PredecessorMap predecessor, DistanceMap distance, WeightMap weight, IndexMap index_map, Compare compare, Combine combine, DistZero zero, + DijkstraVisitor vis) + { + dijkstra_shortest_paths_no_init(g, &s, &s + 1, predecessor, distance, + weight, index_map, compare, combine, zero, + vis); + } + + // Call breadth first search + template + inline void + dijkstra_shortest_paths_no_init + (const Graph& g, + SourceInputIter s_begin, SourceInputIter s_end, + PredecessorMap predecessor, DistanceMap distance, WeightMap weight, + IndexMap index_map, + Compare compare, Combine combine, DistZero zero, DijkstraVisitor vis, ColorMap color) { typedef indirect_cmp IndirectCmp; @@ -309,7 +328,7 @@ namespace boost { PredecessorMap, DistanceMap, Combine, Compare> bfs_vis(vis, Q, weight, predecessor, distance, combine, compare, zero); - breadth_first_visit(g, s, Q, bfs_vis, color); + breadth_first_visit(g, s_begin, s_end, Q, bfs_vis, color); return; } #endif // BOOST_GRAPH_DIJKSTRA_TESTING @@ -334,11 +353,30 @@ namespace boost { PredecessorMap, DistanceMap, Combine, Compare> bfs_vis(vis, Q, weight, predecessor, distance, combine, compare, zero); - breadth_first_visit(g, s, Q, bfs_vis, color); + breadth_first_visit(g, s_begin, s_end, Q, bfs_vis, color); + } + + // Call breadth first search + template + inline void + dijkstra_shortest_paths_no_init + (const Graph& g, + typename graph_traits::vertex_descriptor s, + PredecessorMap predecessor, DistanceMap distance, WeightMap weight, + IndexMap index_map, + Compare compare, Combine combine, DistZero zero, + DijkstraVisitor vis, ColorMap color) + { + dijkstra_shortest_paths_no_init(g, &s, &s + 1, predecessor, distance, + weight, index_map, compare, combine, + zero, vis, color); } // Initialize distances and call breadth first search with default color map - template ::vertex_descriptor s, + SourceInputIter s_begin, SourceInputIter s_end, PredecessorMap predecessor, DistanceMap distance, WeightMap weight, IndexMap index_map, Compare compare, Combine combine, DistInf inf, DistZero zero, @@ -355,16 +393,17 @@ namespace boost { BOOST_GRAPH_ENABLE_IF_MODELS_PARM(VertexListGraph,vertex_list_graph_tag)) { boost::two_bit_color_map color(num_vertices(g), index_map); - dijkstra_shortest_paths(g, s, predecessor, distance, weight, index_map, - compare, combine, inf, zero, vis, + dijkstra_shortest_paths(g, s_begin, s_end, predecessor, distance, weight, + index_map, compare, combine, inf, zero, vis, color); } - // Initialize distances and call breadth first search + // Initialize distances and call breadth first search with default color map template + class DistInf, class DistZero, typename T, typename Tag, + typename Base> inline void dijkstra_shortest_paths (const VertexListGraph& g, @@ -372,6 +411,26 @@ namespace boost { PredecessorMap predecessor, DistanceMap distance, WeightMap weight, IndexMap index_map, Compare compare, Combine combine, DistInf inf, DistZero zero, + DijkstraVisitor vis, + const bgl_named_params& + BOOST_GRAPH_ENABLE_IF_MODELS_PARM(VertexListGraph,vertex_list_graph_tag)) + { + dijkstra_shortest_paths(g, &s, &s + 1, predecessor, distance, weight, + index_map, compare, combine, inf, zero, vis); + } + + // Initialize distances and call breadth first search + template + inline void + dijkstra_shortest_paths + (const VertexListGraph& g, + SourceInputIter s_begin, SourceInputIter s_end, + PredecessorMap predecessor, DistanceMap distance, WeightMap weight, + IndexMap index_map, + Compare compare, Combine combine, DistInf inf, DistZero zero, DijkstraVisitor vis, ColorMap color) { typedef typename property_traits::value_type ColorValue; @@ -383,17 +442,20 @@ namespace boost { put(predecessor, *ui, *ui); put(color, *ui, Color::white()); } - put(distance, s, zero); + for (SourceInputIter it = s_begin; it != s_end; ++it) { + put(distance, *it, zero); + } - dijkstra_shortest_paths_no_init(g, s, predecessor, distance, weight, - index_map, compare, combine, zero, vis, color); + dijkstra_shortest_paths_no_init(g, s_begin, s_end, predecessor, distance, + weight, index_map, compare, combine, zero, vis, + color); } // Initialize distances and call breadth first search template + class DistInf, class DistZero, class ColorMap> inline void dijkstra_shortest_paths (const VertexListGraph& g, @@ -401,13 +463,53 @@ namespace boost { PredecessorMap predecessor, DistanceMap distance, WeightMap weight, IndexMap index_map, Compare compare, Combine combine, DistInf inf, DistZero zero, + DijkstraVisitor vis, ColorMap color) + { + dijkstra_shortest_paths(g, &s, &s + 1, predecessor, distance, weight, + index_map, compare, combine, inf, zero, + vis, color); + } + + // Initialize distances and call breadth first search + template + inline void + dijkstra_shortest_paths + (const VertexListGraph& g, + SourceInputIter s_begin, SourceInputIter s_end, + PredecessorMap predecessor, DistanceMap distance, WeightMap weight, + IndexMap index_map, + Compare compare, Combine combine, DistInf inf, DistZero zero, DijkstraVisitor vis) { - dijkstra_shortest_paths(g, s, predecessor, distance, weight, index_map, + dijkstra_shortest_paths(g, s_begin, s_end, predecessor, distance, + weight, index_map, compare, combine, inf, zero, vis, no_named_parameters()); } + // Initialize distances and call breadth first search + template + inline void + dijkstra_shortest_paths + (const VertexListGraph& g, + typename graph_traits::vertex_descriptor s, + PredecessorMap predecessor, DistanceMap distance, WeightMap weight, + IndexMap index_map, + Compare compare, Combine combine, DistInf inf, DistZero zero, + DijkstraVisitor vis) + { + dijkstra_shortest_paths(g, &s, &s + 1, predecessor, distance, + weight, index_map, + compare, combine, inf, zero, vis); + } + namespace detail { // Handle defaults for PredecessorMap and From cd267de654c67313ec3b80ec83934b169d928a78 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Sat, 17 Aug 2013 22:12:20 +0000 Subject: [PATCH 296/333] Fixed test for negative-weight edges when combine operator is project2nd (as in prim_minimum_spanning_tree); fixes #9012; refs #8398 [SVN r85386] --- .../boost/graph/dijkstra_shortest_paths.hpp | 36 ++++++++++++++++--- 1 file changed, 32 insertions(+), 4 deletions(-) diff --git a/include/boost/graph/dijkstra_shortest_paths.hpp b/include/boost/graph/dijkstra_shortest_paths.hpp index fa7e76cd6..0015a01e9 100644 --- a/include/boost/graph/dijkstra_shortest_paths.hpp +++ b/include/boost/graph/dijkstra_shortest_paths.hpp @@ -118,6 +118,7 @@ namespace boost { struct dijkstra_bfs_visitor { typedef typename property_traits::value_type D; + typedef typename property_traits::value_type W; dijkstra_bfs_visitor(UniformCostVisitor vis, UpdatableQueue& Q, WeightMap w, PredecessorMap p, DistanceMap d, @@ -159,13 +160,40 @@ namespace boost { void examine_vertex(Vertex u, Graph& g) { m_vis.examine_vertex(u, g); } template void examine_edge(Edge e, Graph& g) { - // Comparison needs to be more complicated because distance and weight - // types may not be the same; see bug 8398 - // (https://svn.boost.org/trac/boost/ticket/8398) + // Test for negative-weight edges: + // + // Reasons that simpler comparisons do not work: + // + // m_compare(e_weight, D(0)): + // m_compare only needs to work on distances, not weights, and those + // types do not need to be the same (bug 8398, + // https://svn.boost.org/trac/boost/ticket/8398). + // m_compare(m_combine(source_dist, e_weight), source_dist): + // if m_combine is project2nd (as in prim_minimum_spanning_tree), + // this test will claim that the edge weight is negative whenever + // the edge weight is less than source_dist, even if both of those + // are positive (bug 9012, + // https://svn.boost.org/trac/boost/ticket/9012). + // m_compare(m_combine(e_weight, source_dist), source_dist): + // would fix project2nd issue, but documentation only requires that + // m_combine be able to take a distance and a weight (in that order) + // and return a distance. + D source_dist = get(m_distance, source(e, g)); - if (m_compare(m_combine(source_dist, get(m_weight, e)), source_dist)) + W e_weight = get(m_weight, e); + // sd_plus_ew = source_dist + e_weight. + D sd_plus_ew = m_combine(source_dist, e_weight); + // sd_plus_2ew = source_dist + 2 * e_weight. + D sd_plus_2ew = m_combine(sd_plus_ew, e_weight); + // The test here is equivalent to e_weight < 0 if m_combine has a + // cancellation law, but always returns false when m_combine is a + // projection operator or is idempotent. + if (m_compare(sd_plus_2ew, sd_plus_ew)) boost::throw_exception(negative_edge()); + // End of test for negative-weight edges. + m_vis.examine_edge(e, g); + } template void black_target(Edge, Graph&) { } From d983ea89a5ff2080a12c491df62b9354e4b2395b Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Sat, 17 Aug 2013 22:21:16 +0000 Subject: [PATCH 297/333] Simplified negative-edge test; refs #9012 [SVN r85387] --- include/boost/graph/dijkstra_shortest_paths.hpp | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/include/boost/graph/dijkstra_shortest_paths.hpp b/include/boost/graph/dijkstra_shortest_paths.hpp index 0015a01e9..10e40f828 100644 --- a/include/boost/graph/dijkstra_shortest_paths.hpp +++ b/include/boost/graph/dijkstra_shortest_paths.hpp @@ -162,7 +162,7 @@ namespace boost { void examine_edge(Edge e, Graph& g) { // Test for negative-weight edges: // - // Reasons that simpler comparisons do not work: + // Reasons that other comparisons do not work: // // m_compare(e_weight, D(0)): // m_compare only needs to work on distances, not weights, and those @@ -179,16 +179,15 @@ namespace boost { // m_combine be able to take a distance and a weight (in that order) // and return a distance. - D source_dist = get(m_distance, source(e, g)); - W e_weight = get(m_weight, e); + // W e_weight = get(m_weight, e); // sd_plus_ew = source_dist + e_weight. - D sd_plus_ew = m_combine(source_dist, e_weight); + // D sd_plus_ew = m_combine(source_dist, e_weight); // sd_plus_2ew = source_dist + 2 * e_weight. - D sd_plus_2ew = m_combine(sd_plus_ew, e_weight); + // D sd_plus_2ew = m_combine(sd_plus_ew, e_weight); // The test here is equivalent to e_weight < 0 if m_combine has a // cancellation law, but always returns false when m_combine is a - // projection operator or is idempotent. - if (m_compare(sd_plus_2ew, sd_plus_ew)) + // projection operator. + if (m_compare(m_combine(m_zero, get(m_weight, e)), m_zero)) boost::throw_exception(negative_edge()); // End of test for negative-weight edges. From 5ba855f46ee142121385eeaa323104138d285e8f Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Mon, 26 Aug 2013 04:11:49 +0000 Subject: [PATCH 298/333] Removed use of "void" as property type to avoid errors in Clang; added static assertion to prevent this use in the future (it is broken anyway) [SVN r85472] --- include/boost/graph/compressed_sparse_row_graph.hpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/include/boost/graph/compressed_sparse_row_graph.hpp b/include/boost/graph/compressed_sparse_row_graph.hpp index de3234a04..7b91d4d6c 100644 --- a/include/boost/graph/compressed_sparse_row_graph.hpp +++ b/include/boost/graph/compressed_sparse_row_graph.hpp @@ -192,6 +192,11 @@ class compressed_sparse_row_graph > inherited_vertex_properties; + // Some tests to prevent use of "void" is a property type (as was done in some test cases): + BOOST_STATIC_ASSERT((!is_same::value)); + BOOST_STATIC_ASSERT((!is_same::value)); + BOOST_STATIC_ASSERT((!is_same::value)); + public: // For Property Graph typedef GraphProperty graph_property_type; From 01a683d8cef35f0f58e7cba2bb5dec2fa91d9a7b Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Sat, 31 Aug 2013 19:29:22 +0000 Subject: [PATCH 299/333] Added Hawick circuits code from Louis Dionne; fixes #8433 [SVN r85533] --- doc/hawick_circuits.html | 58 ++++ doc/hawick_circuits.md | 53 ++++ doc/table_of_contents.html | 9 +- example/Jamfile.v2 | 1 + example/hawick_circuits.cpp | 96 ++++++ include/boost/graph/hawick_circuits.hpp | 381 ++++++++++++++++++++++++ test/Jamfile.v2 | 1 + test/cycle_test.hpp | 80 +++++ test/hawick_circuits.cpp | 32 ++ 9 files changed, 707 insertions(+), 4 deletions(-) create mode 100644 doc/hawick_circuits.html create mode 100644 doc/hawick_circuits.md create mode 100644 example/hawick_circuits.cpp create mode 100644 include/boost/graph/hawick_circuits.hpp create mode 100644 test/cycle_test.hpp create mode 100644 test/hawick_circuits.cpp diff --git a/doc/hawick_circuits.html b/doc/hawick_circuits.html new file mode 100644 index 000000000..5fabcf7c5 --- /dev/null +++ b/doc/hawick_circuits.html @@ -0,0 +1,58 @@ +

    + +

    C++ Boost

    + +

    hawick_circuits

    + +
    template <typename Graph, typename Visitor, typename VertexIndexMap>
    +void hawick_circuits(Graph const& graph, Visitor visitor, VertexIndexMap const& vim = get(vertex_index, graph));
    +
    +template <typename Graph, typename Visitor, typename VertexIndexMap>
    +void hawick_unique_circuits(Graph const& graph, Visitor visitor, VertexIndexMap const& vim = get(vertex_index, graph));
    +
    + +

    Enumerate all the elementary circuits in a directed multigraph. Specifically, +self-loops and redundant circuits caused by parallel edges are enumerated too. +hawick_unique_circuits may be used if redundant circuits caused by parallel +edges are not desired.

    + +

    The algorithm is described in detail in +http://www.massey.ac.nz/~kahawick/cstn/013/cstn-013.pdf.

    + +

    Where defined

    + +

    #include <boost/graph/hawick_circuits.hpp>

    + +

    Parameters

    + +

    IN: Graph const& graph

    + +
    +

    The graph on which the algorithm is to be performed. It must be a model of + the VertexListGraph and AdjacencyGraph concepts.

    +
    + +

    IN: Visitor visitor

    + +
    +

    The visitor that will be notified on each circuit found by the algorithm. + The visitor.cycle(circuit, graph) expression must be valid, with circuit + being a const-reference to a random access sequence of vertex_descriptors.

    + +

    For example, if a circuit u -> v -> w -> u exists in the graph, the + visitor will be called with a sequence consisting of (u, v, w).

    +
    + +

    IN: VertexIndexMap const& vim = get(vertex_index, graph)

    + +
    +

    A model of the ReadablePropertyMap concept mapping each vertex_descriptor + to an integer in the range [0, num_vertices(graph)). It defaults to using + the vertex index map provided by the graph.

    +
    + +
    + + diff --git a/doc/hawick_circuits.md b/doc/hawick_circuits.md new file mode 100644 index 000000000..828a71b9c --- /dev/null +++ b/doc/hawick_circuits.md @@ -0,0 +1,53 @@ + + +![C++ Boost](../../../boost.png) + +# `hawick_circuits` + + template + void hawick_circuits(Graph const& graph, Visitor visitor, VertexIndexMap const& vim = get(vertex_index, graph)); + + template + void hawick_unique_circuits(Graph const& graph, Visitor visitor, VertexIndexMap const& vim = get(vertex_index, graph)); + +Enumerate all the elementary circuits in a directed multigraph. Specifically, +self-loops and redundant circuits caused by parallel edges are enumerated too. +`hawick_unique_circuits` may be used if redundant circuits caused by parallel +edges are not desired. + +The algorithm is described in detail in +. + + +### Where defined + +[`#include `](../../../boost/graph/hawick_circuits.hpp) + + +### Parameters + +__IN:__ `Graph const& graph` + +> The graph on which the algorithm is to be performed. It must be a model of +> the `VertexListGraph` and `AdjacencyGraph` concepts. + +__IN:__ `Visitor visitor` + +> The visitor that will be notified on each circuit found by the algorithm. +> The `visitor.cycle(circuit, graph)` expression must be valid, with `circuit` +> being a `const`-reference to a random access sequence of `vertex_descriptor`s. +> +> For example, if a circuit `u -> v -> w -> u` exists in the graph, the +> visitor will be called with a sequence consisting of `(u, v, w)`. + +__IN:__ `VertexIndexMap const& vim = get(vertex_index, graph)` + +> A model of the `ReadablePropertyMap` concept mapping each `vertex_descriptor` +> to an integer in the range `[0, num_vertices(graph))`. It defaults to using +> the vertex index map provided by the `graph`. + + +------------------------------------------------------------------------------ + diff --git a/doc/table_of_contents.html b/doc/table_of_contents.html index 0fd36e8e2..a2f5edf1a 100644 --- a/doc/table_of_contents.html +++ b/doc/table_of_contents.html @@ -284,10 +284,11 @@

    Table of Contents: the Boost Graph Library
    1. metric_tsp_approx
    2. sequential_vertex_coloring
    3. +
    4. edge_coloring
    5. is_bipartite (including two-coloring of bipartite graphs)
    6. find_odd_cycle
    7. maximum_adjacency_search
    8. diff --git a/example/Jamfile.v2 b/example/Jamfile.v2 index e2b45201a..e85664977 100644 --- a/example/Jamfile.v2 +++ b/example/Jamfile.v2 @@ -51,4 +51,5 @@ exe vf2_sub_graph_iso_example : vf2_sub_graph_iso_example.cpp ; exe vf2_sub_graph_iso_multi_example : vf2_sub_graph_iso_multi_example.cpp ; exe sloan_ordering : sloan_ordering.cpp ; exe hawick_circuits : hawick_circuits.cpp ; +exe edge_coloring : edge_coloring.cpp ; diff --git a/example/edge_coloring.cpp b/example/edge_coloring.cpp new file mode 100644 index 000000000..81a8a38da --- /dev/null +++ b/example/edge_coloring.cpp @@ -0,0 +1,70 @@ +//======================================================================= +// Copyright 2013 Maciej Piechotka +// Authors: Maciej Piechotka +// +// 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) +//======================================================================= + +#include +#include +#include +#include + +/* + Sample output + Colored using 5 colors + a-d: 4 + a-f: 0 + b-c: 2 + b-e: 3 + b-g: 1 + b-j: 0 + c-d: 0 + c-e: 1 + d-f: 2 + d-i: 1 + e-g: 4 + f-g: 3 + f-h: 1 + g-h: 0 +*/ + +int main(int, char *[]) +{ + using namespace boost; + using namespace std; + typedef adjacency_list Graph; + + typedef std::pair Pair; + Pair edges[14] = { Pair(0,3), //a-d + Pair(0,5), //a-f + Pair(1,2), //b-c + Pair(1,4), //b-e + Pair(1,6), //b-g + Pair(1,9), //b-j + Pair(2,3), //c-d + Pair(2,4), //c-e + Pair(3,5), //d-f + Pair(3,8), //d-i + Pair(4,6), //e-g + Pair(5,6), //f-g + Pair(5,7), //f-h + Pair(6,7) }; //g-h + + Graph G(10); + + for (size_t i = 0; i < sizeof(edges)/sizeof(edges[0]); i++) + add_edge(edges[i].first, edges[i].second, G).first; + + size_t colors = edge_coloring(G, get(edge_bundle, G)); + + cout << "Colored using " << colors << " colors" << endl; + for (size_t i = 0; i < sizeof(edges)/sizeof(edges[0]); i++) { + cout << " " << (char)('a' + edges[i].first) << "-" << (char)('a' + edges[i].second) << ": " << G[edge(edges[i].first, edges[i].second, G).first] << endl; + } + + return 0; +} + diff --git a/include/boost/graph/edge_coloring.hpp b/include/boost/graph/edge_coloring.hpp new file mode 100644 index 000000000..8eb79ad43 --- /dev/null +++ b/include/boost/graph/edge_coloring.hpp @@ -0,0 +1,196 @@ +//======================================================================= +// Copyright 2013 Maciej Piechotka +// Authors: Maciej Piechotka +// +// 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_GRAPH_EDGE_COLORING_HPP +#define BOOST_GRAPH_EDGE_COLORING_HPP + +#include +#include +#include +#include +#include +#include + +/* This algorithm is to find coloring of an edges + + Reference: + + Misra, J., & Gries, D. (1992). A constructive proof of Vizing's + theorem. In Information Processing Letters. +*/ + +namespace boost { + namespace detail { + template + bool + is_free(const Graph &g, + ColorMap color, + typename boost::graph_traits::vertex_descriptor u, + typename boost::property_traits::value_type free_color) + { + typedef typename boost::property_traits::value_type color_t; + if (free_color == (std::numeric_limits::max)()) + return false; + BGL_FORALL_OUTEDGES_T(u, e, g, Graph) { + if (get(color, e) == free_color) { + return false; + } + } + return true; + } + + template + std::vector::vertex_descriptor> + maximal_fan(const Graph &g, + ColorMap color, + typename boost::graph_traits::vertex_descriptor x, + typename boost::graph_traits::vertex_descriptor y) + { + typedef typename boost::graph_traits::vertex_descriptor vertex_t; + std::vector fan; + fan.push_back(y); + bool extended; + do { + extended = false; + BGL_FORALL_OUTEDGES_T(x, e, g, Graph) { + vertex_t v = target(e, g); + if (is_free(g, color, fan.back(), get(color, e)) && + std::find(fan.begin(), fan.end(), v) == fan.end()) { + fan.push_back(v); + extended = true; + } + } + } while(extended); + return fan; + } + template + typename boost::property_traits::value_type + find_free_color(const Graph &g, + ColorMap color, + typename boost::graph_traits::vertex_descriptor u) + { + typename boost::property_traits::value_type c = 0; + while (!is_free(g, color, u, c)) c++; + return c; + } + + template + void + invert_cd_path(const Graph &g, + ColorMap color, + typename boost::graph_traits::vertex_descriptor x, + typename boost::graph_traits::edge_descriptor eold, + typename boost::property_traits::value_type c, + typename boost::property_traits::value_type d) + { + put(color, eold, d); + BGL_FORALL_OUTEDGES_T(x, e, g, Graph) { + if (get(color, e) == d && e != eold) { + invert_cd_path(g, color, target(e, g), e, d, c); + return; + } + } + } + + template + void + invert_cd_path(const Graph &g, + ColorMap color, + typename boost::graph_traits::vertex_descriptor x, + typename boost::property_traits::value_type c, + typename boost::property_traits::value_type d) + { + BGL_FORALL_OUTEDGES_T(x, e, g, Graph) { + if (get(color, e) == d) { + invert_cd_path(g, color, target(e, g), e, d, c); + return; + } + } + } + + template + void + rotate_fan(const Graph &g, + ColorMap color, + typename boost::graph_traits::vertex_descriptor x, + ForwardIterator begin, + ForwardIterator end) + { + typedef typename boost::graph_traits::edge_descriptor edge_t; + if (begin == end) { + return; + } + edge_t previous = edge(x, *begin, g).first; + for (begin++; begin != end; begin++) { + edge_t current = edge(x, *begin, g).first; + put(color, previous, get(color, current)); + previous = current; + } + } + + template + class find_free_in_fan + { + public: + find_free_in_fan(const Graph &graph, + const ColorMap color, + typename boost::property_traits::value_type d) + : graph(graph), + color(color), + d(d) {} + bool operator()(const typename boost::graph_traits::vertex_descriptor u) const { + return is_free(graph, color, u, d); + } + private: + const Graph &graph; + const ColorMap color; + const typename boost::property_traits::value_type d; + }; + } + + template + typename boost::property_traits::value_type + color_edge(const Graph &g, + ColorMap color, + typename boost::graph_traits::edge_descriptor e) + { + typedef typename boost::graph_traits::vertex_descriptor vertex_t; + typedef typename boost::property_traits::value_type color_t; + typedef typename std::vector::iterator fan_iterator; + using namespace detail; + vertex_t x = source(e, g), y = target(e, g); + std::vector fan = maximal_fan(g, color, x, y); + color_t c = find_free_color(g, color, x); + color_t d = find_free_color(g, color, fan.back()); + invert_cd_path(g, color, x, c, d); + fan_iterator w = std::find_if(fan.begin(), + fan.end(), + find_free_in_fan(g, color, d)); + rotate_fan(g, color, x, fan.begin(), w + 1); + put(color, edge(x, *w, g).first, d); + return (std::max)(c, d); + } + + template + typename boost::property_traits::value_type + edge_coloring(const Graph &g, + ColorMap color) + { + typedef typename boost::property_traits::value_type color_t; + BGL_FORALL_EDGES_T(e, g, Graph) { + put(color, e, (std::numeric_limits::max)()); + } + color_t colors = 0; + BGL_FORALL_EDGES_T(e, g, Graph) { + colors = (std::max)(colors, color_edge(g, color, e) + 1); + } + return colors; + } +} + +#endif From 915b70ec05c6acc58f98c021c81d2785255f9cca Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Sat, 31 Aug 2013 20:09:11 +0000 Subject: [PATCH 301/333] Added min_cost_max_flow code from Piotr Wygocki [SVN r85536] --- doc/cycle_canceling.html | 223 +++++++++++++++ doc/find_flow_cost.html | 139 +++++++++ doc/graph_theory_review.html | 3 + doc/successive_shortest_path.html | 264 ++++++++++++++++++ example/Jamfile.v2 | 2 + example/cycle_canceling_example.cpp | 19 ++ example/successive_shortest_path_example.cpp | 21 ++ include/boost/graph/cycle_canceling.hpp | 181 ++++++++++++ include/boost/graph/detail/augment.hpp | 63 +++++ include/boost/graph/find_flow_cost.hpp | 52 ++++ include/boost/graph/named_function_params.hpp | 1 + .../boost/graph/successive_shortest_path.hpp | 261 +++++++++++++++++ test/Jamfile.v2 | 2 + test/cycle_canceling_test.cpp | 51 ++++ test/min_cost_max_flow_utils.hpp | 128 +++++++++ test/successive_shortest_path_test.cpp | 55 ++++ 16 files changed, 1465 insertions(+) create mode 100644 doc/cycle_canceling.html create mode 100644 doc/find_flow_cost.html create mode 100644 doc/successive_shortest_path.html create mode 100644 example/cycle_canceling_example.cpp create mode 100644 example/successive_shortest_path_example.cpp create mode 100644 include/boost/graph/cycle_canceling.hpp create mode 100644 include/boost/graph/detail/augment.hpp create mode 100644 include/boost/graph/find_flow_cost.hpp create mode 100644 include/boost/graph/successive_shortest_path.hpp create mode 100644 test/cycle_canceling_test.cpp create mode 100644 test/min_cost_max_flow_utils.hpp create mode 100644 test/successive_shortest_path_test.cpp diff --git a/doc/cycle_canceling.html b/doc/cycle_canceling.html new file mode 100644 index 000000000..459a2e2b2 --- /dev/null +++ b/doc/cycle_canceling.html @@ -0,0 +1,223 @@ + + + +Boost Graph Library: Cycle Canceling for Min Cost Max Flow + +C++ Boost + +
      + +

      +cycle_canceling +

      + +
      +// named parameter version
      +template <class Graph, class P, class T, class R>
      +void cycle_canceling(
      +        Graph &g, 
      +        const bgl_named_params<P, T, R> & params  = all defaults)
      +
      +// non-named parameter version
      +template <class Graph, class Pred, class Distance, class Reversed, class ResidualCapacity, class Weight>
      +void cycle_canceling(const Graph & g, Weight weight, Reversed rev, ResidualCapacity residual_capacity, Pred pred, Distance distance) 
      +
      + +

      +The cycle_canceling() function calculates the minimum cost flow of a network with given flow. See Section Network +Flow Algorithms for a description of maximum flow. +For given flow values f(u,v) function minimizes flow cost in such a way, that for each v in V the + sum u in V f(v,u) is preserved. Particularly if the input flow was the maximum flow, the function produces min cost max flow. + + + The function calculates the flow values f(u,v) for all (u,v) in +E, which are returned in the form of the residual capacity +r(u,v) = c(u,v) - f(u,v). + +

      +There are several special requirements on the input graph and property +map parameters for this algorithm. First, the directed graph +G=(V,E) that represents the network must be augmented to +include the reverse edge for every edge in E. That is, the +input graph should be Gin = (V,{E U +ET}). The ReverseEdgeMap argument rev +must map each edge in the original graph to its reverse edge, that is +(u,v) -> (v,u) for all (u,v) in E. +The WeightMap has to map each edge from ET to -weight of its reversed edge. +Note that edges from E can have negative weights. +

      +If weights in the graph are nonnegative, the +successive_shortest_path() +might be better choice for min cost max flow. + +

      +The algorithm is described in Network Flows. + +

      +In each round algorithm augments the negative cycle (in terms of weight) in the residual graph. +If there is no negative cycle in the network, the cost is optimized. + +

      +Note that, although we mention capacity in the problem description, the actual algorithm doesn't have to now it. + +

      +In order to find the cost of the result flow use: +find_flow_cost(). + + +

      Where Defined

      + +

      +boost/graph/successive_shortest_path.hpp + +

      + +

      Parameters

      + +IN: Graph& g +
      + A directed graph. The + graph's type must be a model of VertexListGraph and IncidenceGraph For each edge + (u,v) in the graph, the reverse edge (v,u) must also + be in the graph. +
      + +

      Named Parameters

      + + +IN/OUT: residual_capacity_map(ResidualCapacityEdgeMap res) +
      + This maps edges to their residual capacity. The type must be a model + of a mutable Lvalue Property + Map. The key type of the map must be the graph's edge descriptor + type.
      + Default: get(edge_residual_capacity, g) +
      + +IN: reverse_edge_map(ReverseEdgeMap rev) +
      + An edge property map that maps every edge (u,v) in the graph + to the reverse edge (v,u). The map must be a model of + constant Lvalue + Property Map. The key type of the map must be the graph's edge + descriptor type.
      + Default: get(edge_reverse, g) +
      + +IN: weight_map(WeightMap w) +
      + The weight (also know as ``length'' or ``cost'') of each edge in the + graph. The WeightMap type must be a model of Readable Property + Map. The key type for this property map must be the edge + descriptor of the graph. The value type for the weight map must be + Addable with the distance map's value type.
      + Default: get(edge_weight, g)
      +
      + +UTIL: predecessor_map(PredEdgeMap pred) +
      + Use by the algorithm to store augmenting paths. The map must be a + model of mutable Lvalue Property Map. + The key type must be the graph's vertex descriptor type and the + value type must be the graph's edge descriptor type.
      + + Default: an + iterator_property_map created from a std::vector + of edge descriptors of size num_vertices(g) and + using the i_map for the index map. +
      + +UTIL: distance_map(DistanceMap d_map) +
      + The shortest path weight from the source vertex s to each + vertex in the graph g is recorded in this property map. The + shortest path weight is the sum of the edge weights along the + shortest path. The type DistanceMap must be a model of Read/Write + Property Map. The vertex descriptor type of the graph needs to + be usable as the key type of the distance map. + + Default: + iterator_property_map created from a + std::vector of the WeightMap's value type of size + num_vertices(g) and using the i_map for the index + map.
      + +
      + +IN: vertex_index_map(VertexIndexMap i_map) +
      + Maps each vertex of the graph to a unique integer in the range + [0, num_vertices(g)). This property map is only needed + if the default for the distance or predecessor map is used. + The vertex index map must be a model of Readable Property + Map. The key type of the map must be the graph's vertex + descriptor type.
      + Default: get(vertex_index, g) + Note: if you use this default, make sure your graph has + an internal vertex_index property. For example, + adjacenty_list with VertexList=listS does + not have an internal vertex_index property. +
      + +

      Complexity

      +In the integer capacity and weight case, if C is the initial cost of the flow, then the complexity is O(C * |V| * |E|), +where O(|E|* |V|) is the complexity of the bellman ford shortest paths algorithm and C is upper bound on number of iteration. +In many real world cases number of iterations is much smaller than C. + + +

      Example

      + +The program in example/cycle_canceling_example.cpp. + + +

      See Also

      + +successive_shortest_path()
      +find_flow_cost(). + +
      +
      + + +
      Copyright © 2013 +Piotr Wygocki, University of Warsaw (wygos at mimuw.edu.pl) +
      + + + + + + + + + + + + diff --git a/doc/find_flow_cost.html b/doc/find_flow_cost.html new file mode 100644 index 000000000..94f9c045e --- /dev/null +++ b/doc/find_flow_cost.html @@ -0,0 +1,139 @@ + + + +Boost Graph Library: Find Flow Cost + +C++ Boost + +
      + +

      +find_flow_cost +

      + +
      +// named parameter version
      +template <class Graph>
      +typename property_traits<typename property_map < Graph, edge_capacity_t >::type>::value_type
      +find_flow_cost(const Graph & g,
      +        const bgl_named_params<P, T, R> & params  = all defaults)
      +
      +// non-named parameter version
      +template<class Graph, class Capacity, class ResidualCapacity, class Weight>
      +typename property_traits<typename property_map < Graph, edge_capacity_t >::type>::value_type
      +find_flow_cost(const Graph & g, Capacity capacity, ResidualCapacity residual_capacity, Weight weight) 
      +
      + +

      +The find_flow_cost() function calculates the minimum cost maximum flow value of a network and given flow. See Section Network +Flow Algorithms for a description of maximum flow. +The function calculates the cost from the flow values f(u,v) for (u,v) in +E, which are passed in the form of the residual capacity +r(u,v) = c(u,v) - f(u,v). + +

      +In order to compute the min cost max flow use : +successive_shortest_path() or +cycle_canceling(). + +

      Where Defined

      + +

      +boost/graph/successive_shortest_path.hpp + +

      + +

      Parameters

      + +IN: const Graph& g +
      + A directed graph. The + graph's type must be a model of VertexListGraph and IncidenceGraph For each edge + (u,v) in the graph, the reverse edge (v,u) must also + be in the graph. +
      +

      Named Parameters

      + + +IN: capacity_map(CapacityEdgeMap cap) +
      + The edge capacity property map. The type must be a model of a + constant Lvalue Property Map. The + key type of the map must be the graph's edge descriptor type.
      + Default: get(edge_capacity, g) +
      + +IN: residual_capacity_map(ResidualCapacityEdgeMap res) +
      + This maps edges to their residual capacity. The type must be a model + of a mutable Lvalue Property + Map. The key type of the map must be the graph's edge descriptor + type.
      + Default: get(edge_residual_capacity, g) +
      + + +IN: weight_map(WeightMap w_map) +
      + The weight or ``cost'' of each edge in the graph. + The type WeightMap must be a model of + Readable Property Map. The edge descriptor type of + the graph needs to be usable as the key type for the weight + map. The value type for this map must be + the same as the value type of the distance map.
      + Default: get(edge_weight, g)
      + +
      + +

      Complexity

      +The complexity is O(|E|), + +

      Example

      + +The function is used in the successive_shortest_path example. The program in example/successive_shortest_path_example.cpp. + +

      See Also

      + +cycle_canceling()
      +successive_shortest_path(). + +
      +
      + + +
      Copyright © 2013 +Piotr Wygocki, University of Warsaw (wygos at mimuw.edu.pl) +
      + + + + + + + + + + + + diff --git a/doc/graph_theory_review.html b/doc/graph_theory_review.html index e811d2979..33a6d2cd2 100644 --- a/doc/graph_theory_review.html +++ b/doc/graph_theory_review.html @@ -552,6 +552,9 @@

      Network Flow Algorithms

      The maximum flow problem is to determine the maximum possible value for |f| and the corresponding flow values for every vertex pair in the graph. +

      +The minimum cost maximum flow problem is to determine the maximum flow which minimizes sum(u,v) in E +cost(u,v) * f(u,v) .

      A flow network is shown in Figure diff --git a/doc/successive_shortest_path.html b/doc/successive_shortest_path.html new file mode 100644 index 000000000..4b403d52a --- /dev/null +++ b/doc/successive_shortest_path.html @@ -0,0 +1,264 @@ + + + +Boost Graph Library: Successive Shortest Path for Min Cost Max Flow + +C++ Boost + +
      + +

      +successive_shortest_path +

      + +
      +// named parameter version
      +template <class Graph, class P, class T, class R>
      +void successive_shortest_path(
      +        Graph &g, 
      +        typename graph_traits<Graph>::vertex_descriptor s, 
      +        typename graph_traits<Graph>::vertex_descriptor t,
      +        const bgl_named_params<P, T, R> & params  = all defaults)
      +
      +// non-named parameter version
      +template <class Graph, class Capacity, class ResidualCapacity, class Reversed, class Pred, class Weight, class Distance, class Distance2, class VertexIndex>
      +void successive_shortest_path(
      +        const Graph & g, 
      +        typename graph_traits<Graph>::vertex_descriptor s, 
      +        typename graph_traits<Graph>::vertex_descriptor t,
      +        Capacity capacity,
      +        ResidualCapacity residual_capacity,
      +        Weight weight, 
      +        Reversed rev,
      +        VertexIndex index,
      +        Pred pred, 
      +        Distance distance,
      +        Distance2 distance_prev) 
      +
      + +

      +The successive_shortest_path() function calculates the minimum cost maximum flow of a network. See Section Network +Flow Algorithms for a description of maximum flow. + The function calculates the flow values f(u,v) for all (u,v) in +E, which are returned in the form of the residual capacity +r(u,v) = c(u,v) - f(u,v). + +

      +There are several special requirements on the input graph and property +map parameters for this algorithm. First, the directed graph +G=(V,E) that represents the network must be augmented to +include the reverse edge for every edge in E. That is, the +input graph should be Gin = (V,{E U +ET}). The ReverseEdgeMap argument rev +must map each edge in the original graph to its reverse edge, that is +(u,v) -> (v,u) for all (u,v) in E. The +CapacityEdgeMap argument cap must map each edge in +E to a positive number, and each edge in ET +to 0. The WeightMap has to map each edge from E to nonnegative number, and each edge from ET to -weight of its reversed edge. + +

      +The algorithm is described in Network Flows. + +

      +This algorithm starts with empty flow and in each round augments the shortest path (in terms of weight) in the residual graph. + +

      +In order to find the cost of the result flow use: +find_flow_cost(). + +

      Where Defined

      + +

      +boost/graph/successive_shortest_path.hpp + +

      + +

      Parameters

      + +IN: Graph& g +
      + A directed graph. The + graph's type must be a model of VertexListGraph and IncidenceGraph For each edge + (u,v) in the graph, the reverse edge (v,u) must also + be in the graph. +
      + +IN: vertex_descriptor s +
      + The source vertex for the flow network graph. +
      + +IN: vertex_descriptor t +
      + The sink vertex for the flow network graph. +
      + +

      Named Parameters

      + + +IN: capacity_map(CapacityEdgeMap cap) +
      + The edge capacity property map. The type must be a model of a + constant Lvalue Property Map. The + key type of the map must be the graph's edge descriptor type.
      + Default: get(edge_capacity, g) +
      + +OUT: residual_capacity_map(ResidualCapacityEdgeMap res) +
      + This maps edges to their residual capacity. The type must be a model + of a mutable Lvalue Property + Map. The key type of the map must be the graph's edge descriptor + type.
      + Default: get(edge_residual_capacity, g) +
      + +IN: reverse_edge_map(ReverseEdgeMap rev) +
      + An edge property map that maps every edge (u,v) in the graph + to the reverse edge (v,u). The map must be a model of + constant Lvalue + Property Map. The key type of the map must be the graph's edge + descriptor type.
      + Default: get(edge_reverse, g) +
      + +IN: weight_map(WeightMap w_map) +
      + The weight or ``cost'' of each edge in the graph. The weights + must all be non-negative, and the algorithm will throw a + negative_edge + exception if one of the edges is negative. + The type WeightMap must be a model of + Readable Property Map. The edge descriptor type of + the graph needs to be usable as the key type for the weight + map. The value type for this map must be + the same as the value type of the distance map.
      + Default: get(edge_weight, g)
      + +
      + +UTIL: predecessor_map(PredEdgeMap pred) +
      + Use by the algorithm to store augmenting paths. The map must be a + model of mutable Lvalue Property Map. + The key type must be the graph's vertex descriptor type and the + value type must be the graph's edge descriptor type.
      + + Default: an + iterator_property_map created from a std::vector + of edge descriptors of size num_vertices(g) and + using the i_map for the index map. +
      + +UTIL: distance_map(DistanceMap d_map) +
      + The shortest path weight from the source vertex s to each + vertex in the graph g is recorded in this property map. The + shortest path weight is the sum of the edge weights along the + shortest path. The type DistanceMap must be a model of Read/Write + Property Map. The vertex descriptor type of the graph needs to + be usable as the key type of the distance map. + + Default: + iterator_property_map created from a + std::vector of the WeightMap's value type of size + num_vertices(g) and using the i_map for the index + map.
      + +
      + +UTIL: distance_map2(DistanceMap2 d_map2) +
      + The shortest path computation in iteration nr k uses distances computed in iteration k. + The type DistanceMap2 must be a model of Read/Write + Property Map. The vertex descriptor type of the graph needs to + be usable as the key type of the distance map. + + Default: + iterator_property_map created from a + std::vector of the WeightMap's value type of size + num_vertices(g) and using the i_map for the index + map.
      + +
      + +IN: vertex_index_map(VertexIndexMap i_map) +
      + Maps each vertex of the graph to a unique integer in the range + [0, num_vertices(g)). This property map is only needed + if the default for the distance or distance2 or predecessor map is used. + The vertex index map must be a model of Readable Property + Map. The key type of the map must be the graph's vertex + descriptor type.
      + Default: get(vertex_index, g) + Note: if you use this default, make sure your graph has + an internal vertex_index property. For example, + adjacenty_list with VertexList=listS does + not have an internal vertex_index property. +
      + + +

      Complexity

      +In the integer capacity case, if U is the value of the max flow, then the complexity is O(U * (|E| + |V|*log|V|)), +where O(|E| + |V|*log|V|) is the complexity of the dijkstra algorithm and U is upper bound on number of iteration. +In many real world cases number of iterations is much smaller than U. + + +

      Example

      + +The program in example/successive_shortest_path_example.cpp. + +

      See Also

      + +cycle_canceling()
      +find_flow_cost(). + +
      +
      + + +
      Copyright © 2013 +Piotr Wygocki, University of Warsaw (wygos at mimuw.edu.pl) +
      + + + + + + + + + + + + diff --git a/example/Jamfile.v2 b/example/Jamfile.v2 index e85664977..d3f0caf73 100644 --- a/example/Jamfile.v2 +++ b/example/Jamfile.v2 @@ -52,4 +52,6 @@ exe vf2_sub_graph_iso_multi_example : vf2_sub_graph_iso_multi_example.cpp ; exe sloan_ordering : sloan_ordering.cpp ; exe hawick_circuits : hawick_circuits.cpp ; exe edge_coloring : edge_coloring.cpp ; +exe successive_shortest_path_example : successive_shortest_path_example.cpp ; +exe cycle_canceling_example : cycle_canceling_example.cpp ; diff --git a/example/cycle_canceling_example.cpp b/example/cycle_canceling_example.cpp new file mode 100644 index 000000000..66e5ac8dd --- /dev/null +++ b/example/cycle_canceling_example.cpp @@ -0,0 +1,19 @@ +#include +#include + +#include "../test/min_cost_max_flow_utils.hpp" + + +int main() { + unsigned s,t; + boost::SampleGraph::Graph g + = boost::SampleGraph::getSampleGraph(s, t); + + boost::edmonds_karp_max_flow(g, s, t); + boost::cycle_canceling(g); + + int cost = boost::find_flow_cost(g); + assert(cost == 29); + return 0; +} + diff --git a/example/successive_shortest_path_example.cpp b/example/successive_shortest_path_example.cpp new file mode 100644 index 000000000..2583f7934 --- /dev/null +++ b/example/successive_shortest_path_example.cpp @@ -0,0 +1,21 @@ +#include +#include + +#include "../test/min_cost_max_flow_utils.hpp" + + +int main() { + unsigned s,t; + boost::SampleGraph::Graph g + = boost::SampleGraph::getSampleGraph(s, t); + + boost::successive_shortest_path(g, s, t); + + int cost = boost::find_flow_cost(g); + assert(cost == 29); + + return 0; +} + + + diff --git a/include/boost/graph/cycle_canceling.hpp b/include/boost/graph/cycle_canceling.hpp new file mode 100644 index 000000000..6d4425fab --- /dev/null +++ b/include/boost/graph/cycle_canceling.hpp @@ -0,0 +1,181 @@ +//======================================================================= +// Copyright 2013 University of Warsaw. +// Authors: Piotr Wygocki +// +// 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) +//======================================================================= +// +// +//This algorithm is described in "Network Flows: Theory, Algorithms, and Applications" +// by Ahuja, Magnanti, Orlin. + +#ifndef BOOST_GRAPH_CYCLE_CANCELING_HPP +#define BOOST_GRAPH_CYCLE_CANCELING_HPP + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost { + + +namespace detail { + +template +class RecordEdgeMapAndCycleVertex + : public bellman_visitor > { + typedef edge_predecessor_recorder PredRec; +public: + RecordEdgeMapAndCycleVertex(PredEdgeMap pred, Vertex & v) : + bellman_visitor(PredRec(pred)), m_v(v), m_pred(pred) {} + + template + void edge_not_minimized(Edge e, const Graph & g) const { + typename graph_traits::vertices_size_type n = num_vertices(g) + 1; + + //edge e is not minimized but does not have to be on the negative weight cycle + //to find vertex on negative wieight cycle we move n+1 times backword in the PredEdgeMap graph. + while(n > 0) { + e = get(m_pred, source(e, g)); + --n; + } + m_v = source(e, g); + } +private: + Vertex & m_v; + PredEdgeMap m_pred; +}; + +} //detail + + +template +void cycle_canceling(const Graph &g, Weight weight, Reversed rev, ResidualCapacity residual_capacity, Pred pred, Distance distance) { + typedef filtered_graph > ResGraph; + ResGraph gres = detail::residual_graph(g, residual_capacity); + + typedef graph_traits ResGTraits; + typedef graph_traits GTraits; + typedef typename ResGTraits::edge_descriptor edge_descriptor; + typedef typename ResGTraits::vertex_descriptor vertex_descriptor; + + typename GTraits::vertices_size_type N = num_vertices(g); + + BGL_FORALL_VERTICES_T(v, g, Graph) { + put(pred, v, edge_descriptor()); + put(distance, v, 0); + } + + vertex_descriptor cycleStart; + while(!bellman_ford_shortest_paths(gres, N, + weight_map(weight). + distance_map(distance). + visitor(detail::RecordEdgeMapAndCycleVertex(pred, cycleStart)))) { + + detail::augment(g, cycleStart, cycleStart, pred, residual_capacity, rev); + + BGL_FORALL_VERTICES_T(v, g, Graph) { + put(pred, v, edge_descriptor()); + put(distance, v, 0); + } + } +} + + +//in this namespace argument dispatching tak place +namespace detail { + +template +void cycle_canceling_dispatch2( + const Graph &g, + Weight weight, + Reversed rev, + ResidualCapacity residual_capacity, + Pred pred, + Distance dist, + const bgl_named_params& params) { + cycle_canceling(g, weight, rev, residual_capacity, pred, dist); +} + +//setting default distance map +template +void cycle_canceling_dispatch2( + Graph &g, + Weight weight, + Reversed rev, + ResidualCapacity residual_capacity, + Pred pred, + param_not_found, + const bgl_named_params& params) { + typedef typename property_traits::value_type D; + + std::vector d_map(num_vertices(g)); + + cycle_canceling(g, weight, rev, residual_capacity, pred, + make_iterator_property_map(d_map.begin(), choose_const_pmap(get_param(params, vertex_index), g, vertex_index))); +} + +template +void cycle_canceling_dispatch1( + Graph &g, + Weight weight, + Reversed rev, + ResidualCapacity residual_capacity, + Pred pred, + const bgl_named_params& params) { + cycle_canceling_dispatch2(g, weight, rev,residual_capacity, pred, + get_param(params, vertex_distance), params); +} + +//setting default predecessors map +template +void cycle_canceling_dispatch1( + Graph &g, + Weight weight, + Reversed rev, + ResidualCapacity residual_capacity, + param_not_found, + const bgl_named_params& params) { + typedef typename graph_traits::edge_descriptor edge_descriptor; + std::vector p_map(num_vertices(g)); + + cycle_canceling_dispatch2(g, weight, rev, residual_capacity, + make_iterator_property_map(p_map.begin(), choose_const_pmap(get_param(params, vertex_index), g, vertex_index)), + get_param(params, vertex_distance), params); +} + +}//detail + +template +void cycle_canceling(Graph &g, + const bgl_named_params& params) { + cycle_canceling_dispatch1(g, + choose_const_pmap(get_param(params, edge_weight), g, edge_weight), + choose_const_pmap(get_param(params, edge_reverse), g, edge_reverse), + choose_pmap(get_param(params, edge_residual_capacity), + g, edge_residual_capacity), + get_param(params, vertex_predecessor), + params); +} + +template +void cycle_canceling(Graph &g) { + bgl_named_params params(0); + cycle_canceling(g, params); +} + + +} + +#endif /* BOOST_GRAPH_CYCLE_CANCELING_HPP */ + diff --git a/include/boost/graph/detail/augment.hpp b/include/boost/graph/detail/augment.hpp new file mode 100644 index 000000000..3b20dcc4a --- /dev/null +++ b/include/boost/graph/detail/augment.hpp @@ -0,0 +1,63 @@ +//======================================================================= +// Copyright 2013 University of Warsaw. +// Authors: Piotr Wygocki +// +// 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_GRAPH_AUGMENT_HPP +#define BOOST_GRAPH_AUGMENT_HPP + +#include + +namespace boost { +namespace detail { + +template +filtered_graph > +residual_graph(const Graph& g, ResCapMap residual_capacity) { + return filtered_graph > + (g, is_residual_edge(residual_capacity)); +} + +template +inline void +augment(const Graph& g, + typename graph_traits::vertex_descriptor src, + typename graph_traits::vertex_descriptor sink, + PredEdgeMap p, + ResCapMap residual_capacity, + RevEdgeMap reverse_edge) +{ + typename graph_traits::edge_descriptor e; + typename graph_traits::vertex_descriptor u; + typedef typename property_traits::value_type FlowValue; + + // find minimum residual capacity along the augmenting path + FlowValue delta = (std::numeric_limits::max)(); + e = get(p, sink); + do { + BOOST_USING_STD_MIN(); + delta = min BOOST_PREVENT_MACRO_SUBSTITUTION(delta, get(residual_capacity, e)); + u = source(e, g); + e = get(p, u); + } while (u != src); + + // push delta units of flow along the augmenting path + e = get(p, sink); + do { + put(residual_capacity, e, get(residual_capacity, e) - delta); + put(residual_capacity, get(reverse_edge, e), get(residual_capacity, get(reverse_edge, e)) + delta); + u = source(e, g); + e = get(p, u); + } while (u != src); +} + +} // namespace detail +} //namespace boost + +#endif /* BOOST_GRAPH_AUGMENT_HPP */ + diff --git a/include/boost/graph/find_flow_cost.hpp b/include/boost/graph/find_flow_cost.hpp new file mode 100644 index 000000000..e4d6f404e --- /dev/null +++ b/include/boost/graph/find_flow_cost.hpp @@ -0,0 +1,52 @@ +//======================================================================= +// Copyright 2013 University of Warsaw. +// Authors: Piotr Wygocki +// +// 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_GRAPH_FIND_FLOW_COST_HPP +#define BOOST_GRAPH_FIND_FLOW_COST_HPP + +#include + +namespace boost { + +template +typename property_traits::type>::value_type +find_flow_cost(const Graph & g, Capacity capacity, ResidualCapacity residual_capacity, Weight weight) { + typedef typename property_traits::const_type>::value_type Cost; + + Cost cost = 0; + BGL_FORALL_EDGES_T(e, g, Graph) { + if(get(capacity, e) > Cost(0)) { + cost += (get(capacity, e) - get(residual_capacity, e)) * get(weight, e); + } + } + return cost; +} + +template +typename property_traits::type>::value_type +find_flow_cost(const Graph & g, + const bgl_named_params& params) { + return find_flow_cost(g, + choose_const_pmap(get_param(params, edge_capacity), g, edge_capacity), + choose_const_pmap(get_param(params, edge_residual_capacity), + g, edge_residual_capacity), + choose_const_pmap(get_param(params, edge_weight), g, edge_weight)); +} + +template +typename property_traits::type>::value_type +find_flow_cost(const Graph &g) { + bgl_named_params params(0); + return find_flow_cost(g, params); +} + + +} //boost + +#endif /* BOOST_GRAPH_FIND_FLOW_COST_HPP */ + diff --git a/include/boost/graph/named_function_params.hpp b/include/boost/graph/named_function_params.hpp index 4ab24f63c..26d3d5e40 100644 --- a/include/boost/graph/named_function_params.hpp +++ b/include/boost/graph/named_function_params.hpp @@ -64,6 +64,7 @@ namespace boost { BOOST_BGL_ONE_PARAM_CREF(weight_map, edge_weight) \ BOOST_BGL_ONE_PARAM_CREF(weight_map2, edge_weight2) \ BOOST_BGL_ONE_PARAM_CREF(distance_map, vertex_distance) \ + BOOST_BGL_ONE_PARAM_CREF(distance_map2, vertex_distance2) \ BOOST_BGL_ONE_PARAM_CREF(predecessor_map, vertex_predecessor) \ BOOST_BGL_ONE_PARAM_CREF(rank_map, vertex_rank) \ BOOST_BGL_ONE_PARAM_CREF(root_map, vertex_root) \ diff --git a/include/boost/graph/successive_shortest_path.hpp b/include/boost/graph/successive_shortest_path.hpp new file mode 100644 index 000000000..0e5703db8 --- /dev/null +++ b/include/boost/graph/successive_shortest_path.hpp @@ -0,0 +1,261 @@ +//======================================================================= +// Copyright 2013 University of Warsaw. +// Authors: Piotr Wygocki +// +// 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) +//======================================================================= +// +//This algorithm is described in "Network Flows: Theory, Algorithms, and Applications" +// by Ahuja, Magnanti, Orlin. + +#ifndef BOOST_GRAPH_SUCCESSIVE_SHORTEST_PATH_HPP +#define BOOST_GRAPH_SUCCESSIVE_SHORTEST_PATH_HPP + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost { + + +namespace detail { + +template +class MapReducedWeight : + public put_get_helper::value_type, MapReducedWeight > { + typedef graph_traits gtraits; +public: + typedef boost::readable_property_map_tag category; + typedef typename property_traits::value_type value_type; + typedef value_type reference; + typedef typename gtraits::edge_descriptor key_type; + MapReducedWeight(const Graph & g, Weight w, Distance d, Reversed r) : + g_(g), weight_(w), distance_(d), rev_(r) {} + + reference operator[](key_type v) const { + return get(distance_, source(v, g_)) - get(distance_,target(v, g_)) + get(weight_, v); + } +private: + const Graph & g_; + Weight weight_; + Distance distance_; + Reversed rev_; +}; + +template +MapReducedWeight +make_mapReducedWeight(const Graph & g, Weight w, Distance d, Reversed r) { + return MapReducedWeight(g, w, d, r); +} + +}//detail + + +template +void successive_shortest_path( + const Graph &g, + typename graph_traits::vertex_descriptor s, + typename graph_traits::vertex_descriptor t, + Capacity capacity, + ResidualCapacity residual_capacity, + Weight weight, + Reversed rev, + VertexIndex index, + Pred pred, + Distance distance, + Distance2 distance_prev) { + filtered_graph > + gres = detail::residual_graph(g, residual_capacity); + typedef typename graph_traits::edge_descriptor edge_descriptor; + + BGL_FORALL_EDGES_T(e, g, Graph) { + put(residual_capacity, e, get(capacity, e)); + } + + BGL_FORALL_VERTICES_T(v, g, Graph) { + put(distance_prev, v, 0); + } + + while(true) { + BGL_FORALL_VERTICES_T(v, g, Graph) { + put(pred, v, edge_descriptor()); + } + dijkstra_shortest_paths(gres, s, + weight_map(detail::make_mapReducedWeight(gres, weight, distance_prev, rev)). + distance_map(distance). + vertex_index_map(index). + visitor(make_dijkstra_visitor(record_edge_predecessors(pred, on_edge_relaxed())))); + + if(get(pred, t) == edge_descriptor()) { + break; + } + + BGL_FORALL_VERTICES_T(v, g, Graph) { + put(distance_prev, v, get(distance_prev, v) + get(distance, v)); + } + + detail::augment(g, s, t, pred, residual_capacity, rev); + } +} + +//in this namespace argument dispatching tak place +namespace detail { + +template +void successive_shortest_path_dispatch3( + const Graph &g, + typename graph_traits::vertex_descriptor s, + typename graph_traits::vertex_descriptor t, + Capacity capacity, + ResidualCapacity residual_capacity, + Weight weight, + Reversed rev, + VertexIndex index, + Pred pred, + Distance dist, + Distance2 dist_pred) { + successive_shortest_path(g, s, t, capacity, residual_capacity, weight, rev, index, pred, dist, dist_pred); +} + +//setting default distance map +template +void successive_shortest_path_dispatch3( + Graph &g, + typename graph_traits::vertex_descriptor s, + typename graph_traits::vertex_descriptor t, + Capacity capacity, + ResidualCapacity residual_capacity, + Weight weight, + Reversed rev, + VertexIndex index, + Pred pred, + Distance dist, + param_not_found) { + typedef typename property_traits::value_type D; + + std::vector d_map(num_vertices(g)); + + successive_shortest_path(g, s, t, capacity, residual_capacity, weight, rev, index, pred, dist, + make_iterator_property_map(d_map.begin(), index)); +} + +template +void successive_shortest_path_dispatch2( + Graph &g, + typename graph_traits::vertex_descriptor s, + typename graph_traits::vertex_descriptor t, + Capacity capacity, + ResidualCapacity residual_capacity, + Weight weight, + Reversed rev, + VertexIndex index, + Pred pred, + Distance dist, + const bgl_named_params& params) { + successive_shortest_path_dispatch3(g, s, t, capacity, residual_capacity, weight, rev, index, pred, dist, get_param(params, vertex_distance2)); +} + +//setting default distance map +template +void successive_shortest_path_dispatch2( + Graph &g, + typename graph_traits::vertex_descriptor s, + typename graph_traits::vertex_descriptor t, + Capacity capacity, + ResidualCapacity residual_capacity, + Weight weight, + Reversed rev, + VertexIndex index, + Pred pred, + param_not_found, + const bgl_named_params& params) { + typedef typename property_traits::value_type D; + + std::vector d_map(num_vertices(g)); + + successive_shortest_path_dispatch3(g, s, t, capacity, residual_capacity, weight, rev, index, pred, + make_iterator_property_map(d_map.begin(), index), + get_param(params, vertex_distance2)); +} + +template +void successive_shortest_path_dispatch1( + Graph &g, + typename graph_traits::vertex_descriptor s, + typename graph_traits::vertex_descriptor t, + Capacity capacity, + ResidualCapacity residual_capacity, + Weight weight, + Reversed rev, + VertexIndex index, + Pred pred, + const bgl_named_params& params) { + successive_shortest_path_dispatch2(g, s, t, capacity, residual_capacity, weight, rev, index, pred, + get_param(params, vertex_distance), params); +} + +//setting default predecessors map +template +void successive_shortest_path_dispatch1( + Graph &g, + typename graph_traits::vertex_descriptor s, + typename graph_traits::vertex_descriptor t, + Capacity capacity, + ResidualCapacity residual_capacity, + Weight weight, + Reversed rev, + VertexIndex index, + param_not_found, + const bgl_named_params& params) { + typedef typename graph_traits::edge_descriptor edge_descriptor; + std::vector pred_vec(num_vertices(g)); + + successive_shortest_path_dispatch2(g, s, t, capacity, residual_capacity, weight, rev, index, + make_iterator_property_map(pred_vec.begin(), index), + get_param(params, vertex_distance), params); +} + +}//detail + + +template +void successive_shortest_path( + Graph &g, + typename graph_traits::vertex_descriptor s, + typename graph_traits::vertex_descriptor t, + const bgl_named_params& params) { + + return detail::successive_shortest_path_dispatch1(g, s, t, + choose_const_pmap(get_param(params, edge_capacity), g, edge_capacity), + choose_pmap(get_param(params, edge_residual_capacity), + g, edge_residual_capacity), + choose_const_pmap(get_param(params, edge_weight), g, edge_weight), + choose_const_pmap(get_param(params, edge_reverse), g, edge_reverse), + choose_const_pmap(get_param(params, vertex_index), g, vertex_index), + get_param(params, vertex_predecessor), + params); +} + +template +void successive_shortest_path( + Graph &g, + typename graph_traits::vertex_descriptor s, + typename graph_traits::vertex_descriptor t) { + bgl_named_params params(0); + successive_shortest_path(g, s, t, params); +} + + +}//boost +#endif /* BOOST_GRAPH_SUCCESSIVE_SHORTEST_PATH_HPP */ + diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 37cebaa57..35bf687d3 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -128,6 +128,8 @@ test-suite graph_test : [ compile filtered_graph_properties_dijkstra.cpp ] [ run vf2_sub_graph_iso_test.cpp ] [ run hawick_circuits.cpp ] + [ run successive_shortest_path_test.cpp ../../test/build//boost_unit_test_framework/static ] + [ run cycle_canceling_test.cpp ../../test/build//boost_unit_test_framework/static ] ; # Run SDB tests only when -sSDB= is set. diff --git a/test/cycle_canceling_test.cpp b/test/cycle_canceling_test.cpp new file mode 100644 index 000000000..05f6b101e --- /dev/null +++ b/test/cycle_canceling_test.cpp @@ -0,0 +1,51 @@ +#define BOOST_TEST_MODULE cycle_canceling_test + +#include + +#include +#include + +#include "min_cost_max_flow_utils.hpp" + + +BOOST_AUTO_TEST_CASE(cycle_canceling_def_test) { + unsigned s,t; + boost::SampleGraph::Graph g + = boost::SampleGraph::getSampleGraph(s, t); + + boost::edmonds_karp_max_flow(g, s, t); + boost::cycle_canceling(g); + + int cost = boost::find_flow_cost(g); + BOOST_CHECK_EQUAL(cost, 29); +} + +BOOST_AUTO_TEST_CASE(path_augmentation_def_test2) { + unsigned s,t; + boost::SampleGraph::Graph g + = boost::SampleGraph::getSampleGraph2(s, t); + + boost::edmonds_karp_max_flow(g, s, t); + boost::cycle_canceling(g); + + int cost = boost::find_flow_cost(g); + BOOST_CHECK_EQUAL(cost, 7); +} + +BOOST_AUTO_TEST_CASE(cycle_canceling_test) { + unsigned s,t; + typedef boost::SampleGraph::Graph Graph; + Graph g = boost::SampleGraph::getSampleGraph(s, t); + + int N = num_vertices(g); + std::vector dist(N); + typedef boost::graph_traits::edge_descriptor edge_descriptor; + std::vector pred(N); + + boost::edmonds_karp_max_flow(g, s, t); + boost::cycle_canceling(g, boost::distance_map(&dist[0]).predecessor_map(&pred[0]).vertex_index_map(boost::identity_property_map())); + + int cost = boost::find_flow_cost(g); + BOOST_CHECK_EQUAL(cost, 29); +} + diff --git a/test/min_cost_max_flow_utils.hpp b/test/min_cost_max_flow_utils.hpp new file mode 100644 index 000000000..acb58b44d --- /dev/null +++ b/test/min_cost_max_flow_utils.hpp @@ -0,0 +1,128 @@ +/** + * @file sample_graph_undirected.hpp + * @brief + * @author Piotr Wygocki + * @version 1.0 + * @date 2013-06-17 + */ +#ifndef SAMPLE_GRAPH_UNDIRECTED_HPP +#define SAMPLE_GRAPH_UNDIRECTED_HPP + +#include + + +namespace boost { +struct SampleGraph { + typedef adjacency_list_traits < vecS, vecS, directedS > Traits; + + typedef adjacency_list < listS, vecS, directedS, no_property, + property < edge_capacity_t, long, + property < edge_residual_capacity_t, long, + property < edge_reverse_t, Traits::edge_descriptor, + property + > + > + > > Graph; + typedef property_map < Graph, edge_capacity_t >::type Capacity; + typedef property_map < Graph, edge_residual_capacity_t >::type ResidualCapacity; + typedef property_map < Graph, edge_weight_t >::type Weight; + + + template + class EdgeAdder { + public: + EdgeAdder(Graph & g, Weight & w, Capacity & c, Reversed & rev, ResidualCapacity & residualCapacity) + : m_g(g), m_w(w), m_cap(c), m_resCap(residualCapacity), m_rev(rev) {} + void addEdge(int v, int w, int weight, int capacity) { + Traits::edge_descriptor e,f; + e = add(v, w, weight, capacity); + f = add(w, v, -weight, 0); + m_rev[e] = f; + m_rev[f] = e; + } + private: + Traits::edge_descriptor add(int v, int w, int weight, int capacity) { + bool b; + Traits::edge_descriptor e; + boost::tie(e, b) = add_edge(v, w, m_g); + assert(b); + m_cap[e] = capacity; + m_w[e] = weight; + return e; + } + Graph & m_g; + Weight & m_w; + Capacity & m_cap; + ResidualCapacity & m_resCap; + Reversed & m_rev; + }; + + + static Graph getSampleGraph(unsigned & s, unsigned & t) { + const boost::graph_traits::vertices_size_type N(6); + typedef property_map < Graph, edge_reverse_t >::type Reversed; + + Graph g(N); + Capacity capacity = get(edge_capacity, g); + Reversed rev = get(edge_reverse, g); + ResidualCapacity residual_capacity = get(edge_residual_capacity, g); + Weight weight = get(edge_weight, g); + + s = 0; + t = 5; + + EdgeAdder + ea(g, weight, capacity, rev, residual_capacity); + + ea.addEdge(0, 1, 4 ,2); + ea.addEdge(0, 2, 2 ,2); + + ea.addEdge(1, 3, 2 ,2); + ea.addEdge(1, 4, 1 ,1); + ea.addEdge(2, 3, 1 ,1); + ea.addEdge(2, 4, 1 ,1); + + ea.addEdge(3, 5, 4 ,20); + ea.addEdge(4, 5, 2 ,20); + + return g; + } + + static Graph getSampleGraph2(unsigned & s, unsigned & t) { + const boost::graph_traits::vertices_size_type N(5); + typedef property_map < Graph, edge_reverse_t >::type Reversed; + + Graph g(N); + Capacity capacity = get(edge_capacity, g); + Reversed rev = get(edge_reverse, g); + ResidualCapacity residual_capacity = get(edge_residual_capacity, g); + Weight weight = get(edge_weight, g); + + s = 0; + t = 4; + + EdgeAdder + ea(g, weight, capacity, rev, residual_capacity); + + ea.addEdge(0, 1, 4 ,2); + ea.addEdge(0, 2, 2 ,2); + ea.addEdge(1, 2, 2 ,2); + ea.addEdge(2, 3, 1 ,1); + ea.addEdge(2, 4, 1 ,1); + ea.addEdge(3, 4, 1 ,1); + + + ea.addEdge(1, 0, 2 ,2); + ea.addEdge(2, 0, 1 ,1); + ea.addEdge(2, 1, 5 ,2); + ea.addEdge(3, 2, 1 ,1); + ea.addEdge(4, 2, 2 ,2); + ea.addEdge(4, 3, 1 ,3); + + return g; + } +}; +} //boost + +#endif /* SAMPLE_GRAPH_UNDIRECTED_HPP */ + diff --git a/test/successive_shortest_path_test.cpp b/test/successive_shortest_path_test.cpp new file mode 100644 index 000000000..e7551438f --- /dev/null +++ b/test/successive_shortest_path_test.cpp @@ -0,0 +1,55 @@ +#define BOOST_TEST_MODULE successive_shortest_path_test + +#include + +#include +#include + +#include "min_cost_max_flow_utils.hpp" + + +BOOST_AUTO_TEST_CASE(path_augmentation_def_test) { + unsigned s,t; + boost::SampleGraph::Graph g + = boost::SampleGraph::getSampleGraph(s, t); + + boost::successive_shortest_path(g, s, t); + + int cost = boost::find_flow_cost(g); + BOOST_CHECK_EQUAL(cost, 29); +} + +BOOST_AUTO_TEST_CASE(path_augmentation_def_test2) { + unsigned s,t; + boost::SampleGraph::Graph g + = boost::SampleGraph::getSampleGraph2(s, t); + + boost::successive_shortest_path(g, s, t); + + int cost = boost::find_flow_cost(g); + BOOST_CHECK_EQUAL(cost, 7); +} + +BOOST_AUTO_TEST_CASE(path_augmentation_test) { + unsigned s,t; + typedef boost::SampleGraph::Graph Graph; + Graph g = boost::SampleGraph::getSampleGraph(s, t); + + int N = boost::num_vertices(g); + std::vector dist(N); + std::vector dist_prev(N); + typedef boost::graph_traits::edge_descriptor edge_descriptor; + std::vector pred(N); + + + boost::successive_shortest_path(g, s, t, + boost::distance_map(&dist[0]). + predecessor_map(&pred[0]). + distance_map2(&dist_prev[0]). + vertex_index_map(boost::identity_property_map())); + + int cost = boost::find_flow_cost(g); + BOOST_CHECK_EQUAL(cost, 29); +} + + From 8aa602b40d5860fcf9a2eb01513c75d062c7b9ed Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Tue, 3 Sep 2013 18:12:59 +0000 Subject: [PATCH 302/333] Fixed pseudocode in documentation; fixes #9080 [SVN r85551] --- doc/dijkstra_shortest_paths_no_color_map.html | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/doc/dijkstra_shortest_paths_no_color_map.html b/doc/dijkstra_shortest_paths_no_color_map.html index b65d333f0..c7202b68a 100644 --- a/doc/dijkstra_shortest_paths_no_color_map.html +++ b/doc/dijkstra_shortest_paths_no_color_map.html @@ -124,11 +124,12 @@

      if (w(u,v) + d[u] < d[v]) d[v] := w(u,v) + d[u] p[v] := u - DECREASE-KEY(Q, v) + if (d[v] was originally infinity) + INSERT(Q, v) + else + DECREASE-KEY(Q, v) else ... - if (d[v] was originally infinity) - INSERT(Q, v) end for end while return (d, p) @@ -146,10 +147,11 @@

      edge (u,v) relaxed +discover vertex v + edge (u,v) not relaxed -discover vertex v finish vertex u From 85b45da7c8a80e103d848168443e092e84cecc77 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Wed, 4 Sep 2013 20:47:36 +0000 Subject: [PATCH 303/333] Fixed various data type bugs, and cleaned up signed vs. unsigned and int vs. size_t issues [SVN r85567] --- include/boost/graph/r_c_shortest_paths.hpp | 33 ++++++++++++---------- 1 file changed, 18 insertions(+), 15 deletions(-) diff --git a/include/boost/graph/r_c_shortest_paths.hpp b/include/boost/graph/r_c_shortest_paths.hpp index 28755d872..081393ee9 100644 --- a/include/boost/graph/r_c_shortest_paths.hpp +++ b/include/boost/graph/r_c_shortest_paths.hpp @@ -185,7 +185,10 @@ void r_c_shortest_paths_dispatch pareto_optimal_resource_containers.clear(); pareto_optimal_solutions.clear(); - unsigned long i_label_num = 0; + typedef typename boost::graph_traits::vertices_size_type + vertices_size_type; + + size_t i_label_num = 0; typedef typename Label_Allocator::template rebind @@ -217,9 +220,9 @@ void r_c_shortest_paths_dispatch vec_vertex_labels[vertex_index_map[s]].push_back( splabel_first_label ); std::vector::iterator> vec_last_valid_positions_for_dominance( num_vertices( g ) ); - for( int i = 0; i < static_cast( num_vertices( g ) ); ++i ) + for( vertices_size_type i = 0; i < num_vertices( g ); ++i ) vec_last_valid_positions_for_dominance[i] = vec_vertex_labels[i].begin(); - std::vector vec_last_valid_index_for_dominance( num_vertices( g ), 0 ); + std::vector vec_last_valid_index_for_dominance( num_vertices( g ), 0 ); std::vector b_vec_vertex_already_checked_for_dominance( num_vertices( g ), false ); while( !unprocessed_labels.empty() && vis.on_enter_loop(unprocessed_labels, g) ) @@ -241,12 +244,12 @@ void r_c_shortest_paths_dispatch // if the label to be extended is undominated if( !cur_label->b_is_dominated ) { - int i_cur_resident_vertex_num = cur_label->resident_vertex; + vertices_size_type i_cur_resident_vertex_num = get(vertex_index_map, cur_label->resident_vertex); std::list& list_labels_cur_vertex = vec_vertex_labels[i_cur_resident_vertex_num]; - if( static_cast( list_labels_cur_vertex.size() ) >= 2 + if( list_labels_cur_vertex.size() >= 2 && vec_last_valid_index_for_dominance[i_cur_resident_vertex_num] - < static_cast( list_labels_cur_vertex.size() ) ) + < list_labels_cur_vertex.size() ) { typename std::list::iterator outer_iter = list_labels_cur_vertex.begin(); @@ -318,7 +321,7 @@ void r_c_shortest_paths_dispatch if( !b_outer_iter_erased ) ++outer_iter; } - if( static_cast( list_labels_cur_vertex.size() ) > 1 ) + if( list_labels_cur_vertex.size() > 1 ) vec_last_valid_positions_for_dominance[i_cur_resident_vertex_num] = (--(list_labels_cur_vertex.end())); else @@ -327,7 +330,7 @@ void r_c_shortest_paths_dispatch b_vec_vertex_already_checked_for_dominance [i_cur_resident_vertex_num] = true; vec_last_valid_index_for_dominance[i_cur_resident_vertex_num] = - static_cast( list_labels_cur_vertex.size() ) - 1; + list_labels_cur_vertex.size() - 1; } } if( !b_all_pareto_optimal_solutions && cur_label->resident_vertex == t ) @@ -430,8 +433,8 @@ void r_c_shortest_paths_dispatch } } - int i_size = static_cast( vec_vertex_labels.size() ); - for( int i = 0; i < i_size; ++i ) + size_t i_size = vec_vertex_labels.size(); + for( size_t i = 0; i < i_size; ++i ) { const std::list& list_labels_cur_vertex = vec_vertex_labels[i]; csi_end = list_labels_cur_vertex.end(); @@ -679,7 +682,7 @@ void check_r_c_path( const Graph& g, typename graph_traits::edge_descriptor& ed_last_extended_arc ) { - int i_size_ed_vec_path = static_cast( ed_vec_path.size() ); + size_t i_size_ed_vec_path = ed_vec_path.size(); std::vector::edge_descriptor> buf_path; if( i_size_ed_vec_path == 0 ) b_feasible = true; @@ -689,9 +692,9 @@ void check_r_c_path( const Graph& g, || target( ed_vec_path[0], g ) == source( ed_vec_path[1], g ) ) buf_path = ed_vec_path; else - for( int i = i_size_ed_vec_path - 1; i >= 0; --i ) - buf_path.push_back( ed_vec_path[i] ); - for( int i = 0; i < i_size_ed_vec_path - 1; ++i ) + for( size_t i = i_size_ed_vec_path ; i > 0; --i ) + buf_path.push_back( ed_vec_path[i - 1] ); + for( size_t i = 0; i < i_size_ed_vec_path - 1; ++i ) { if( target( buf_path[i], g ) != source( buf_path[i + 1], g ) ) { @@ -707,7 +710,7 @@ void check_r_c_path( const Graph& g, b_correctly_extended = false; Resource_Container current_resource_levels = initial_resource_levels; actual_final_resource_levels = current_resource_levels; - for( int i = 0; i < i_size_ed_vec_path; ++i ) + for( size_t i = 0; i < i_size_ed_vec_path; ++i ) { ed_last_extended_arc = buf_path[i]; b_feasible = ref( g, From bd107e4ab5c18435708f822546e3d717f072a4f6 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Wed, 4 Sep 2013 21:39:21 +0000 Subject: [PATCH 304/333] Applied patch and file renames from Piotr Wygocki [SVN r85568] --- doc/cycle_canceling.html | 6 ++-- doc/find_flow_cost.html | 10 +++--- ...ve_shortest_path_nonnegative_weights.html} | 14 ++++---- doc/table_of_contents.html | 6 ++++ example/Jamfile.v2 | 2 +- example/cycle_canceling_example.cpp | 9 +++++ example/successive_shortest_path_example.cpp | 21 ------------ ...rtest_path_nonnegative_weights_example.cpp | 30 ++++++++++++++++ include/boost/graph/cycle_canceling.hpp | 2 +- ...ive_shortest_path_nonnegative_weights.hpp} | 34 +++++++++---------- test/Jamfile.v2 | 2 +- test/cycle_canceling_test.cpp | 9 +++++ test/min_cost_max_flow_utils.hpp | 16 +++++---- ...hortest_path_nonnegative_weights_test.cpp} | 19 ++++++++--- 14 files changed, 112 insertions(+), 68 deletions(-) rename doc/{successive_shortest_path.html => successive_shortest_path_nonnegative_weights.html} (93%) delete mode 100644 example/successive_shortest_path_example.cpp create mode 100644 example/successive_shortest_path_nonnegative_weights_example.cpp rename include/boost/graph/{successive_shortest_path.hpp => successive_shortest_path_nonnegative_weights.hpp} (85%) rename test/{successive_shortest_path_test.cpp => successive_shortest_path_nonnegative_weights_test.cpp} (63%) diff --git a/doc/cycle_canceling.html b/doc/cycle_canceling.html index 459a2e2b2..63cecf050 100644 --- a/doc/cycle_canceling.html +++ b/doc/cycle_canceling.html @@ -56,7 +56,7 @@

      Note that edges from E can have negative weights.

      If weights in the graph are nonnegative, the -successive_shortest_path() +successive_shortest_path_nonnegative_weights() might be better choice for min cost max flow.

      @@ -78,7 +78,7 @@

      Where Defined

      -boost/graph/successive_shortest_path.hpp +boost/graph/successive_shortest_path_nonnegative_weights.hpp

      @@ -191,7 +191,7 @@

      Example

      See Also

      -successive_shortest_path()
      +successive_shortest_path_nonnegative_weights()
      find_flow_cost().
      diff --git a/doc/find_flow_cost.html b/doc/find_flow_cost.html index 94f9c045e..7f839cf90 100644 --- a/doc/find_flow_cost.html +++ b/doc/find_flow_cost.html @@ -42,13 +42,13 @@

      In order to compute the min cost max flow use : -successive_shortest_path() or +successive_shortest_path_nonnegative_weights() or cycle_canceling().

      Where Defined

      -boost/graph/successive_shortest_path.hpp +boost/graph/successive_shortest_path_nonnegative_weights.hpp

      @@ -102,13 +102,13 @@

      Complexity

      Example

      -The function is used in the successive_shortest_path example. The program in example/successive_shortest_path_example.cpp. +The function is used in the successive_shortest_path_nonnegative_weights example. The program in example/successive_shortest_path_nonnegative_weights_example.cpp.

      See Also

      cycle_canceling()
      -successive_shortest_path(). +successive_shortest_path_nonnegative_weights().

      diff --git a/doc/successive_shortest_path.html b/doc/successive_shortest_path_nonnegative_weights.html similarity index 93% rename from doc/successive_shortest_path.html rename to doc/successive_shortest_path_nonnegative_weights.html index 4b403d52a..d6d53be22 100644 --- a/doc/successive_shortest_path.html +++ b/doc/successive_shortest_path_nonnegative_weights.html @@ -15,14 +15,14 @@
      -

      -successive_shortest_path +

      +successive_shortest_path_nonnegative_weights

       // named parameter version
       template <class Graph, class P, class T, class R>
      -void successive_shortest_path(
      +void successive_shortest_path_nonnegative_weights(
               Graph &g, 
               typename graph_traits<Graph>::vertex_descriptor s, 
               typename graph_traits<Graph>::vertex_descriptor t,
      @@ -30,7 +30,7 @@ 

      // non-named parameter version template <class Graph, class Capacity, class ResidualCapacity, class Reversed, class Pred, class Weight, class Distance, class Distance2, class VertexIndex> -void successive_shortest_path( +void successive_shortest_path_nonnegative_weights( const Graph & g, typename graph_traits<Graph>::vertex_descriptor s, typename graph_traits<Graph>::vertex_descriptor t, @@ -45,7 +45,7 @@

      -The successive_shortest_path() function calculates the minimum cost maximum flow of a network. See Section successive_shortest_path_nonnegative_weights() function calculates the minimum cost maximum flow of a network. See Section Network Flow Algorithms for a description of maximum flow. The function calculates the flow values f(u,v) for all (u,v) in @@ -79,7 +79,7 @@

      Where Defined

      -boost/graph/successive_shortest_path.hpp +boost/graph/successive_shortest_path_nonnegative_weights.hpp

      @@ -228,7 +228,7 @@

      Complexity

      Example

      The program in example/successive_shortest_path_example.cpp. +href="../example/successive_shortest_path_nonnegative_weights_example.cpp">example/successive_shortest_path_nonnegative_weights_example.cpp.

      See Also

      diff --git a/doc/table_of_contents.html b/doc/table_of_contents.html index 1e5664e39..9e0e9ec78 100644 --- a/doc/table_of_contents.html +++ b/doc/table_of_contents.html @@ -214,6 +214,12 @@

      Table of Contents: the Boost Graph Library
    9. boykov_kolmogorov_max_flow
    10. edmonds_maximum_cardinality_matching
    +
  • Minimum Cost Maximum Flow Algorithms +
      +
    1. cycle_canceling +
    2. successive_shortest_path_nonnegative_weights +
    3. find_flow_cost
    4. +
  • Minimum Cut Algorithms
    1. stoer_wagner_min_cut diff --git a/example/Jamfile.v2 b/example/Jamfile.v2 index d3f0caf73..13cdf75f6 100644 --- a/example/Jamfile.v2 +++ b/example/Jamfile.v2 @@ -52,6 +52,6 @@ exe vf2_sub_graph_iso_multi_example : vf2_sub_graph_iso_multi_example.cpp ; exe sloan_ordering : sloan_ordering.cpp ; exe hawick_circuits : hawick_circuits.cpp ; exe edge_coloring : edge_coloring.cpp ; -exe successive_shortest_path_example : successive_shortest_path_example.cpp ; +exe successive_shortest_path_nonnegative_weights_example : successive_shortest_path_nonnegative_weights_example.cpp ; exe cycle_canceling_example : cycle_canceling_example.cpp ; diff --git a/example/cycle_canceling_example.cpp b/example/cycle_canceling_example.cpp index 66e5ac8dd..f1e02dd7f 100644 --- a/example/cycle_canceling_example.cpp +++ b/example/cycle_canceling_example.cpp @@ -1,3 +1,12 @@ +//======================================================================= +// Copyright 2013 University of Warsaw. +// Authors: Piotr Wygocki +// +// 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) +//======================================================================= + #include #include diff --git a/example/successive_shortest_path_example.cpp b/example/successive_shortest_path_example.cpp deleted file mode 100644 index 2583f7934..000000000 --- a/example/successive_shortest_path_example.cpp +++ /dev/null @@ -1,21 +0,0 @@ -#include -#include - -#include "../test/min_cost_max_flow_utils.hpp" - - -int main() { - unsigned s,t; - boost::SampleGraph::Graph g - = boost::SampleGraph::getSampleGraph(s, t); - - boost::successive_shortest_path(g, s, t); - - int cost = boost::find_flow_cost(g); - assert(cost == 29); - - return 0; -} - - - diff --git a/example/successive_shortest_path_nonnegative_weights_example.cpp b/example/successive_shortest_path_nonnegative_weights_example.cpp new file mode 100644 index 000000000..f877d40c9 --- /dev/null +++ b/example/successive_shortest_path_nonnegative_weights_example.cpp @@ -0,0 +1,30 @@ +//======================================================================= +// Copyright 2013 University of Warsaw. +// Authors: Piotr Wygocki +// +// 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) +//======================================================================= + +#include +#include + +#include "../test/min_cost_max_flow_utils.hpp" + + +int main() { + unsigned s,t; + boost::SampleGraph::Graph g + = boost::SampleGraph::getSampleGraph(s, t); + + boost::successive_shortest_path_nonnegative_weights(g, s, t); + + int cost = boost::find_flow_cost(g); + assert(cost == 29); + + return 0; +} + + + diff --git a/include/boost/graph/cycle_canceling.hpp b/include/boost/graph/cycle_canceling.hpp index 6d4425fab..46a4b864c 100644 --- a/include/boost/graph/cycle_canceling.hpp +++ b/include/boost/graph/cycle_canceling.hpp @@ -92,7 +92,7 @@ void cycle_canceling(const Graph &g, Weight weight, Reversed rev, ResidualCapaci } -//in this namespace argument dispatching tak place +//in this namespace argument dispatching takes place namespace detail { template diff --git a/include/boost/graph/successive_shortest_path.hpp b/include/boost/graph/successive_shortest_path_nonnegative_weights.hpp similarity index 85% rename from include/boost/graph/successive_shortest_path.hpp rename to include/boost/graph/successive_shortest_path_nonnegative_weights.hpp index 0e5703db8..72b1512c1 100644 --- a/include/boost/graph/successive_shortest_path.hpp +++ b/include/boost/graph/successive_shortest_path_nonnegative_weights.hpp @@ -62,7 +62,7 @@ make_mapReducedWeight(const Graph & g, Weight w, Distance d, Reversed r) { template -void successive_shortest_path( +void successive_shortest_path_nonnegative_weights( const Graph &g, typename graph_traits::vertex_descriptor s, typename graph_traits::vertex_descriptor t, @@ -112,7 +112,7 @@ void successive_shortest_path( namespace detail { template -void successive_shortest_path_dispatch3( +void successive_shortest_path_nonnegative_weights_dispatch3( const Graph &g, typename graph_traits::vertex_descriptor s, typename graph_traits::vertex_descriptor t, @@ -124,12 +124,12 @@ void successive_shortest_path_dispatch3( Pred pred, Distance dist, Distance2 dist_pred) { - successive_shortest_path(g, s, t, capacity, residual_capacity, weight, rev, index, pred, dist, dist_pred); + successive_shortest_path_nonnegative_weights(g, s, t, capacity, residual_capacity, weight, rev, index, pred, dist, dist_pred); } //setting default distance map template -void successive_shortest_path_dispatch3( +void successive_shortest_path_nonnegative_weights_dispatch3( Graph &g, typename graph_traits::vertex_descriptor s, typename graph_traits::vertex_descriptor t, @@ -145,12 +145,12 @@ void successive_shortest_path_dispatch3( std::vector d_map(num_vertices(g)); - successive_shortest_path(g, s, t, capacity, residual_capacity, weight, rev, index, pred, dist, + successive_shortest_path_nonnegative_weights(g, s, t, capacity, residual_capacity, weight, rev, index, pred, dist, make_iterator_property_map(d_map.begin(), index)); } template -void successive_shortest_path_dispatch2( +void successive_shortest_path_nonnegative_weights_dispatch2( Graph &g, typename graph_traits::vertex_descriptor s, typename graph_traits::vertex_descriptor t, @@ -162,12 +162,12 @@ void successive_shortest_path_dispatch2( Pred pred, Distance dist, const bgl_named_params& params) { - successive_shortest_path_dispatch3(g, s, t, capacity, residual_capacity, weight, rev, index, pred, dist, get_param(params, vertex_distance2)); + successive_shortest_path_nonnegative_weights_dispatch3(g, s, t, capacity, residual_capacity, weight, rev, index, pred, dist, get_param(params, vertex_distance2)); } //setting default distance map template -void successive_shortest_path_dispatch2( +void successive_shortest_path_nonnegative_weights_dispatch2( Graph &g, typename graph_traits::vertex_descriptor s, typename graph_traits::vertex_descriptor t, @@ -183,13 +183,13 @@ void successive_shortest_path_dispatch2( std::vector d_map(num_vertices(g)); - successive_shortest_path_dispatch3(g, s, t, capacity, residual_capacity, weight, rev, index, pred, + successive_shortest_path_nonnegative_weights_dispatch3(g, s, t, capacity, residual_capacity, weight, rev, index, pred, make_iterator_property_map(d_map.begin(), index), get_param(params, vertex_distance2)); } template -void successive_shortest_path_dispatch1( +void successive_shortest_path_nonnegative_weights_dispatch1( Graph &g, typename graph_traits::vertex_descriptor s, typename graph_traits::vertex_descriptor t, @@ -200,13 +200,13 @@ void successive_shortest_path_dispatch1( VertexIndex index, Pred pred, const bgl_named_params& params) { - successive_shortest_path_dispatch2(g, s, t, capacity, residual_capacity, weight, rev, index, pred, + successive_shortest_path_nonnegative_weights_dispatch2(g, s, t, capacity, residual_capacity, weight, rev, index, pred, get_param(params, vertex_distance), params); } //setting default predecessors map template -void successive_shortest_path_dispatch1( +void successive_shortest_path_nonnegative_weights_dispatch1( Graph &g, typename graph_traits::vertex_descriptor s, typename graph_traits::vertex_descriptor t, @@ -220,7 +220,7 @@ void successive_shortest_path_dispatch1( typedef typename graph_traits::edge_descriptor edge_descriptor; std::vector pred_vec(num_vertices(g)); - successive_shortest_path_dispatch2(g, s, t, capacity, residual_capacity, weight, rev, index, + successive_shortest_path_nonnegative_weights_dispatch2(g, s, t, capacity, residual_capacity, weight, rev, index, make_iterator_property_map(pred_vec.begin(), index), get_param(params, vertex_distance), params); } @@ -229,13 +229,13 @@ void successive_shortest_path_dispatch1( template -void successive_shortest_path( +void successive_shortest_path_nonnegative_weights( Graph &g, typename graph_traits::vertex_descriptor s, typename graph_traits::vertex_descriptor t, const bgl_named_params& params) { - return detail::successive_shortest_path_dispatch1(g, s, t, + return detail::successive_shortest_path_nonnegative_weights_dispatch1(g, s, t, choose_const_pmap(get_param(params, edge_capacity), g, edge_capacity), choose_pmap(get_param(params, edge_residual_capacity), g, edge_residual_capacity), @@ -247,12 +247,12 @@ void successive_shortest_path( } template -void successive_shortest_path( +void successive_shortest_path_nonnegative_weights( Graph &g, typename graph_traits::vertex_descriptor s, typename graph_traits::vertex_descriptor t) { bgl_named_params params(0); - successive_shortest_path(g, s, t, params); + successive_shortest_path_nonnegative_weights(g, s, t, params); } diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 35bf687d3..8311f146d 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -128,7 +128,7 @@ test-suite graph_test : [ compile filtered_graph_properties_dijkstra.cpp ] [ run vf2_sub_graph_iso_test.cpp ] [ run hawick_circuits.cpp ] - [ run successive_shortest_path_test.cpp ../../test/build//boost_unit_test_framework/static ] + [ run successive_shortest_path_nonnegative_weights_test.cpp ../../test/build//boost_unit_test_framework/static ] [ run cycle_canceling_test.cpp ../../test/build//boost_unit_test_framework/static ] ; diff --git a/test/cycle_canceling_test.cpp b/test/cycle_canceling_test.cpp index 05f6b101e..6c2ca89af 100644 --- a/test/cycle_canceling_test.cpp +++ b/test/cycle_canceling_test.cpp @@ -1,3 +1,12 @@ +//======================================================================= +// Copyright 2013 University of Warsaw. +// Authors: Piotr Wygocki +// +// 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) +//======================================================================= + #define BOOST_TEST_MODULE cycle_canceling_test #include diff --git a/test/min_cost_max_flow_utils.hpp b/test/min_cost_max_flow_utils.hpp index acb58b44d..78d17fd8d 100644 --- a/test/min_cost_max_flow_utils.hpp +++ b/test/min_cost_max_flow_utils.hpp @@ -1,10 +1,12 @@ -/** - * @file sample_graph_undirected.hpp - * @brief - * @author Piotr Wygocki - * @version 1.0 - * @date 2013-06-17 - */ +//======================================================================= +// Copyright 2013 University of Warsaw. +// Authors: Piotr Wygocki +// +// 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 SAMPLE_GRAPH_UNDIRECTED_HPP #define SAMPLE_GRAPH_UNDIRECTED_HPP diff --git a/test/successive_shortest_path_test.cpp b/test/successive_shortest_path_nonnegative_weights_test.cpp similarity index 63% rename from test/successive_shortest_path_test.cpp rename to test/successive_shortest_path_nonnegative_weights_test.cpp index e7551438f..fc7d1d647 100644 --- a/test/successive_shortest_path_test.cpp +++ b/test/successive_shortest_path_nonnegative_weights_test.cpp @@ -1,8 +1,17 @@ -#define BOOST_TEST_MODULE successive_shortest_path_test +//======================================================================= +// Copyright 2013 University of Warsaw. +// Authors: Piotr Wygocki +// +// 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) +//======================================================================= + +#define BOOST_TEST_MODULE successive_shortest_path_nonnegative_weights_test #include -#include +#include #include #include "min_cost_max_flow_utils.hpp" @@ -13,7 +22,7 @@ BOOST_AUTO_TEST_CASE(path_augmentation_def_test) { boost::SampleGraph::Graph g = boost::SampleGraph::getSampleGraph(s, t); - boost::successive_shortest_path(g, s, t); + boost::successive_shortest_path_nonnegative_weights(g, s, t); int cost = boost::find_flow_cost(g); BOOST_CHECK_EQUAL(cost, 29); @@ -24,7 +33,7 @@ BOOST_AUTO_TEST_CASE(path_augmentation_def_test2) { boost::SampleGraph::Graph g = boost::SampleGraph::getSampleGraph2(s, t); - boost::successive_shortest_path(g, s, t); + boost::successive_shortest_path_nonnegative_weights(g, s, t); int cost = boost::find_flow_cost(g); BOOST_CHECK_EQUAL(cost, 7); @@ -42,7 +51,7 @@ BOOST_AUTO_TEST_CASE(path_augmentation_test) { std::vector pred(N); - boost::successive_shortest_path(g, s, t, + boost::successive_shortest_path_nonnegative_weights(g, s, t, boost::distance_map(&dist[0]). predecessor_map(&pred[0]). distance_map2(&dist_prev[0]). From a3efa1c030b6ad3dd87a4335557c95c2be8bf108 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Thu, 5 Sep 2013 12:57:15 +0000 Subject: [PATCH 305/333] Added new test from potato_research of custom vertex index map in r_c_shortest_paths [SVN r85571] --- test/Jamfile.v2 | 1 + test/rcsp_custom_vertex_id.cpp | 109 +++++++++++++++++++++++++++++++++ 2 files changed, 110 insertions(+) create mode 100644 test/rcsp_custom_vertex_id.cpp diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 8311f146d..a41d23361 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -104,6 +104,7 @@ test-suite graph_test : ../../system/build : $(PLANAR_INPUT_FILES) ] [ run r_c_shortest_paths_test.cpp ] + [ run rcsp_custom_vertex_id.cpp ] [ run is_straight_line_draw_test.cpp ] [ run metric_tsp_approx.cpp : metric_tsp_approx.graph ] [ compile dimacs.cpp ] diff --git a/test/rcsp_custom_vertex_id.cpp b/test/rcsp_custom_vertex_id.cpp new file mode 100644 index 000000000..4a81548b1 --- /dev/null +++ b/test/rcsp_custom_vertex_id.cpp @@ -0,0 +1,109 @@ +//======================================================================= +// Author: Alberto Santini +// +// 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) +//======================================================================= + +#include +#include +#include +#include +#include +#include + +using std::vector; +using std::allocator; +using namespace boost; + +class VertexProperty { +public: + int property1; + int property2; + int id; + VertexProperty() {} + VertexProperty(const int property1, const int property2) : property1(property1), property2(property2) {} +}; + +class EdgeProperty { +public: + int cost; + int id; + EdgeProperty() {} + EdgeProperty(const int cost) : cost(cost) {} +}; + +typedef adjacency_list Graph; +typedef graph_traits::vertex_descriptor Vertex; +typedef graph_traits::edge_descriptor Edge; + +class ResourceCont { +public: + int res; + ResourceCont(const int res = 5) : res(res) {} + bool operator==(const ResourceCont& rc) const { return (res == rc.res); } + bool operator<(const ResourceCont& rc) const { return (res > rc.res); } +}; + +class LabelExt { +public: + bool operator()(const Graph& g, ResourceCont& rc, const ResourceCont& old_rc, Edge e) const { + rc.res = old_rc.res - g[e].cost; + return (rc.res > 0); + } +}; + +class LabelDom { +public: + bool operator()(const ResourceCont& rc1, const ResourceCont& rc2) const { + return (rc1 == rc2 || rc1 < rc2); + } +}; + +int main() { + VertexProperty vp1(1, 1); + VertexProperty vp2(5, 9); + VertexProperty vp3(4, 3); + EdgeProperty e12(1); + EdgeProperty e23(2); + + Graph g; + + Vertex v1 = add_vertex(g); g[v1] = vp1; + Vertex v2 = add_vertex(g); g[v2] = vp2; + Vertex v3 = add_vertex(g); g[v3] = vp3; + + add_edge(v1, v2, e12, g); + add_edge(v2, v3, e23, g); + + int index = 0; + BGL_FORALL_VERTICES(v, g, Graph) { + g[v].id = index++; + } + index = 0; + BGL_FORALL_EDGES(e, g, Graph) { + g[e].id = index++; + } + + typedef vector > OptPath; + typedef vector ParetoOpt; + + OptPath op; + ParetoOpt ol; + + r_c_shortest_paths( g, + get(&VertexProperty::id, g), + get(&EdgeProperty::id, g), + v1, + v2, + op, + ol, + ResourceCont(5), + LabelExt(), + LabelDom(), + allocator >(), + default_r_c_shortest_paths_visitor()); + + return 0; +} From 405e21d011279a83b258daccbffd443709ae9e49 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Thu, 5 Sep 2013 19:48:31 +0000 Subject: [PATCH 306/333] Applied patch from potato_research to add copyright notice [SVN r85580] --- test/rcsp_custom_vertex_id.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/test/rcsp_custom_vertex_id.cpp b/test/rcsp_custom_vertex_id.cpp index 4a81548b1..467709671 100644 --- a/test/rcsp_custom_vertex_id.cpp +++ b/test/rcsp_custom_vertex_id.cpp @@ -1,4 +1,5 @@ //======================================================================= +// Copyright (c) 2013 Alberto Santini // Author: Alberto Santini // // Distributed under the Boost Software License, Version 1.0. (See @@ -67,9 +68,9 @@ int main() { VertexProperty vp3(4, 3); EdgeProperty e12(1); EdgeProperty e23(2); - + Graph g; - + Vertex v1 = add_vertex(g); g[v1] = vp1; Vertex v2 = add_vertex(g); g[v2] = vp2; Vertex v3 = add_vertex(g); g[v3] = vp3; From e1bcb667b69f1deef2bbed606b6a5a51b51834bc Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Fri, 6 Sep 2013 03:54:57 +0000 Subject: [PATCH 307/333] Fixed ambiguous call [SVN r85583] --- test/cycle_test.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/cycle_test.hpp b/test/cycle_test.hpp index b60bc3073..537044733 100644 --- a/test/cycle_test.hpp +++ b/test/cycle_test.hpp @@ -38,7 +38,7 @@ namespace cycle_test_detail { // that the paths are valid. typename Path::const_iterator i, j, last = prior(p.end()); for (i = p.begin(); i != last; ++i) { - j = next(i); + j = boost::next(i); BOOST_ASSERT(edge(*i, *j, g).second); } BOOST_ASSERT(edge(p.back(), p.front(), g).second); From 93f4a862c31d3038eb017398f30680f5d1e61c2f Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Sat, 7 Sep 2013 16:34:49 +0000 Subject: [PATCH 308/333] Changed from iterator to const_iterator to fix VC++ issue [SVN r85593] --- include/boost/graph/hawick_circuits.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/boost/graph/hawick_circuits.hpp b/include/boost/graph/hawick_circuits.hpp index f2500354f..2ef04954f 100644 --- a/include/boost/graph/hawick_circuits.hpp +++ b/include/boost/graph/hawick_circuits.hpp @@ -110,7 +110,7 @@ struct hawick_circuits_from { typedef typename result_of< GetAdjacentVertices(Vertex, Graph const&) >::type AdjacentVertices; - typedef typename range_iterator::type AdjacencyIterator; + typedef typename range_iterator::type AdjacencyIterator; // The one_bit_color_map starts all white, i.e. not blocked. // Since we make that assumption (I looked at the implementation, but From 93f232252efc88bf73654677a01f09d5c4cceb85 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Sat, 7 Sep 2013 16:36:45 +0000 Subject: [PATCH 309/333] Fixed VC++ warning [SVN r85594] --- include/boost/graph/hawick_circuits.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/boost/graph/hawick_circuits.hpp b/include/boost/graph/hawick_circuits.hpp index 2ef04954f..93c12b5c7 100644 --- a/include/boost/graph/hawick_circuits.hpp +++ b/include/boost/graph/hawick_circuits.hpp @@ -105,7 +105,7 @@ struct hawick_circuits_from { typedef typename Traits::vertex_descriptor Vertex; typedef typename Traits::edge_descriptor Edge; typedef typename Traits::vertices_size_type VerticesSize; - typedef typename property_traits::reference VertexIndex; + typedef typename property_traits::value_type VertexIndex; typedef typename result_of< GetAdjacentVertices(Vertex, Graph const&) From fdd8e41b47d089e4c94920c8570e9b8777cb9c56 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Thu, 12 Sep 2013 14:01:50 +0000 Subject: [PATCH 310/333] Fixing tests (hopefully) for VC++ [SVN r85654] --- test/cycle_canceling_test.cpp | 4 +++- test/min_cost_max_flow_utils.hpp | 9 +++++++-- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/test/cycle_canceling_test.cpp b/test/cycle_canceling_test.cpp index 6c2ca89af..f618f61d1 100644 --- a/test/cycle_canceling_test.cpp +++ b/test/cycle_canceling_test.cpp @@ -51,8 +51,10 @@ BOOST_AUTO_TEST_CASE(cycle_canceling_test) { typedef boost::graph_traits::edge_descriptor edge_descriptor; std::vector pred(N); + boost::property_map::const_type idx = get(boost::vertex_index, g); + boost::edmonds_karp_max_flow(g, s, t); - boost::cycle_canceling(g, boost::distance_map(&dist[0]).predecessor_map(&pred[0]).vertex_index_map(boost::identity_property_map())); + boost::cycle_canceling(g, boost::distance_map(boost::make_iterator_property_map(dist.begin(), idx)).predecessor_map(boost::make_iterator_property_map(pred.begin(), idx)).vertex_index_map(idx)); int cost = boost::find_flow_cost(g); BOOST_CHECK_EQUAL(cost, 29); diff --git a/test/min_cost_max_flow_utils.hpp b/test/min_cost_max_flow_utils.hpp index 78d17fd8d..f68ad4fe2 100644 --- a/test/min_cost_max_flow_utils.hpp +++ b/test/min_cost_max_flow_utils.hpp @@ -10,6 +10,8 @@ #ifndef SAMPLE_GRAPH_UNDIRECTED_HPP #define SAMPLE_GRAPH_UNDIRECTED_HPP +#include +#include #include @@ -46,8 +48,11 @@ struct SampleGraph { Traits::edge_descriptor add(int v, int w, int weight, int capacity) { bool b; Traits::edge_descriptor e; - boost::tie(e, b) = add_edge(v, w, m_g); - assert(b); + boost::tie(e, b) = add_edge(vertex(v, m_g), vertex(w, m_g), m_g); + if (!b) { + std::cerr << "Edge between " << v << " and " << w << " already exists." << std::endl; + std::abort(); + } m_cap[e] = capacity; m_w[e] = weight; return e; From c40148ee94c149b81240317a9e0931f4087368d4 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Thu, 12 Sep 2013 15:14:36 +0000 Subject: [PATCH 311/333] Removed uses of pointers as property maps from tests and examples [SVN r85655] --- example/astar-cities.cpp | 3 +- example/bfs-example.cpp | 10 +++++-- example/bfs-example2.cpp | 18 ++++++++++-- example/canonical_ordering.cpp | 8 ++++-- example/dfs-example.cpp | 15 ++++++---- example/implicit_graph.cpp | 10 +++++-- test/astar_search_test.cpp | 7 ++++- test/bellman-test.cpp | 10 ++++--- test/bfs.cpp | 28 +++++++++++++++---- test/boykov_kolmogorov_max_flow_test.cpp | 3 +- test/dfs.cpp | 25 +++++++++++++---- test/dijkstra_heap_performance.cpp | 10 +++++-- test/make_connected_test.cpp | 16 ++++++++--- ...shortest_path_nonnegative_weights_test.cpp | 10 ++++--- test/transitive_closure_test.cpp | 10 +++---- test/undirected_dfs.cpp | 25 +++++++++++++---- 16 files changed, 154 insertions(+), 54 deletions(-) diff --git a/example/astar-cities.cpp b/example/astar-cities.cpp index a6c1eead5..48b3260f9 100644 --- a/example/astar-cities.cpp +++ b/example/astar-cities.cpp @@ -195,7 +195,8 @@ int main(int argc, char **argv) (g, start, distance_heuristic (locations, goal), - predecessor_map(&p[0]).distance_map(&d[0]). + predecessor_map(make_iterator_property_map(p.begin(), get(vertex_index, g))). + distance_map(make_iterator_property_map(d.begin(), get(vertex_index, g))). visitor(astar_goal_visitor(goal))); diff --git a/example/bfs-example.cpp b/example/bfs-example.cpp index 9ca03124d..0436204ce 100644 --- a/example/bfs-example.cpp +++ b/example/bfs-example.cpp @@ -55,13 +55,17 @@ main() // Typedefs typedef graph_traits < graph_t >::vertices_size_type Size; - typedef Size* Iiter; // a vector to hold the discover time property for each vertex std::vector < Size > dtime(num_vertices(g)); + typedef + iterator_property_map::iterator, + property_map::const_type> + dtime_pm_type; + dtime_pm_type dtime_pm(dtime.begin(), get(vertex_index, g)); Size time = 0; - bfs_time_visitor < Size * >vis(&dtime[0], time); + bfs_time_visitor < dtime_pm_type >vis(dtime_pm, time); breadth_first_search(g, vertex(s, g), visitor(vis)); // Use std::sort to order the vertices by their discover time @@ -69,7 +73,7 @@ main() integer_range < int >range(0, N); std::copy(range.begin(), range.end(), discover_order.begin()); std::sort(discover_order.begin(), discover_order.end(), - indirect_cmp < Iiter, std::less < Size > >(&dtime[0])); + indirect_cmp < dtime_pm_type, std::less < Size > >(dtime_pm)); std::cout << "order of discovery: "; for (int i = 0; i < N; ++i) diff --git a/example/bfs-example2.cpp b/example/bfs-example2.cpp index 7e6acc2b7..bc5d92abd 100644 --- a/example/bfs-example2.cpp +++ b/example/bfs-example2.cpp @@ -9,6 +9,7 @@ #include #include #include +#include #include @@ -30,6 +31,7 @@ template < typename TimeMap > class bfs_time_visitor:public default_bfs_visitor struct VertexProps { boost::default_color_type color; std::size_t discover_time; + unsigned int index; }; int @@ -64,7 +66,6 @@ main() // Typedefs typedef graph_traits::vertices_size_type Size; - typedef Size* Iiter; Size time = 0; typedef property_map::type dtime_map_t; @@ -75,17 +76,28 @@ main() // a vector to hold the discover time property for each vertex std::vector < Size > dtime(num_vertices(g)); + typedef + iterator_property_map::iterator, + property_map::type> + dtime_pm_type; graph_traits::vertex_iterator vi, vi_end; std::size_t c = 0; - for (boost::tie(vi, vi_end) = vertices(g); vi != vi_end; ++vi, ++c) + for (boost::tie(vi, vi_end) = vertices(g); vi != vi_end; ++vi, ++c) { dtime[c] = dtime_map[*vi]; + put(&VertexProps::index, g, *vi, c); + } + dtime_pm_type dtime_pm(dtime.begin(), get(&VertexProps::index, g)); // Use std::sort to order the vertices by their discover time std::vector::vertices_size_type > discover_order(N); integer_range < int >range(0, N); std::copy(range.begin(), range.end(), discover_order.begin()); std::sort(discover_order.begin(), discover_order.end(), - indirect_cmp < Iiter, std::less < Size > >(&dtime[0])); + make_indirect_cmp( + std::less(), + make_iterator_property_map( + dtime.begin(), + typed_identity_property_map()))); std::cout << "order of discovery: "; for (int i = 0; i < N; ++i) diff --git a/example/canonical_ordering.cpp b/example/canonical_ordering.cpp index 129af6ac2..947984255 100644 --- a/example/canonical_ordering.cpp +++ b/example/canonical_ordering.cpp @@ -64,7 +64,8 @@ int main(int argc, char** argv) std::vector embedding(num_vertices(g)); if (boyer_myrvold_planarity_test(boyer_myrvold_params::graph = g, boyer_myrvold_params::embedding = - &embedding[0] + make_iterator_property_map( + embedding.begin(), get(vertex_index, g)) ) ) std::cout << "Input graph is planar" << std::endl; @@ -75,7 +76,10 @@ int main(int argc, char** argv) ordering_storage_t; ordering_storage_t ordering; - planar_canonical_ordering(g, &embedding[0], std::back_inserter(ordering)); + planar_canonical_ordering(g, + make_iterator_property_map( + embedding.begin(), get(vertex_index, g)), + std::back_inserter(ordering)); ordering_storage_t::iterator oi, oi_end; oi_end = ordering.end(); diff --git a/example/dfs-example.cpp b/example/dfs-example.cpp index dc7b3f777..0117b81dc 100644 --- a/example/dfs-example.cpp +++ b/example/dfs-example.cpp @@ -58,14 +58,17 @@ main() graph_t g(edge_array, edge_array + sizeof(edge_array) / sizeof(E), N); #endif - // Typedefs - typedef size_type* Iiter; - // discover time and finish time properties std::vector < size_type > dtime(num_vertices(g)); std::vector < size_type > ftime(num_vertices(g)); + typedef + iterator_property_map::iterator, + property_map::const_type> + time_pm_type; + time_pm_type dtime_pm(dtime.begin(), get(vertex_index, g)); + time_pm_type ftime_pm(ftime.begin(), get(vertex_index, g)); size_type t = 0; - dfs_time_visitor < size_type * >vis(&dtime[0], &ftime[0], t); + dfs_time_visitor < time_pm_type >vis(dtime_pm, ftime_pm, t); depth_first_search(g, visitor(vis)); @@ -74,7 +77,7 @@ main() integer_range < size_type > r(0, N); std::copy(r.begin(), r.end(), discover_order.begin()); std::sort(discover_order.begin(), discover_order.end(), - indirect_cmp < Iiter, std::less < size_type > >(&dtime[0])); + indirect_cmp < time_pm_type, std::less < size_type > >(dtime_pm)); std::cout << "order of discovery: "; int i; for (i = 0; i < N; ++i) @@ -83,7 +86,7 @@ main() std::vector < size_type > finish_order(N); std::copy(r.begin(), r.end(), finish_order.begin()); std::sort(finish_order.begin(), finish_order.end(), - indirect_cmp < Iiter, std::less < size_type > >(&ftime[0])); + indirect_cmp < time_pm_type, std::less < size_type > >(ftime_pm)); std::cout << std::endl << "order of finish: "; for (i = 0; i < N; ++i) std::cout << name[finish_order[i]] << " "; diff --git a/example/implicit_graph.cpp b/example/implicit_graph.cpp index 5461d3dca..9b42e4d6b 100644 --- a/example/implicit_graph.cpp +++ b/example/implicit_graph.cpp @@ -527,10 +527,16 @@ int main (int argc, char const *argv[]) { vertex_descriptor source = 0; std::vector pred(num_vertices(g)); std::vector dist(num_vertices(g)); + iterator_property_map::iterator, + property_map::const_type> + pred_pm(pred.begin(), get(vertex_index, g)); + iterator_property_map::iterator, + property_map::const_type> + dist_pm(dist.begin(), get(vertex_index, g)); dijkstra_shortest_paths(g, source, - predecessor_map(&pred[0]). - distance_map(&dist[0]) ); + predecessor_map(pred_pm). + distance_map(dist_pm) ); std::cout << "Dijkstra search from vertex " << source << std::endl; for (boost::tie(vi, vi_end) = vertices(g); vi != vi_end; ++vi) { diff --git a/test/astar_search_test.cpp b/test/astar_search_test.cpp index d5fca3f4d..72f29150d 100644 --- a/test/astar_search_test.cpp +++ b/test/astar_search_test.cpp @@ -184,13 +184,18 @@ int main(int, char **) vector p(num_vertices(g)); vector d(num_vertices(g)); + + boost::property_map::const_type + idx = get(boost::vertex_index, g); + try { // call astar named parameter interface astar_search (g, start, distance_heuristic (locations, goal), - predecessor_map(&p[0]).distance_map(&d[0]). + predecessor_map(make_iterator_property_map(p.begin(), idx)). + distance_map(make_iterator_property_map(d.begin(), idx)). visitor(astar_goal_visitor(goal)).distance_inf(my_float((std::numeric_limits::max)()))); diff --git a/test/bellman-test.cpp b/test/bellman-test.cpp index 7fa948aaf..a285b31d7 100644 --- a/test/bellman-test.cpp +++ b/test/bellman-test.cpp @@ -56,8 +56,8 @@ int test_main(int, char*[]) bool const r = bellman_ford_shortest_paths (g, int (numVertex), weight_pmap, - &parent[0], - &distance[0], + boost::make_iterator_property_map(parent.begin(), get(boost::vertex_index, g)), + boost::make_iterator_property_map(distance.begin(), get(boost::vertex_index, g)), closed_plus(), std::less(), default_bellman_visitor()); @@ -81,8 +81,10 @@ int test_main(int, char*[]) std::vector distance2(numVertex, 17); bool const r2 = bellman_ford_shortest_paths (g, - weight_map(weight_pmap).distance_map(&distance2[0]). - predecessor_map(&parent2[0]).root_vertex(s)); + weight_map(weight_pmap). + distance_map(boost::make_iterator_property_map(distance2.begin(), get(boost::vertex_index, g))). + predecessor_map(boost::make_iterator_property_map(parent2.begin(), get(boost::vertex_index, g))). + root_vertex(s)); if (r2) { for(int i = 0; i < numVertex; ++i) { std::cout << name[i] << ": "; diff --git a/test/bfs.cpp b/test/bfs.cpp index 7e59ac9b3..615999a9f 100644 --- a/test/bfs.cpp +++ b/test/bfs.cpp @@ -140,20 +140,38 @@ struct bfs_test parent[*ui] = *ui; std::vector color(i); + // Get vertex index map + typedef typename boost::property_map::const_type idx_type; + idx_type idx = get(boost::vertex_index, g); + + // Make property maps from vectors + typedef + boost::iterator_property_map::iterator, idx_type> + distance_pm_type; + distance_pm_type distance_pm(distance.begin(), idx); + typedef + boost::iterator_property_map::iterator, idx_type> + parent_pm_type; + parent_pm_type parent_pm(parent.begin(), idx); + typedef + boost::iterator_property_map::iterator, idx_type> + color_pm_type; + color_pm_type color_pm(color.begin(), idx); + // Create the testing visitor. - bfs_testing_visitor - vis(start, &distance[0], &parent[0], &color[0]); + bfs_testing_visitor + vis(start, distance_pm, parent_pm, color_pm); boost::breadth_first_search(g, start, visitor(vis). - color_map(&color[0])); + color_map(color_pm)); // All white vertices should be unreachable from the source. for (boost::tie(ui, ui_end) = vertices(g); ui != ui_end; ++ui) if (color[*ui] == Color::white()) { std::vector color2(i, Color::white()); - BOOST_CHECK(!boost::is_reachable(start, *ui, g, &color2[0])); + BOOST_CHECK(!boost::is_reachable(start, *ui, g, color_pm_type(color2.begin(), idx))); } // The shortest path to a child should be one longer than diff --git a/test/boykov_kolmogorov_max_flow_test.cpp b/test/boykov_kolmogorov_max_flow_test.cpp index 17607fcef..1f0ce5892 100644 --- a/test/boykov_kolmogorov_max_flow_test.cpp +++ b/test/boykov_kolmogorov_max_flow_test.cpp @@ -218,7 +218,8 @@ long test_overloads(int n_verts, int n_edges, std::size_t seed){ get(edge_capacity,g), get(edge_residual_capacity,g), get(edge_reverse,g), - &(color_vec[0]), + boost::make_iterator_property_map( + color_vec.begin(), get(vertex_index, g)), get(vertex_index,g), src, sink); diff --git a/test/dfs.cpp b/test/dfs.cpp index 7f458e0a8..d958ba441 100644 --- a/test/dfs.cpp +++ b/test/dfs.cpp @@ -122,9 +122,24 @@ struct dfs_test std::vector discover_time(num_vertices(g)), finish_time(num_vertices(g)); - dfs_test_visitor vis(color, &parent[0], - &discover_time[0], &finish_time[0]); + // Get vertex index map + typedef typename boost::property_map::const_type idx_type; + idx_type idx = get(boost::vertex_index, g); + + typedef + boost::iterator_property_map::iterator, idx_type> + parent_pm_type; + parent_pm_type parent_pm(parent.begin(), idx); + typedef + boost::iterator_property_map::iterator, idx_type> + time_pm_type; + time_pm_type discover_time_pm(discover_time.begin(), idx); + time_pm_type finish_time_pm(finish_time.begin(), idx); + + dfs_test_visitor + vis(color, parent_pm, + discover_time_pm, finish_time_pm); boost::depth_first_search(g, visitor(vis).color_map(color)); @@ -142,10 +157,10 @@ struct dfs_test || finish_time[v] < discover_time[u] || (discover_time[v] < discover_time[u] && finish_time[u] < finish_time[v] - && boost::is_descendant(u, v, &parent[0])) + && boost::is_descendant(u, v, parent_pm)) || (discover_time[u] < discover_time[v] && finish_time[v] < finish_time[u] - && boost::is_descendant(v, u, &parent[0])) + && boost::is_descendant(v, u, parent_pm)) ); } } diff --git a/test/dijkstra_heap_performance.cpp b/test/dijkstra_heap_performance.cpp index 72d40f9cc..2cab3fbf2 100644 --- a/test/dijkstra_heap_performance.cpp +++ b/test/dijkstra_heap_performance.cpp @@ -117,7 +117,9 @@ int main(int argc, char* argv[]) dijkstra_relaxed_heap = false; #endif dijkstra_shortest_paths(g, vertex(0, g), - distance_map(&binary_heap_distances[0])); + distance_map( + boost::make_iterator_property_map( + binary_heap_distances.begin(), get(boost::vertex_index, g)))); double binary_heap_time = t.elapsed(); std::cout << binary_heap_time << " seconds.\n"; @@ -135,7 +137,9 @@ int main(int argc, char* argv[]) dijkstra_relaxed_heap = true; #endif dijkstra_shortest_paths(g, vertex(0, g), - distance_map(&relaxed_heap_distances[0])); + distance_map( + boost::make_iterator_property_map( + relaxed_heap_distances.begin(), get(boost::vertex_index, g)))); double relaxed_heap_time = t.elapsed(); std::cout << relaxed_heap_time << " seconds.\n" << "Speedup = " << (binary_heap_time / relaxed_heap_time) << ".\n"; @@ -159,7 +163,7 @@ int main(int argc, char* argv[]) dijkstra_shortest_paths_no_color_map (g, vertex(0, g), boost::dummy_property_map(), - boost::make_iterator_property_map(&no_color_map_distances[0], + boost::make_iterator_property_map(no_color_map_distances.begin(), get(boost::vertex_index, g), 0.), get(boost::edge_weight, g), diff --git a/test/make_connected_test.cpp b/test/make_connected_test.cpp index 40517f0f7..bc4a9104d 100644 --- a/test/make_connected_test.cpp +++ b/test/make_connected_test.cpp @@ -114,10 +114,14 @@ int test_main(int, char* []) make_disconnected_cycles(gVV, num_cycles, cycle_size); reset_edge_index(gVV); std::vector gVV_components(num_vertices(gVV)); - BOOST_CHECK(connected_components(gVV, &gVV_components[0]) == + boost::iterator_property_map< + std::vector::iterator, + typename boost::property_map::const_type + > gVV_components_pm(gVV_components.begin(), get(boost::vertex_index, gVV)); + BOOST_CHECK(connected_components(gVV, gVV_components_pm) == static_cast(num_cycles)); make_connected(gVV); - BOOST_CHECK(connected_components(gVV, &gVV_components[0]) == 1); + BOOST_CHECK(connected_components(gVV, gVV_components_pm) == 1); BOOST_CHECK(num_edges(gVV) == num_cycles * cycle_size + num_cycles - 1); LVgraph_t gLV; @@ -126,10 +130,14 @@ int test_main(int, char* []) make_disconnected_cycles(gLV, num_cycles, cycle_size); reset_edge_index(gLV); std::vector gLV_components(num_vertices(gLV)); - BOOST_CHECK(connected_components(gLV, &gLV_components[0]) == + boost::iterator_property_map< + std::vector::iterator, + typename boost::property_map::const_type + > gLV_components_pm(gLV_components.begin(), get(boost::vertex_index, gLV)); + BOOST_CHECK(connected_components(gLV, gLV_components_pm) == static_cast(num_cycles)); make_connected(gLV); - BOOST_CHECK(connected_components(gLV, &gLV_components[0]) == 1); + BOOST_CHECK(connected_components(gLV, gLV_components_pm) == 1); BOOST_CHECK(num_edges(gLV) == num_cycles * cycle_size + num_cycles - 1); VLgraph_t gVL; diff --git a/test/successive_shortest_path_nonnegative_weights_test.cpp b/test/successive_shortest_path_nonnegative_weights_test.cpp index fc7d1d647..8437def0a 100644 --- a/test/successive_shortest_path_nonnegative_weights_test.cpp +++ b/test/successive_shortest_path_nonnegative_weights_test.cpp @@ -50,12 +50,14 @@ BOOST_AUTO_TEST_CASE(path_augmentation_test) { typedef boost::graph_traits::edge_descriptor edge_descriptor; std::vector pred(N); + boost::property_map::const_type + idx = get(boost::vertex_index, g); boost::successive_shortest_path_nonnegative_weights(g, s, t, - boost::distance_map(&dist[0]). - predecessor_map(&pred[0]). - distance_map2(&dist_prev[0]). - vertex_index_map(boost::identity_property_map())); + boost::distance_map(boost::make_iterator_property_map(dist.begin(), idx)). + predecessor_map(boost::make_iterator_property_map(pred.begin(), idx)). + distance_map2(boost::make_iterator_property_map(dist_prev.begin(), idx)). + vertex_index_map(idx)); int cost = boost::find_flow_cost(g); BOOST_CHECK_EQUAL(cost, 29); diff --git a/test/transitive_closure_test.cpp b/test/transitive_closure_test.cpp index 16ec350f8..cdae591dc 100644 --- a/test/transitive_closure_test.cpp +++ b/test/transitive_closure_test.cpp @@ -74,7 +74,7 @@ bool check_transitive_closure(Graph& g, GraphTC& tc) typename graph_traits::adjacency_iterator k, k_end; for (boost::tie(k, k_end) = adjacent_vertices(*i, g); k != k_end; ++k) { std::vector color_map_vec(num_vertices(g)); - if (is_reachable(*k, *i, g, &color_map_vec[0])) { + if (is_reachable(*k, *i, g, boost::make_iterator_property_map(color_map_vec.begin(), get(boost::vertex_index, g)))) { can_reach = true; break; } @@ -93,7 +93,7 @@ bool check_transitive_closure(Graph& g, GraphTC& tc) } } else { std::vector color_map_vec(num_vertices(g)); - if (is_reachable(*i, *j, g, &color_map_vec[0])) { + if (is_reachable(*i, *j, g, boost::make_iterator_property_map(color_map_vec.begin(), get(boost::vertex_index, g)))) { if (num_tc != 1) return false; } else { @@ -117,16 +117,16 @@ bool test(int n, double p) { progress_timer t; cout << "transitive_closure" << endl; - transitive_closure(g1, g1_tc, vertex_index_map(identity_property_map())); + transitive_closure(g1, g1_tc, vertex_index_map(get(boost::vertex_index, g1))); } if(check_transitive_closure(g1, g1_tc)) return true; else { cout << "Original graph was "; - print_graph(g1, identity_property_map()); + print_graph(g1, get(boost::vertex_index, g1)); cout << "Result is "; - print_graph(g1_tc, identity_property_map()); + print_graph(g1_tc, get(boost::vertex_index, g1_tc)); return false; } } diff --git a/test/undirected_dfs.cpp b/test/undirected_dfs.cpp index b9d4285ff..74e7d3884 100644 --- a/test/undirected_dfs.cpp +++ b/test/undirected_dfs.cpp @@ -130,9 +130,24 @@ struct dfs_test std::vector discover_time(num_vertices(g)), finish_time(num_vertices(g)); - dfs_test_visitor vis(color, &parent[0], - &discover_time[0], &finish_time[0]); + // Get vertex index map + typedef typename boost::property_map::const_type idx_type; + idx_type idx = get(boost::vertex_index, g); + + typedef + boost::iterator_property_map::iterator, idx_type> + parent_pm_type; + parent_pm_type parent_pm(parent.begin(), idx); + typedef + boost::iterator_property_map::iterator, idx_type> + time_pm_type; + time_pm_type discover_time_pm(discover_time.begin(), idx); + time_pm_type finish_time_pm(finish_time.begin(), idx); + + dfs_test_visitor + vis(color, parent_pm, + discover_time_pm, finish_time_pm); boost::undirected_dfs(g, visitor(vis).color_map(color) .edge_color_map(e_color)); @@ -155,10 +170,10 @@ struct dfs_test || finish_time[v] < discover_time[u] || (discover_time[v] < discover_time[u] && finish_time[u] < finish_time[v] - && boost::is_descendant(u, v, &parent[0])) + && boost::is_descendant(u, v, parent_pm)) || (discover_time[u] < discover_time[v] && finish_time[v] < finish_time[u] - && boost::is_descendant(v, u, &parent[0])) + && boost::is_descendant(v, u, parent_pm)) ); } } From f97c2ee74673234fc02efadd9e921a8357c40479 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Fri, 13 Sep 2013 14:48:17 +0000 Subject: [PATCH 312/333] Attached patch from Piotr Wygocki for min-cost max-flow [SVN r85661] --- example/cycle_canceling_example.cpp | 6 +-- ...rtest_path_nonnegative_weights_example.cpp | 6 +-- test/cycle_canceling_test.cpp | 17 ++++---- test/min_cost_max_flow_utils.hpp | 41 ++++++++++--------- ...shortest_path_nonnegative_weights_test.cpp | 17 ++++---- 5 files changed, 45 insertions(+), 42 deletions(-) diff --git a/example/cycle_canceling_example.cpp b/example/cycle_canceling_example.cpp index f1e02dd7f..46e85f149 100644 --- a/example/cycle_canceling_example.cpp +++ b/example/cycle_canceling_example.cpp @@ -14,9 +14,9 @@ int main() { - unsigned s,t; - boost::SampleGraph::Graph g - = boost::SampleGraph::getSampleGraph(s, t); + boost::SampleGraph::vertex_descriptor s,t; + boost::SampleGraph::Graph g; + boost::SampleGraph::getSampleGraph(g, s, t); boost::edmonds_karp_max_flow(g, s, t); boost::cycle_canceling(g); diff --git a/example/successive_shortest_path_nonnegative_weights_example.cpp b/example/successive_shortest_path_nonnegative_weights_example.cpp index f877d40c9..0edc3710f 100644 --- a/example/successive_shortest_path_nonnegative_weights_example.cpp +++ b/example/successive_shortest_path_nonnegative_weights_example.cpp @@ -14,9 +14,9 @@ int main() { - unsigned s,t; - boost::SampleGraph::Graph g - = boost::SampleGraph::getSampleGraph(s, t); + boost::SampleGraph::vertex_descriptor s,t; + boost::SampleGraph::Graph g; + boost::SampleGraph::getSampleGraph(g, s, t); boost::successive_shortest_path_nonnegative_weights(g, s, t); diff --git a/test/cycle_canceling_test.cpp b/test/cycle_canceling_test.cpp index f618f61d1..d2acc802b 100644 --- a/test/cycle_canceling_test.cpp +++ b/test/cycle_canceling_test.cpp @@ -18,9 +18,9 @@ BOOST_AUTO_TEST_CASE(cycle_canceling_def_test) { - unsigned s,t; - boost::SampleGraph::Graph g - = boost::SampleGraph::getSampleGraph(s, t); + boost::SampleGraph::vertex_descriptor s,t; + boost::SampleGraph::Graph g; + boost::SampleGraph::getSampleGraph(g, s, t); boost::edmonds_karp_max_flow(g, s, t); boost::cycle_canceling(g); @@ -30,9 +30,9 @@ BOOST_AUTO_TEST_CASE(cycle_canceling_def_test) { } BOOST_AUTO_TEST_CASE(path_augmentation_def_test2) { - unsigned s,t; - boost::SampleGraph::Graph g - = boost::SampleGraph::getSampleGraph2(s, t); + boost::SampleGraph::vertex_descriptor s,t; + boost::SampleGraph::Graph g; + boost::SampleGraph::getSampleGraph2(g, s, t); boost::edmonds_karp_max_flow(g, s, t); boost::cycle_canceling(g); @@ -42,9 +42,10 @@ BOOST_AUTO_TEST_CASE(path_augmentation_def_test2) { } BOOST_AUTO_TEST_CASE(cycle_canceling_test) { - unsigned s,t; + boost::SampleGraph::vertex_descriptor s,t; typedef boost::SampleGraph::Graph Graph; - Graph g = boost::SampleGraph::getSampleGraph(s, t); + boost::SampleGraph::Graph g; + boost::SampleGraph::getSampleGraph(g, s, t); int N = num_vertices(g); std::vector dist(N); diff --git a/test/min_cost_max_flow_utils.hpp b/test/min_cost_max_flow_utils.hpp index f68ad4fe2..37c97953c 100644 --- a/test/min_cost_max_flow_utils.hpp +++ b/test/min_cost_max_flow_utils.hpp @@ -19,7 +19,7 @@ namespace boost { struct SampleGraph { typedef adjacency_list_traits < vecS, vecS, directedS > Traits; - typedef adjacency_list < listS, vecS, directedS, no_property, + typedef adjacency_list < vecS, vecS, directedS, no_property, property < edge_capacity_t, long, property < edge_residual_capacity_t, long, property < edge_reverse_t, Traits::edge_descriptor, @@ -30,14 +30,15 @@ struct SampleGraph { typedef property_map < Graph, edge_capacity_t >::type Capacity; typedef property_map < Graph, edge_residual_capacity_t >::type ResidualCapacity; typedef property_map < Graph, edge_weight_t >::type Weight; + typedef property_map < Graph, edge_reverse_t>::type Reversed; + typedef boost::graph_traits::vertices_size_type size_type; + typedef Traits::vertex_descriptor vertex_descriptor; - - template class EdgeAdder { public: EdgeAdder(Graph & g, Weight & w, Capacity & c, Reversed & rev, ResidualCapacity & residualCapacity) : m_g(g), m_w(w), m_cap(c), m_resCap(residualCapacity), m_rev(rev) {} - void addEdge(int v, int w, int weight, int capacity) { + void addEdge(vertex_descriptor v, vertex_descriptor w, long weight, long capacity) { Traits::edge_descriptor e,f; e = add(v, w, weight, capacity); f = add(w, v, -weight, 0); @@ -45,7 +46,7 @@ struct SampleGraph { m_rev[f] = e; } private: - Traits::edge_descriptor add(int v, int w, int weight, int capacity) { + Traits::edge_descriptor add(vertex_descriptor v, vertex_descriptor w, long weight, long capacity) { bool b; Traits::edge_descriptor e; boost::tie(e, b) = add_edge(vertex(v, m_g), vertex(w, m_g), m_g); @@ -65,11 +66,13 @@ struct SampleGraph { }; - static Graph getSampleGraph(unsigned & s, unsigned & t) { - const boost::graph_traits::vertices_size_type N(6); + static void getSampleGraph(Graph &g, vertex_descriptor & s, vertex_descriptor & t) { + size_type N(6); typedef property_map < Graph, edge_reverse_t >::type Reversed; - Graph g(N); + for(size_type i = 0; i < N; ++i){ + add_vertex(g); + } Capacity capacity = get(edge_capacity, g); Reversed rev = get(edge_reverse, g); ResidualCapacity residual_capacity = get(edge_residual_capacity, g); @@ -78,8 +81,7 @@ struct SampleGraph { s = 0; t = 5; - EdgeAdder - ea(g, weight, capacity, rev, residual_capacity); + EdgeAdder ea(g, weight, capacity, rev, residual_capacity); ea.addEdge(0, 1, 4 ,2); ea.addEdge(0, 2, 2 ,2); @@ -91,15 +93,17 @@ struct SampleGraph { ea.addEdge(3, 5, 4 ,20); ea.addEdge(4, 5, 2 ,20); - - return g; } - - static Graph getSampleGraph2(unsigned & s, unsigned & t) { + + static void getSampleGraph2(Graph &g, vertex_descriptor & s, vertex_descriptor & t) { + const boost::graph_traits::vertices_size_type N(5); typedef property_map < Graph, edge_reverse_t >::type Reversed; - Graph g(N); + for(size_type i = 0; i < N; ++i){ + add_vertex(g); + } + Capacity capacity = get(edge_capacity, g); Reversed rev = get(edge_reverse, g); ResidualCapacity residual_capacity = get(edge_residual_capacity, g); @@ -108,8 +112,7 @@ struct SampleGraph { s = 0; t = 4; - EdgeAdder - ea(g, weight, capacity, rev, residual_capacity); + EdgeAdder ea(g, weight, capacity, rev, residual_capacity); ea.addEdge(0, 1, 4 ,2); ea.addEdge(0, 2, 2 ,2); @@ -117,7 +120,7 @@ struct SampleGraph { ea.addEdge(2, 3, 1 ,1); ea.addEdge(2, 4, 1 ,1); ea.addEdge(3, 4, 1 ,1); - + ea.addEdge(1, 0, 2 ,2); ea.addEdge(2, 0, 1 ,1); @@ -125,8 +128,6 @@ struct SampleGraph { ea.addEdge(3, 2, 1 ,1); ea.addEdge(4, 2, 2 ,2); ea.addEdge(4, 3, 1 ,3); - - return g; } }; } //boost diff --git a/test/successive_shortest_path_nonnegative_weights_test.cpp b/test/successive_shortest_path_nonnegative_weights_test.cpp index 8437def0a..cf9fe50c1 100644 --- a/test/successive_shortest_path_nonnegative_weights_test.cpp +++ b/test/successive_shortest_path_nonnegative_weights_test.cpp @@ -18,9 +18,9 @@ BOOST_AUTO_TEST_CASE(path_augmentation_def_test) { - unsigned s,t; - boost::SampleGraph::Graph g - = boost::SampleGraph::getSampleGraph(s, t); + boost::SampleGraph::vertex_descriptor s,t; + boost::SampleGraph::Graph g; + boost::SampleGraph::getSampleGraph(g, s, t); boost::successive_shortest_path_nonnegative_weights(g, s, t); @@ -29,9 +29,9 @@ BOOST_AUTO_TEST_CASE(path_augmentation_def_test) { } BOOST_AUTO_TEST_CASE(path_augmentation_def_test2) { - unsigned s,t; - boost::SampleGraph::Graph g - = boost::SampleGraph::getSampleGraph2(s, t); + boost::SampleGraph::vertex_descriptor s,t; + boost::SampleGraph::Graph g; + boost::SampleGraph::getSampleGraph2(g, s, t); boost::successive_shortest_path_nonnegative_weights(g, s, t); @@ -40,9 +40,10 @@ BOOST_AUTO_TEST_CASE(path_augmentation_def_test2) { } BOOST_AUTO_TEST_CASE(path_augmentation_test) { - unsigned s,t; + boost::SampleGraph::vertex_descriptor s,t; typedef boost::SampleGraph::Graph Graph; - Graph g = boost::SampleGraph::getSampleGraph(s, t); + Graph g; + boost::SampleGraph::getSampleGraph(g, s, t); int N = boost::num_vertices(g); std::vector dist(N); From 51d3fe8aedbff70407f1e147d7610b6cc640d62e Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Mon, 23 Sep 2013 15:30:22 +0000 Subject: [PATCH 313/333] Cleaned up property maps and added a bunch of error checking asserts [SVN r85853] --- include/boost/graph/r_c_shortest_paths.hpp | 112 ++++++++++++++------- 1 file changed, 78 insertions(+), 34 deletions(-) diff --git a/include/boost/graph/r_c_shortest_paths.hpp b/include/boost/graph/r_c_shortest_paths.hpp index 081393ee9..afa50cf08 100644 --- a/include/boost/graph/r_c_shortest_paths.hpp +++ b/include/boost/graph/r_c_shortest_paths.hpp @@ -13,6 +13,8 @@ #include #include +#include +#include namespace boost { @@ -34,7 +36,8 @@ struct r_c_shortest_paths_label pred_edge( ed ), resident_vertex( vd ), b_is_dominated( false ), - b_is_processed( false ) + b_is_processed( false ), + b_is_valid( true ) {} r_c_shortest_paths_label& operator=( const r_c_shortest_paths_label& other ) { @@ -51,6 +54,7 @@ struct r_c_shortest_paths_label const typename graph_traits::vertex_descriptor resident_vertex; bool b_is_dominated; bool b_is_processed; + bool b_is_valid; }; // r_c_shortest_paths_label template @@ -58,6 +62,7 @@ inline bool operator== ( const r_c_shortest_paths_label& l1, const r_c_shortest_paths_label& l2 ) { + assert (l1.b_is_valid && l2.b_is_valid); return l1.cumulated_resource_consumption == l2.cumulated_resource_consumption; } @@ -67,6 +72,7 @@ inline bool operator!= ( const r_c_shortest_paths_label& l1, const r_c_shortest_paths_label& l2 ) { + assert (l1.b_is_valid && l2.b_is_valid); return !( l1 == l2 ); } @@ -76,6 +82,7 @@ inline bool operator< ( const r_c_shortest_paths_label& l1, const r_c_shortest_paths_label& l2 ) { + assert (l1.b_is_valid && l2.b_is_valid); return l1.cumulated_resource_consumption < l2.cumulated_resource_consumption; } @@ -85,6 +92,7 @@ inline bool operator> ( const r_c_shortest_paths_label& l1, const r_c_shortest_paths_label& l2 ) { + assert (l1.b_is_valid && l2.b_is_valid); return l2.cumulated_resource_consumption < l1.cumulated_resource_consumption; } @@ -94,6 +102,7 @@ inline bool operator<= ( const r_c_shortest_paths_label& l1, const r_c_shortest_paths_label& l2 ) { + assert (l1.b_is_valid && l2.b_is_valid); return l1 < l2 || l1 == l2; } @@ -103,6 +112,7 @@ inline bool operator>= ( const r_c_shortest_paths_label& l1, const r_c_shortest_paths_label& l2 ) { + assert (l1.b_is_valid && l2.b_is_valid); return l2 < l1 || l1 == l2; } @@ -185,9 +195,6 @@ void r_c_shortest_paths_dispatch pareto_optimal_resource_containers.clear(); pareto_optimal_solutions.clear(); - typedef typename boost::graph_traits::vertices_size_type - vertices_size_type; - size_t i_label_num = 0; typedef typename @@ -216,18 +223,40 @@ void r_c_shortest_paths_dispatch Splabel splabel_first_label = Splabel( first_label ); unprocessed_labels.push( splabel_first_label ); - std::vector > vec_vertex_labels( num_vertices( g ) ); - vec_vertex_labels[vertex_index_map[s]].push_back( splabel_first_label ); - std::vector::iterator> - vec_last_valid_positions_for_dominance( num_vertices( g ) ); - for( vertices_size_type i = 0; i < num_vertices( g ); ++i ) - vec_last_valid_positions_for_dominance[i] = vec_vertex_labels[i].begin(); - std::vector vec_last_valid_index_for_dominance( num_vertices( g ), 0 ); + std::vector > vec_vertex_labels_data( num_vertices( g ) ); + iterator_property_map >::iterator, + VertexIndexMap> + vec_vertex_labels(vec_vertex_labels_data.begin(), vertex_index_map); + vec_vertex_labels[s].push_back( splabel_first_label ); + typedef + std::vector::iterator> + vec_last_valid_positions_for_dominance_data_type; + vec_last_valid_positions_for_dominance_data_type + vec_last_valid_positions_for_dominance_data( num_vertices( g ) ); + iterator_property_map< + typename vec_last_valid_positions_for_dominance_data_type::iterator, + VertexIndexMap> + vec_last_valid_positions_for_dominance + (vec_last_valid_positions_for_dominance_data.begin(), + vertex_index_map); + BGL_FORALL_VERTICES_T(v, g, Graph) { + put(vec_last_valid_positions_for_dominance, v, vec_vertex_labels[v].begin()); + } + std::vector vec_last_valid_index_for_dominance_data( num_vertices( g ), 0 ); + iterator_property_map::iterator, VertexIndexMap> + vec_last_valid_index_for_dominance + (vec_last_valid_index_for_dominance_data.begin(), vertex_index_map); std::vector - b_vec_vertex_already_checked_for_dominance( num_vertices( g ), false ); + b_vec_vertex_already_checked_for_dominance_data( num_vertices( g ), false ); + iterator_property_map::iterator, VertexIndexMap> + b_vec_vertex_already_checked_for_dominance + (b_vec_vertex_already_checked_for_dominance_data.begin(), + vertex_index_map); + while( !unprocessed_labels.empty() && vis.on_enter_loop(unprocessed_labels, g) ) { Splabel cur_label = unprocessed_labels.top(); + assert (cur_label->b_is_valid); unprocessed_labels.pop(); vis.on_label_popped( *cur_label, g ); // an Splabel object in unprocessed_labels and the respective Splabel @@ -242,13 +271,15 @@ void r_c_shortest_paths_dispatch // if there is a chance that extending the // label leads to new undominated labels, which in turn is possible only // if the label to be extended is undominated + assert (cur_label->b_is_valid); if( !cur_label->b_is_dominated ) { - vertices_size_type i_cur_resident_vertex_num = get(vertex_index_map, cur_label->resident_vertex); + typename boost::graph_traits::vertex_descriptor + i_cur_resident_vertex = cur_label->resident_vertex; std::list& list_labels_cur_vertex = - vec_vertex_labels[i_cur_resident_vertex_num]; + get(vec_vertex_labels, i_cur_resident_vertex); if( list_labels_cur_vertex.size() >= 2 - && vec_last_valid_index_for_dominance[i_cur_resident_vertex_num] + && vec_last_valid_index_for_dominance[i_cur_resident_vertex] < list_labels_cur_vertex.size() ) { typename std::list::iterator outer_iter = @@ -257,14 +288,14 @@ void r_c_shortest_paths_dispatch while( outer_iter != list_labels_cur_vertex.end() ) { Splabel cur_outer_splabel = *outer_iter; + assert (cur_outer_splabel->b_is_valid); typename std::list::iterator inner_iter = outer_iter; if( !b_outer_iter_at_or_beyond_last_valid_pos_for_dominance && outer_iter == - vec_last_valid_positions_for_dominance - [i_cur_resident_vertex_num] ) + get(vec_last_valid_positions_for_dominance, + i_cur_resident_vertex) ) b_outer_iter_at_or_beyond_last_valid_pos_for_dominance = true; - if( !b_vec_vertex_already_checked_for_dominance - [i_cur_resident_vertex_num] + if( !get(b_vec_vertex_already_checked_for_dominance, i_cur_resident_vertex) || b_outer_iter_at_or_beyond_last_valid_pos_for_dominance ) { ++inner_iter; @@ -272,14 +303,15 @@ void r_c_shortest_paths_dispatch else { inner_iter = - vec_last_valid_positions_for_dominance - [i_cur_resident_vertex_num]; + get(vec_last_valid_positions_for_dominance, + i_cur_resident_vertex); ++inner_iter; } bool b_outer_iter_erased = false; while( inner_iter != list_labels_cur_vertex.end() ) { Splabel cur_inner_splabel = *inner_iter; + assert (cur_inner_splabel->b_is_valid); if( dominance( cur_outer_splabel-> cumulated_resource_consumption, cur_inner_splabel-> @@ -290,6 +322,7 @@ void r_c_shortest_paths_dispatch list_labels_cur_vertex.erase( buf ); if( cur_inner_splabel->b_is_processed ) { + cur_inner_splabel->b_is_valid = false; l_alloc.destroy( cur_inner_splabel.get() ); l_alloc.deallocate( cur_inner_splabel.get(), 1 ); } @@ -308,8 +341,10 @@ void r_c_shortest_paths_dispatch ++outer_iter; list_labels_cur_vertex.erase( buf ); b_outer_iter_erased = true; + assert (cur_outer_splabel->b_is_valid); if( cur_outer_splabel->b_is_processed ) { + cur_outer_splabel->b_is_valid = false; l_alloc.destroy( cur_outer_splabel.get() ); l_alloc.deallocate( cur_outer_splabel.get(), 1 ); } @@ -322,33 +357,37 @@ void r_c_shortest_paths_dispatch ++outer_iter; } if( list_labels_cur_vertex.size() > 1 ) - vec_last_valid_positions_for_dominance[i_cur_resident_vertex_num] = - (--(list_labels_cur_vertex.end())); + put(vec_last_valid_positions_for_dominance, i_cur_resident_vertex, + (--(list_labels_cur_vertex.end()))); else - vec_last_valid_positions_for_dominance[i_cur_resident_vertex_num] = - list_labels_cur_vertex.begin(); - b_vec_vertex_already_checked_for_dominance - [i_cur_resident_vertex_num] = true; - vec_last_valid_index_for_dominance[i_cur_resident_vertex_num] = - list_labels_cur_vertex.size() - 1; + put(vec_last_valid_positions_for_dominance, i_cur_resident_vertex, + list_labels_cur_vertex.begin()); + put(b_vec_vertex_already_checked_for_dominance, + i_cur_resident_vertex, true); + put(vec_last_valid_index_for_dominance, i_cur_resident_vertex, + list_labels_cur_vertex.size() - 1); } } + assert (b_all_pareto_optimal_solutions || cur_label->b_is_valid); if( !b_all_pareto_optimal_solutions && cur_label->resident_vertex == t ) { // the devil don't sleep if( cur_label->b_is_dominated ) { + cur_label->b_is_valid = false; l_alloc.destroy( cur_label.get() ); l_alloc.deallocate( cur_label.get(), 1 ); } while( unprocessed_labels.size() ) { Splabel l = unprocessed_labels.top(); + assert (l->b_is_valid); unprocessed_labels.pop(); // delete only dominated labels, because nondominated labels are // deleted at the end of the function if( l->b_is_dominated ) { + l->b_is_valid = false; l_alloc.destroy( l.get() ); l_alloc.deallocate( l.get(), 1 ); } @@ -386,6 +425,7 @@ void r_c_shortest_paths_dispatch if( !b_feasible ) { vis.on_label_not_feasible( *new_label, g ); + new_label->b_is_valid = false; l_alloc.destroy( new_label ); l_alloc.deallocate( new_label, 1 ); } @@ -395,7 +435,7 @@ void r_c_shortest_paths_dispatch ref_new_label = *new_label; vis.on_label_feasible( ref_new_label, g ); Splabel new_sp_label( new_label ); - vec_vertex_labels[vertex_index_map[new_sp_label->resident_vertex]]. + vec_vertex_labels[new_sp_label->resident_vertex]. push_back( new_sp_label ); unprocessed_labels.push( new_sp_label ); } @@ -403,12 +443,14 @@ void r_c_shortest_paths_dispatch } else { + assert (cur_label->b_is_valid); vis.on_label_dominated( *cur_label, g ); + cur_label->b_is_valid = false; l_alloc.destroy( cur_label.get() ); l_alloc.deallocate( cur_label.get(), 1 ); } } - std::list dsplabels = vec_vertex_labels[vertex_index_map[t]]; + std::list dsplabels = get(vec_vertex_labels, t); typename std::list::const_iterator csi = dsplabels.begin(); typename std::list::const_iterator csi_end = dsplabels.end(); // if d could be reached from o @@ -420,12 +462,14 @@ void r_c_shortest_paths_dispatch cur_pareto_optimal_path; const r_c_shortest_paths_label* p_cur_label = (*csi).get(); + assert (p_cur_label->b_is_valid); pareto_optimal_resource_containers. push_back( p_cur_label->cumulated_resource_consumption ); while( p_cur_label->num != 0 ) { cur_pareto_optimal_path.push_back( p_cur_label->pred_edge ); p_cur_label = p_cur_label->p_pred_label; + assert (p_cur_label->b_is_valid); } pareto_optimal_solutions.push_back( cur_pareto_optimal_path ); if( !b_all_pareto_optimal_solutions ) @@ -433,13 +477,13 @@ void r_c_shortest_paths_dispatch } } - size_t i_size = vec_vertex_labels.size(); - for( size_t i = 0; i < i_size; ++i ) - { + BGL_FORALL_VERTICES_T(i, g, Graph) { const std::list& list_labels_cur_vertex = vec_vertex_labels[i]; csi_end = list_labels_cur_vertex.end(); for( csi = list_labels_cur_vertex.begin(); csi != csi_end; ++csi ) { + assert ((*csi)->b_is_valid); + (*csi)->b_is_valid = false; l_alloc.destroy( (*csi).get() ); l_alloc.deallocate( (*csi).get(), 1 ); } From e096e7e5cc19d5e2dce806d7d0677a1de427b2bb Mon Sep 17 00:00:00 2001 From: Stephen Kelly Date: Thu, 26 Sep 2013 09:41:38 +0000 Subject: [PATCH 314/333] Graph: Remove obsolete MSVC version checks. [SVN r85934] --- include/boost/graph/adjacency_list.hpp | 2 -- include/boost/graph/adjacency_matrix.hpp | 7 +----- include/boost/graph/graph_utility.hpp | 20 --------------- include/boost/graph/graphviz.hpp | 32 ------------------------ include/boost/graph/properties.hpp | 6 ----- include/boost/graph/reverse_graph.hpp | 5 ---- include/boost/graph/visitors.hpp | 21 ---------------- 7 files changed, 1 insertion(+), 92 deletions(-) diff --git a/include/boost/graph/adjacency_list.hpp b/include/boost/graph/adjacency_list.hpp index 6738fa22c..d7fbc06d8 100644 --- a/include/boost/graph/adjacency_list.hpp +++ b/include/boost/graph/adjacency_list.hpp @@ -329,7 +329,6 @@ namespace boost { : Base(num_vertices), m_property(new graph_property_type(p)) { } -#if !defined(BOOST_MSVC) || BOOST_MSVC >= 1300 // Required by Iterator Constructible Graph template adjacency_list(EdgeIterator first, EdgeIterator last, @@ -347,7 +346,6 @@ namespace boost { const GraphProperty& p = GraphProperty()) : Base(n, first, last, ep_iter), m_property(new graph_property_type(p)) { } -#endif void swap(adjacency_list& x) { // Is there a more efficient way to do this? diff --git a/include/boost/graph/adjacency_matrix.hpp b/include/boost/graph/adjacency_matrix.hpp index 65cf27a57..b1078d977 100644 --- a/include/boost/graph/adjacency_matrix.hpp +++ b/include/boost/graph/adjacency_matrix.hpp @@ -443,9 +443,7 @@ namespace boost { // graph type. Instead, use directedS, which also provides the // functionality required for a Bidirectional Graph (in_edges, // in_degree, etc.). -#if !defined(_MSC_VER) || _MSC_VER > 1300 BOOST_STATIC_ASSERT(type_traits::ice_not<(is_same::value)>::value); -#endif typedef typename mpl::if_::type @@ -480,13 +478,11 @@ namespace boost { typedef adjacency_matrix_traits Traits; public: -#if !defined(BOOST_MSVC) || BOOST_MSVC > 1300 // The bidirectionalS tag is not allowed with the adjacency_matrix // graph type. Instead, use directedS, which also provides the // functionality required for a Bidirectional Graph (in_edges, // in_degree, etc.). BOOST_STATIC_ASSERT(!(is_same::value)); -#endif typedef GraphProperty graph_property_type; typedef typename lookup_one_property::type graph_bundled; @@ -500,10 +496,9 @@ namespace boost { public: // should be private typedef typename mpl::if_::type, std::pair, char>::type StoredEdge; -#if (defined(BOOST_MSVC) && BOOST_MSVC <= 1300) || defined(BOOST_NO_STD_ALLOCATOR) +#if defined(BOOST_NO_STD_ALLOCATOR) typedef std::vector Matrix; #else - // This causes internal compiler error for MSVC typedef typename Allocator::template rebind::other Alloc; typedef std::vector Matrix; #endif diff --git a/include/boost/graph/graph_utility.hpp b/include/boost/graph/graph_utility.hpp index e772b6406..f1f120e30 100644 --- a/include/boost/graph/graph_utility.hpp +++ b/include/boost/graph/graph_utility.hpp @@ -265,17 +265,7 @@ namespace boost { { typename graph_traits::adjacency_iterator vi, viend, found; boost::tie(vi, viend) = adjacent_vertices(a, g); -#if defined(BOOST_MSVC) && BOOST_MSVC <= 1300 && defined(__SGI_STL_PORT) - // Getting internal compiler error with std::find() - found = viend; - for (; vi != viend; ++vi) - if (*vi == b) { - found = vi; - break; - } -#else found = std::find(vi, viend, b); -#endif if ( found == viend ) return false; @@ -283,17 +273,7 @@ namespace boost { out_found; boost::tie(oi, oiend) = out_edges(a, g); -#if defined(BOOST_MSVC) && BOOST_MSVC <= 1300 && defined(__SGI_STL_PORT) - // Getting internal compiler error with std::find() - out_found = oiend; - for (; oi != oiend; ++oi) - if (target(*oi, g) == b) { - out_found = oi; - break; - } -#else out_found = std::find_if(oi, oiend, incident_to(b, g)); -#endif if (out_found == oiend) return false; return true; diff --git a/include/boost/graph/graphviz.hpp b/include/boost/graph/graphviz.hpp index aedce5553..df10806cd 100644 --- a/include/boost/graph/graphviz.hpp +++ b/include/boost/graph/graphviz.hpp @@ -289,8 +289,6 @@ namespace boost { 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 @@ -300,7 +298,6 @@ namespace boost { default_writer gw; write_graphviz(out, g, dw, dw, gw); } -#endif template inline void @@ -349,21 +346,7 @@ namespace boost { 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 ( boost::tie(i_child,j_child) = g.children(); @@ -382,15 +365,7 @@ namespace boost { if ( vertex_marker[pos] ) { vertex_marker[pos] = false; out << escape_dot_string(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; } } @@ -403,14 +378,7 @@ namespace boost { edge_marker[pos] = false; out << escape_dot_string(get(vertex_id, u)) << " " << Traits::delimiter() << " " << escape_dot_string(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; } } diff --git a/include/boost/graph/properties.hpp b/include/boost/graph/properties.hpp index d540439ef..0d1d34693 100644 --- a/include/boost/graph/properties.hpp +++ b/include/boost/graph/properties.hpp @@ -27,12 +27,6 @@ #include #include -#if BOOST_WORKAROUND(BOOST_MSVC, < 1300) -// Stay out of the way of the concept checking class -# define Graph Graph_ -# define RandomAccessContainer RandomAccessContainer_ -#endif - namespace boost { enum default_color_type { white_color, gray_color, green_color, red_color, black_color }; diff --git a/include/boost/graph/reverse_graph.hpp b/include/boost/graph/reverse_graph.hpp index e9027e3cf..24eb1c7c0 100644 --- a/include/boost/graph/reverse_graph.hpp +++ b/include/boost/graph/reverse_graph.hpp @@ -13,11 +13,6 @@ #include #include -#if BOOST_WORKAROUND(BOOST_MSVC, < 1300) -// Stay out of the way of the concept checking class -# define BidirectionalGraph BidirectionalGraph_ -#endif - namespace boost { struct reverse_graph_tag { }; diff --git a/include/boost/graph/visitors.hpp b/include/boost/graph/visitors.hpp index e4a614f35..120314f90 100644 --- a/include/boost/graph/visitors.hpp +++ b/include/boost/graph/visitors.hpp @@ -21,11 +21,6 @@ #include #include -#if BOOST_WORKAROUND(BOOST_MSVC, < 1300) -// Stay out of the way of the concept checking class -# define Graph Graph_ -#endif - namespace boost { // This is a bit more convenient than std::numeric_limits because @@ -123,16 +118,6 @@ namespace boost { detail::invoke_dispatch(vlist.first, x, g, IsSameTag()); invoke_visitors(vlist.second, x, g, tag); } -#if defined(BOOST_MSVC) && BOOST_MSVC <= 1300 - template - inline void - invoke_visitors(base_visitor& vis, T x, Graph& g, Tag) { - typedef typename Visitor::event_filter Category; - typedef typename is_same::type IsSameTag; - Visitor& v = static_cast(vis); - detail::invoke_dispatch(v, x, g, IsSameTag()); - } -#else template inline void invoke_visitors(Visitor& v, T x, Graph& g, Tag) { @@ -140,7 +125,6 @@ namespace boost { typedef typename is_same::type IsSameTag; detail::invoke_dispatch(v, x, g, IsSameTag()); } -#endif //======================================================================== // predecessor_recorder @@ -313,9 +297,4 @@ namespace boost { } /* namespace boost */ -#if BOOST_WORKAROUND(BOOST_MSVC, < 1300) -// Stay out of the way of the concept checking class -# undef Graph -#endif - #endif From 4f8a34090e4dd2662cd893174a664cd3f41f50b8 Mon Sep 17 00:00:00 2001 From: Stephen Kelly Date: Mon, 30 Sep 2013 00:19:09 +0000 Subject: [PATCH 315/333] Pending: Remove obsolete MSVC version checks. [SVN r86028] --- include/boost/pending/container_traits.hpp | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/include/boost/pending/container_traits.hpp b/include/boost/pending/container_traits.hpp index 7cdf38c7d..3b0707540 100644 --- a/include/boost/pending/container_traits.hpp +++ b/include/boost/pending/container_traits.hpp @@ -30,12 +30,6 @@ # endif #endif -#if BOOST_WORKAROUND(BOOST_MSVC, < 1300) -// Stay out of the way of concept checking class templates -# define Container Container_ -# define AssociativeContainer AssociativeContainer_ -#endif - // The content of this file is in 'graph_detail' because otherwise // there will be name clashes with // sandbox/boost/sequence_algo/container_traits.hpp @@ -552,10 +546,4 @@ namespace boost { namespace graph_detail { }} // namespace boost::graph_detail -#if BOOST_WORKAROUND(BOOST_MSVC, < 1300) -// Stay out of the way of concept checking class templates -# undef Container -# undef AssociativeContainer -#endif - #endif // BOOST_GRAPH_DETAIL_CONTAINER_TRAITS_H From f0f1251da755f49b342bc4b5c372a1f7fb833fbf Mon Sep 17 00:00:00 2001 From: Stephen Kelly Date: Mon, 30 Sep 2013 15:55:18 +0000 Subject: [PATCH 316/333] Graph: Remove obsolete GCC version check. [SVN r86059] --- include/boost/graph/detail/edge.hpp | 15 --------------- include/boost/graph/graph_concepts.hpp | 1 - 2 files changed, 16 deletions(-) diff --git a/include/boost/graph/detail/edge.hpp b/include/boost/graph/detail/edge.hpp index da085973a..253dae2d2 100644 --- a/include/boost/graph/detail/edge.hpp +++ b/include/boost/graph/detail/edge.hpp @@ -11,11 +11,7 @@ #ifndef BOOST_GRAPH_DETAIL_EDGE_HPP #define BOOST_GRAPH_DETAIL_EDGE_HPP -#if __GNUC__ < 3 -#include -#else #include -#endif namespace boost { @@ -100,15 +96,6 @@ namespace boost { } // namespace boost namespace std { - -#if __GNUC__ < 3 - template - std::ostream& - operator<<(std::ostream& os, const boost::detail::edge_desc_impl& e) - { - return os << "(" << e.m_source << "," << e.m_target << ")"; - } -#else template std::basic_ostream& operator<<(std::basic_ostream& os, @@ -116,8 +103,6 @@ namespace std { { return os << "(" << e.m_source << "," << e.m_target << ")"; } -#endif - } diff --git a/include/boost/graph/graph_concepts.hpp b/include/boost/graph/graph_concepts.hpp index f03afeea3..90a7cb043 100644 --- a/include/boost/graph/graph_concepts.hpp +++ b/include/boost/graph/graph_concepts.hpp @@ -38,7 +38,6 @@ namespace boost // It is needed in order to allow us to write using boost::vertices as // needed for ADL when using vector_as_graph below. #if !defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP) \ - && !BOOST_WORKAROUND(__GNUC__, <= 2) \ && !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) # define BOOST_VECTOR_AS_GRAPH_GRAPH_ADL_HACK #endif From bed19d5c257ec7d64a08ec2c5e86cab432f755f1 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Tue, 1 Oct 2013 18:12:50 +0000 Subject: [PATCH 317/333] Qualified calls to tie in documentation; fixes #9184 [SVN r86126] --- doc/adjacency_list.html | 10 +++++----- doc/boykov_kolmogorov_max_flow.html | 4 ++-- doc/constructing_algorithms.html | 4 ++-- doc/faq.html | 2 +- doc/file_dependency_example.html | 2 +- doc/graph_coloring.html | 4 ++-- doc/graph_concepts.html | 10 +++++----- doc/incident.html | 2 +- doc/kevin_bacon.html | 6 +++--- doc/opposite.html | 2 +- doc/push_relabel_max_flow.html | 4 ++-- doc/quick_tour.html | 10 +++++----- doc/sparse_matrix_ordering.html | 4 ++-- doc/write_graphml.html | 4 ++-- 14 files changed, 34 insertions(+), 34 deletions(-) diff --git a/doc/adjacency_list.html b/doc/adjacency_list.html index 3e53f9f75..10cc75f13 100644 --- a/doc/adjacency_list.html +++ b/doc/adjacency_list.html @@ -214,12 +214,12 @@

      Iterator and Descriptor Stability/Invalidation

      // Attempt to remove all the vertices. Wrong! graph_traits<Graph>::vertex_iterator vi, vi_end; - for (tie(vi, vi_end) = vertices(G); vi != vi_end; ++vi) + for (boost::tie(vi, vi_end) = vertices(G); vi != vi_end; ++vi) remove_vertex(*vi, G); // Remove all the vertices. This is still wrong! graph_traits<Graph>::vertex_iterator vi, vi_end, next; - tie(vi, vi_end) = vertices(G); + boost::tie(vi, vi_end) = vertices(G); for (next = vi; vi != vi_end; vi = next) { ++next; remove_vertex(*vi, G); @@ -247,12 +247,12 @@

      Iterator and Descriptor Stability/Invalidation

      // Attempt to remove all the vertices. Wrong! graph_traits<Graph>::vertex_iterator vi, vi_end; - for (tie(vi, vi_end) = vertices(G); vi != vi_end; ++vi) + for (boost::tie(vi, vi_end) = vertices(G); vi != vi_end; ++vi) remove_vertex(*vi, G); // Remove all the vertices. This is OK. graph_traits<Graph>::vertex_iterator vi, vi_end, next; - tie(vi, vi_end) = vertices(G); + boost::tie(vi, vi_end) = vertices(G); for (next = vi; vi != vi_end; vi = next) { ++next; remove_vertex(*vi, G); @@ -281,7 +281,7 @@

      Iterator and Descriptor Stability/Invalidation

      remove_vertex(s, G); // Bad idea! Invalidates vertex descriptors in parent vector. // The following will produce incorrect results - for(tie(vi, vend) = vertices(G); vi != vend; ++vi) + for(boost::tie(vi, vend) = vertices(G); vi != vend; ++vi) std::cout << p[*vi] << " is the parent of " << *vi << std::endl; diff --git a/doc/boykov_kolmogorov_max_flow.html b/doc/boykov_kolmogorov_max_flow.html index 1a5b0312c..ecaaf5ca3 100644 --- a/doc/boykov_kolmogorov_max_flow.html +++ b/doc/boykov_kolmogorov_max_flow.html @@ -338,8 +338,8 @@

      Example

      std::cout << "c flow values:" << std::endl; graph_traits < Graph >::vertex_iterator u_iter, u_end; graph_traits < Graph >::out_edge_iterator ei, e_end; - for (tie(u_iter, u_end) = vertices(g); u_iter != u_end; ++u_iter) - for (tie(ei, e_end) = out_edges(*u_iter, g); ei != e_end; ++ei) + for (boost::tie(u_iter, u_end) = vertices(g); u_iter != u_end; ++u_iter) + for (boost::tie(ei, e_end) = out_edges(*u_iter, g); ei != e_end; ++ei) if (capacity[*ei] > 0) std::cout << "f " << *u_iter << " " << target(*ei, g) << " " << (capacity[*ei] - residual_capacity[*ei]) << std::endl; diff --git a/doc/constructing_algorithms.html b/doc/constructing_algorithms.html index cc4047b05..4c9e96e25 100644 --- a/doc/constructing_algorithms.html +++ b/doc/constructing_algorithms.html @@ -134,7 +134,7 @@

      Constructing graph algorithms with BGL

      mark(V, numeric_limits_max(max_color)); typename GraphTraits::vertex_iterator v, vend; - for (tie(v, vend) = vertices(G); v != vend; ++v) + for (boost::tie(v, vend) = vertices(G); v != vend; ++v) color[*v] = V - 1; // which means "not colored" for (size_type i = 0; i < V; i++) { @@ -142,7 +142,7 @@

      Constructing graph algorithms with BGL

      // mark all the colors of the adjacent vertices typename GraphTraits::adjacency_iterator ai, aend; - for (tie(ai, aend) = adjacent_vertices(current, G); ai != aend; ++ai) + for (boost::tie(ai, aend) = adjacent_vertices(current, G); ai != aend; ++ai) mark[color[*ai]] = i; // find the smallest color unused by the adjacent vertices diff --git a/doc/faq.html b/doc/faq.html index ff20e1622..c77fca5db 100644 --- a/doc/faq.html +++ b/doc/faq.html @@ -115,7 +115,7 @@

      Frequently Asked Questions

      // initialize the vertex_index property values graph_traits<graph_t>::vertex_iterator vi, vend; graph_traits<graph_t>::vertices_size_type cnt = 0; - for(tie(vi,vend) = vertices(G); vi != vend; ++vi) + for(boost::tie(vi,vend) = vertices(G); vi != vend; ++vi) put(index, *vi, cnt++);
    2. diff --git a/doc/file_dependency_example.html b/doc/file_dependency_example.html index fed8ef6a1..501526764 100644 --- a/doc/file_dependency_example.html +++ b/doc/file_dependency_example.html @@ -233,7 +233,7 @@

      if (in_degree (*i, g) > 0) { Graph::in_edge_iterator j, j_end; int maxdist = 0; - for (tie(j, j_end) = in_edges(*i, g); j != j_end; ++j) + for (boost::tie(j, j_end) = in_edges(*i, g); j != j_end; ++j) maxdist = std::max(time[source(*j, g)], maxdist); time[*i]=maxdist+1; } diff --git a/doc/graph_coloring.html b/doc/graph_coloring.html index cfeaaef97..1d4dcb77d 100644 --- a/doc/graph_coloring.html +++ b/doc/graph_coloring.html @@ -127,7 +127,7 @@

      Graph Coloring

      const size_type num = num_vertices(G); typename GraphTraits::vertex_iterator v, vend; - for (tie(v, vend) = vertices(G); v != vend; ++v) { + for (boost::tie(v, vend) = vertices(G); v != vend; ++v) { put(marker, *v, num); put(degree, *v, out_degree(*v, G)); degree_buckets.push(*v); @@ -152,7 +152,7 @@

      Graph Coloring

      put(marker, node, 0); //node has been ordered. typename GraphTraits::adjacency_iterator v, vend; - for (tie(v,vend) = adjacent_vertices(node, G); v != vend; ++v) + for (boost::tie(v,vend) = adjacent_vertices(node, G); v != vend; ++v) if ( get(marker, *v) > current_order ) { //*v is unordered vertex put(marker, *v, current_order); //mark the columns adjacent to node diff --git a/doc/graph_concepts.html b/doc/graph_concepts.html index a7dd3060b..9b5b5cd39 100644 --- a/doc/graph_concepts.html +++ b/doc/graph_concepts.html @@ -408,7 +408,7 @@

      boost::graph_traits<UndirectedGraph>::out_edge_iterator e, e_end; boost::graph_traits<UndirectedGraph>::vertex_descriptor s = vertex(0, undigraph); - for (tie(e, e_end) = out_edges(s, undigraph); e != e_end; ++e) + for (boost::tie(e, e_end) = out_edges(s, undigraph); e != e_end; ++e) std::cout << "(" << source(*e, undigraph) << "," << target(*e, undigraph) << ")" << endl; @@ -447,8 +447,8 @@

      add_edge(digraph, v, u, Weight(2.4)); boost::graph_traits<DirectedGraph>::edge_descriptor e1, e2; bool found; - tie(e1, found) = edge(u, v, digraph); - tie(e2, found) = edge(v, u, digraph); + boost::tie(e1, found) = edge(u, v, digraph); + boost::tie(e2, found) = edge(v, u, digraph); std::cout << "in a directed graph is "; std::cout << "(u,v) == (v,u) ? " << (e1 == e2) << std::endl; @@ -464,8 +464,8 @@

      add_edge(undigraph, u, v, Weight(3.1)); boost::graph_traits<UndirectedGraph>::edge_descriptor e1, e2; bool found; - tie(e1, found) = edge(u, v, undigraph); - tie(e2, found) = edge(v, u, undigraph); + boost::tie(e1, found) = edge(u, v, undigraph); + boost::tie(e2, found) = edge(v, u, undigraph); std::cout << "in an undirected graph is "; std::cout << "(u,v) == (v,u) ? " << (e1 == e2) << std::endl; diff --git a/doc/incident.html b/doc/incident.html index e75f336c9..703e17f74 100644 --- a/doc/incident.html +++ b/doc/incident.html @@ -57,7 +57,7 @@

      Example

      edge_descriptor e; vertex_descriptor u, v; ... - tie(u, v) = incident(e, g); + boost::tie(u, v) = incident(e, g); diff --git a/doc/kevin_bacon.html b/doc/kevin_bacon.html index 8b2670bdf..6648da7f0 100644 --- a/doc/kevin_bacon.html +++ b/doc/kevin_bacon.html @@ -156,7 +156,7 @@

      Input File and Graph Setup

      tokenizer<>::iterator i = line_toks.begin(); std::string actors_name = *i++; - tie(pos, inserted) = actors.insert(std::make_pair(actors_name, Vertex())); + boost::tie(pos, inserted) = actors.insert(std::make_pair(actors_name, Vertex())); if (inserted) { u = add_vertex(g); actor_name[u] = actors_name; @@ -174,7 +174,7 @@

      Input File and Graph Setup

         std::string movie_name = *i++;
             
      -  tie(pos, inserted) = actors.insert(std::make_pair(*i, Vertex()));
      +  boost::tie(pos, inserted) = actors.insert(std::make_pair(*i, Vertex()));
         if (inserted) {
           v = add_vertex(g);
           actor_name[v] = *i;
      @@ -190,7 +190,7 @@ 

      Input File and Graph Setup

         graph_traits<Graph>::edge_descriptor e;
      -  tie(e, inserted) = add_edge(u, v, g);
      +  boost::tie(e, inserted) = add_edge(u, v, g);
         if (inserted)
           connecting_movie[e] = movie_name;
       
      diff --git a/doc/opposite.html b/doc/opposite.html index 6e3f12db2..f9be2e477 100644 --- a/doc/opposite.html +++ b/doc/opposite.html @@ -56,7 +56,7 @@

      Example

      edge_descriptor e; ... vertex_descriptor u, v; -tie(u, v) = incident(e, g); +boost::tie(u, v) = incident(e, g); assert(v == opposite(e, u, g)); assert(u == opposite(e, v, g));
      diff --git a/doc/push_relabel_max_flow.html b/doc/push_relabel_max_flow.html index cb96c83a9..5dff05047 100644 --- a/doc/push_relabel_max_flow.html +++ b/doc/push_relabel_max_flow.html @@ -196,8 +196,8 @@

      Example

      std::cout << "c flow values:" << std::endl; graph_traits<Graph>::vertex_iterator u_iter, u_end; graph_traits<Graph>::out_edge_iterator ei, e_end; - for (tie(u_iter, u_end) = vertices(g); u_iter != u_end; ++u_iter) - for (tie(ei, e_end) = out_edges(*u_iter, g); ei != e_end; ++ei) + for (boost::tie(u_iter, u_end) = vertices(g); u_iter != u_end; ++u_iter) + for (boost::tie(ei, e_end) = out_edges(*u_iter, g); ei != e_end; ++ei) if (capacity[*ei] > 0) std::cout << "f " << *u_iter << " " << target(*ei, g) << " " << (capacity[*ei] - residual_capacity[*ei]) << std::endl; diff --git a/doc/quick_tour.html b/doc/quick_tour.html index 5ae9ffe95..5156bb7bf 100644 --- a/doc/quick_tour.html +++ b/doc/quick_tour.html @@ -187,7 +187,7 @@

      Accessing the Edge Set

      iterator gives an edge object. The source() and target() functions return the two vertices that are connected by the edge. Instead of explicitly creating a std::pair for the iterators, this time we will -use the tie() helper function. +use the boost::tie() helper function. This handy function can be used to assign the parts of a std::pair into two separate variables, in this case ei and ei_end. This is usually more convenient than creating a std::pair and is our method of @@ -200,7 +200,7 @@

      Accessing the Edge Set

      // ... std::cout << "edges(g) = "; graph_traits<Graph>::edge_iterator ei, ei_end; - for (tie(ei, ei_end) = edges(g); ei != ei_end; ++ei) + for (boost::tie(ei, ei_end) = edges(g); ei != ei_end; ++ei) std::cout << "(" << index[source(*ei, g)] << "," << index[target(*ei, g)] << ") "; std::cout << std::endl; @@ -303,7 +303,7 @@

      Out-Edges, In-Edges, and Edge Descriptors

      std::cout << "out-edges: "; typename GraphTraits::out_edge_iterator out_i, out_end; typename GraphTraits::edge_descriptor e; - for (tie(out_i, out_end) = out_edges(v, g); + for (boost::tie(out_i, out_end) = out_edges(v, g); out_i != out_end; ++out_i) { e = *out_i; Vertex src = source(e, g), targ = target(e, g); @@ -337,7 +337,7 @@

      Out-Edges, In-Edges, and Edge Descriptors

      std::cout << "in-edges: "; typedef typename graph_traits<Graph> GraphTraits; typename GraphTraits::in_edge_iterator in_i, in_end; - for (tie(in_i, in_end) = in_edges(v,g); + for (boost::tie(in_i, in_end) = in_edges(v,g); in_i != in_end; ++in_i) { e = *in_i; Vertex src = source(e, g), targ = target(e, g); @@ -373,7 +373,7 @@

      Adjacent Vertices

      std::cout << "adjacent vertices: "; typename graph_traits<Graph>::adjacency_iterator ai; typename graph_traits<Graph>::adjacency_iterator ai_end; - for (tie(ai, ai_end) = adjacent_vertices(v, g); + for (boost::tie(ai, ai_end) = adjacent_vertices(v, g); ai != ai_end; ++ai) std::cout << index[*ai] << " "; std::cout << std::endl; diff --git a/doc/sparse_matrix_ordering.html b/doc/sparse_matrix_ordering.html index 87b39e7f5..44a6a1bc2 100644 --- a/doc/sparse_matrix_ordering.html +++ b/doc/sparse_matrix_ordering.html @@ -143,7 +143,7 @@

      rcm_queue<Vertex, Degree> Q(degree); typename boost::graph_traits<Graph>::vertex_iterator ui, ui_end; - for (tie(ui, ui_end) = vertices(G); ui != ui_end; ++ui) + for (boost::tie(ui, ui_end) = vertices(G); ui != ui_end; ++ui) put(color, *ui, white(c)); breadth_first_search(G, u, Q, bfs_visitor<>(), color); @@ -214,7 +214,7 @@

      CMVisitor cm_visitor(inverse_permutation); typename boost::graph_traits<Graph>::vertex_iterator ui, ui_end; - for (tie(ui, ui_end) = vertices(G); ui != ui_end; ++ui) + for (boost::tie(ui, ui_end) = vertices(G); ui != ui_end; ++ui) put(color, *ui, white(c)); breadth_first_search(G, s, Q, cm_visitor, color); } diff --git a/doc/write_graphml.html b/doc/write_graphml.html index b3bbd131f..8ed7127ab 100644 --- a/doc/write_graphml.html +++ b/doc/write_graphml.html @@ -116,11 +116,11 @@

      Example

      Graph g(used_by, used_by + nedges, N); graph_traits<Graph>::vertex_iterator v, v_end; - for (tie(v,v_end) = vertices(g); v != v_end; ++v) + for (boost::tie(v,v_end) = vertices(g); v != v_end; ++v) put(vertex_color_t(), g, *v, name[*v]); graph_traits<Graph>::edge_iterator e, e_end; - for (tie(e,e_end) = edges(g); e != e_end; ++e) + for (boost::tie(e,e_end) = edges(g); e != e_end; ++e) put(edge_weight_t(), g, *e, 3); dynamic_properties dp; From da59145176dfdabac7ffbd2f8d26241418a6a8b1 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Wed, 2 Oct 2013 19:10:30 +0000 Subject: [PATCH 318/333] Fixed documentation about hash_setS; fixes #6990 [SVN r86136] --- doc/using_adjacency_list.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/using_adjacency_list.html b/doc/using_adjacency_list.html index 9b077cd8d..efcb40f12 100644 --- a/doc/using_adjacency_list.html +++ b/doc/using_adjacency_list.html @@ -71,7 +71,7 @@

    3. slistS selects std::slist.
    4. setS selects std::set.
    5. multisetS selects std::multiset.
    6. -
    7. hash_setS selects std::hash_set.
    8. +
    9. hash_setS selects boost::unordered_set.
    10. From 4fc3cbfaae0ccd278c8e8fd06da64b96e5250eab Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Wed, 2 Oct 2013 19:15:21 +0000 Subject: [PATCH 319/333] Made boost::unordered inclusion unconditional; removed support for non-partial-specialization compilers; enabled C++11 unordered containers when they are present; refs #8962 [SVN r86137] --- include/boost/pending/container_traits.hpp | 91 +++++++++++++++++++++- 1 file changed, 88 insertions(+), 3 deletions(-) diff --git a/include/boost/pending/container_traits.hpp b/include/boost/pending/container_traits.hpp index 3b0707540..803df77aa 100644 --- a/include/boost/pending/container_traits.hpp +++ b/include/boost/pending/container_traits.hpp @@ -30,6 +30,14 @@ # endif #endif +#ifndef BOOST_NO_CXX11_HDR_UNORDERED_SET +#include +#endif + +#ifndef BOOST_NO_CXX11_HDR_UNORDERED_MAP +#include +#endif + // The content of this file is in 'graph_detail' because otherwise // there will be name clashes with // sandbox/boost/sequence_algo/container_traits.hpp @@ -280,8 +288,6 @@ namespace boost { namespace graph_detail { { }; -#ifndef BOOST_NO_HASH -#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION template struct container_traits< boost::unordered_set > { typedef unordered_set_tag category; @@ -302,7 +308,7 @@ namespace boost { namespace graph_detail { typedef unordered_multimap_tag category; typedef unstable_tag iterator_stability; }; -#endif + template unordered_set_tag container_category(const boost::unordered_set&) @@ -339,8 +345,87 @@ namespace boost { namespace graph_detail { unstable_tag iterator_stability(const boost::unordered_multimap&) { return unstable_tag(); } + +#ifndef BOOST_NO_CXX11_HDR_UNORDERED_SET + template + struct container_traits< std::unordered_set > { + typedef unordered_set_tag category; + typedef unstable_tag iterator_stability; + }; +#endif +#ifndef BOOST_NO_CXX11_HDR_UNORDERED_MAP + template + struct container_traits< std::unordered_map > { + typedef unordered_map_tag category; + typedef unstable_tag iterator_stability; + }; +#endif +#ifndef BOOST_NO_CXX11_HDR_UNORDERED_SET + template + struct container_traits< std::unordered_multiset > { + typedef unordered_multiset_tag category; + typedef unstable_tag iterator_stability; + }; +#endif +#ifndef BOOST_NO_CXX11_HDR_UNORDERED_MAP + template + struct container_traits< std::unordered_multimap > { + typedef unordered_multimap_tag category; + typedef unstable_tag iterator_stability; + }; +#endif +#ifndef BOOST_NO_CXX11_HDR_UNORDERED_SET + template + unordered_set_tag + container_category(const std::unordered_set&) + { return unordered_set_tag(); } #endif +#ifndef BOOST_NO_CXX11_HDR_UNORDERED_MAP + template + unordered_map_tag + container_category(const std::unordered_map&) + { return unordered_map_tag(); } +#endif + +#ifndef BOOST_NO_CXX11_HDR_UNORDERED_SET + template + unstable_tag iterator_stability(const std::unordered_set&) + { return unstable_tag(); } +#endif + +#ifndef BOOST_NO_CXX11_HDR_UNORDERED_MAP + template + unstable_tag iterator_stability(const std::unordered_map&) + { return unstable_tag(); } +#endif +#ifndef BOOST_NO_CXX11_HDR_UNORDERED_SET + template + unordered_multiset_tag + container_category(const std::unordered_multiset&) + { return unordered_multiset_tag(); } +#endif + +#ifndef BOOST_NO_CXX11_HDR_UNORDERED_MAP + template + unordered_multimap_tag + container_category(const std::unordered_multimap&) + { return unordered_multimap_tag(); } +#endif + +#ifndef BOOST_NO_CXX11_HDR_UNORDERED_SET + template + unstable_tag + iterator_stability(const std::unordered_multiset&) + { return unstable_tag(); } +#endif + +#ifndef BOOST_NO_CXX11_HDR_UNORDERED_MAP + template + unstable_tag + iterator_stability(const std::unordered_multimap&) + { return unstable_tag(); } +#endif //=========================================================================== From 4ebf7f60fcb4bc60f52ae2cb31f460fc95f621a5 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Fri, 11 Oct 2013 14:32:02 +0000 Subject: [PATCH 320/333] Applied patch from #9229 to allow common subgraphs of size 1; fixes #9229 [SVN r86236] --- include/boost/graph/mcgregor_common_subgraphs.hpp | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/include/boost/graph/mcgregor_common_subgraphs.hpp b/include/boost/graph/mcgregor_common_subgraphs.hpp index 987a03bf2..9fd544dd0 100644 --- a/include/boost/graph/mcgregor_common_subgraphs.hpp +++ b/include/boost/graph/mcgregor_common_subgraphs.hpp @@ -327,15 +327,11 @@ namespace boost { put(correspondence_map_2_to_1, new_vertex2, new_vertex1); vertex_stack1.push(new_vertex1); - // Only output sub-graphs larger than a single vertex - if (new_graph_size > 1) { - - // Returning false from the callback will cancel iteration - if (!subgraph_callback(correspondence_map_1_to_2, - correspondence_map_2_to_1, - new_graph_size)) { - return (false); - } + // Returning false from the callback will cancel iteration + if (!subgraph_callback(correspondence_map_1_to_2, + correspondence_map_2_to_1, + new_graph_size)) { + return (false); } // Depth-first search into the state space of possible sub-graphs From 0464915a7f1dfc77d5f796619f168ce07de436b4 Mon Sep 17 00:00:00 2001 From: Stephen Kelly Date: Fri, 11 Oct 2013 23:13:10 +0000 Subject: [PATCH 321/333] Remove BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION Process #ifdef...#endif blocks. [SVN r86243] --- include/boost/graph/properties.hpp | 13 ------------- include/boost/graph/vector_as_graph.hpp | 3 --- 2 files changed, 16 deletions(-) diff --git a/include/boost/graph/properties.hpp b/include/boost/graph/properties.hpp index 0d1d34693..ca6a4e9b1 100644 --- a/include/boost/graph/properties.hpp +++ b/include/boost/graph/properties.hpp @@ -47,16 +47,6 @@ namespace boost { inline default_color_type red(default_color_type) { return red_color; } inline default_color_type black(default_color_type) { return black_color; } -#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION - template <> - struct property_traits { - typedef default_color_type value_type; - typedef std::ptrdiff_t key_type; - typedef default_color_type& reference; - typedef lvalue_property_map_tag category; - }; - // get/put already defined for T* -#endif struct graph_property_tag { }; struct vertex_property_tag { }; @@ -333,9 +323,6 @@ namespace boost { return make_iterator_vertex_map(c.begin()); } -#if defined (BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) -# define BOOST_GRAPH_NO_BUNDLED_PROPERTIES -#endif #if BOOST_WORKAROUND(__SUNPRO_CC, BOOST_TESTED_AT(0x590)) && !defined (BOOST_GRAPH_NO_BUNDLED_PROPERTIES) // This compiler cannot define a partial specialization based on a diff --git a/include/boost/graph/vector_as_graph.hpp b/include/boost/graph/vector_as_graph.hpp index 7bc8ac380..a32397349 100644 --- a/include/boost/graph/vector_as_graph.hpp +++ b/include/boost/graph/vector_as_graph.hpp @@ -40,9 +40,6 @@ */ -#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION -#error The vector-as-graph module requires a compiler that supports partial specialization -#endif namespace boost { From 73b68e32ba6aa60448da84c803494378070c91ed Mon Sep 17 00:00:00 2001 From: Stephen Kelly Date: Fri, 11 Oct 2013 23:15:00 +0000 Subject: [PATCH 322/333] Remove BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION Process #ifndef...#endif conditions. [SVN r86244] --- include/boost/graph/detail/adjacency_list.hpp | 2 -- include/boost/graph/graph_as_tree.hpp | 4 ---- include/boost/graph/leda_graph.hpp | 2 -- include/boost/graph/named_graph.hpp | 4 ---- include/boost/graph/stanford_graph.hpp | 2 -- include/boost/graph/vector_as_graph.hpp | 2 -- include/boost/pending/container_traits.hpp | 16 ---------------- 7 files changed, 32 deletions(-) diff --git a/include/boost/graph/detail/adjacency_list.hpp b/include/boost/graph/detail/adjacency_list.hpp index a99ec265c..16cf02678 100644 --- a/include/boost/graph/detail/adjacency_list.hpp +++ b/include/boost/graph/detail/adjacency_list.hpp @@ -2722,7 +2722,6 @@ namespace boost { } // namespace boost -#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) namespace boost { template @@ -2756,7 +2755,6 @@ namespace boost { }; } -#endif #endif // BOOST_GRAPH_DETAIL_DETAIL_ADJACENCY_LIST_CCT diff --git a/include/boost/graph/graph_as_tree.hpp b/include/boost/graph/graph_as_tree.hpp index 3758c3f00..721e503e8 100644 --- a/include/boost/graph/graph_as_tree.hpp +++ b/include/boost/graph/graph_as_tree.hpp @@ -50,13 +50,9 @@ namespace boost { template ::vertex_descriptor -#endif , class ChIt -#if !defined BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION = typename graph_traits::adjacency_iterator -#endif > class graph_as_tree : public graph_as_tree_base struct internal_vertex_name > : internal_vertex_name { }; -#endif /** * Construct an instance of @c VertexProperty directly from its @@ -157,7 +155,6 @@ struct internal_vertex_constructor typedef cannot_add_vertex type; }; -#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION /** * Extract the internal vertex constructor from a @c property structure by * looking at its base. @@ -165,7 +162,6 @@ struct internal_vertex_constructor template struct internal_vertex_constructor > : internal_vertex_constructor { }; -#endif /******************************************************************* * Named graph mixin * diff --git a/include/boost/graph/stanford_graph.hpp b/include/boost/graph/stanford_graph.hpp index 89f5e34b2..99dd835fc 100644 --- a/include/boost/graph/stanford_graph.hpp +++ b/include/boost/graph/stanford_graph.hpp @@ -347,7 +347,6 @@ namespace boost { } }; -#if !defined BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION template inline sgb_vertex_util_map @@ -371,7 +370,6 @@ namespace boost { return sgb_edge_util_map(); } -#endif // ! BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION // Edge Length Access template diff --git a/include/boost/graph/vector_as_graph.hpp b/include/boost/graph/vector_as_graph.hpp index a32397349..b771eaf7f 100644 --- a/include/boost/graph/vector_as_graph.hpp +++ b/include/boost/graph/vector_as_graph.hpp @@ -50,7 +50,6 @@ namespace boost { } } -#if !defined BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION namespace boost { struct vector_as_graph_traversal_tag @@ -94,7 +93,6 @@ namespace boost { typedef void type; }; } -#endif namespace boost { diff --git a/include/boost/pending/container_traits.hpp b/include/boost/pending/container_traits.hpp index 803df77aa..3577487f6 100644 --- a/include/boost/pending/container_traits.hpp +++ b/include/boost/pending/container_traits.hpp @@ -89,14 +89,12 @@ namespace boost { namespace graph_detail { //====================================================================== // Container Traits Class and container_category() function -#if !defined BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION // don't use this unless there is partial specialization template struct container_traits { typedef typename Container::category category; typedef typename Container::iterator_stability iterator_stability; }; -#endif // Use this as a compile-time assertion that X is stable inline void require_stable(stable_tag) { } @@ -114,13 +112,11 @@ namespace boost { namespace graph_detail { unstable_tag iterator_stability(const std::vector&) { return unstable_tag(); } -#if !defined BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION template struct container_traits< std::vector > { typedef vector_tag category; typedef unstable_tag iterator_stability; }; -#endif // std::list struct list_tag : @@ -138,24 +134,20 @@ namespace boost { namespace graph_detail { stable_tag iterator_stability(const std::list&) { return stable_tag(); } -#if !defined BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION template struct container_traits< std::list > { typedef list_tag category; typedef stable_tag iterator_stability; }; -#endif // std::slist #ifndef BOOST_NO_SLIST -# ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION template struct container_traits > { typedef front_insertion_sequence_tag category; typedef stable_tag iterator_stability; }; -#endif template front_insertion_sequence_tag container_category( const BOOST_STD_EXTENSION_NAMESPACE::slist& @@ -184,13 +176,11 @@ namespace boost { namespace graph_detail { stable_tag iterator_stability(const std::set&) { return stable_tag(); } -#if !defined BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION template struct container_traits< std::set > { typedef set_tag category; typedef stable_tag iterator_stability; }; -#endif // std::multiset struct multiset_tag : @@ -207,13 +197,11 @@ namespace boost { namespace graph_detail { stable_tag iterator_stability(const std::multiset&) { return stable_tag(); } -#if !defined BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION template struct container_traits< std::multiset > { typedef multiset_tag category; typedef stable_tag iterator_stability; }; -#endif // deque @@ -224,13 +212,11 @@ namespace boost { namespace graph_detail { virtual public unique_associative_container_tag { }; -#if !defined BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION template struct container_traits< std::map > { typedef map_tag category; typedef stable_tag iterator_stability; }; -#endif template map_tag container_category(const std::map&) @@ -247,13 +233,11 @@ namespace boost { namespace graph_detail { virtual public multiple_associative_container_tag { }; -#if !defined BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION template struct container_traits< std::multimap > { typedef multimap_tag category; typedef stable_tag iterator_stability; }; -#endif template multimap_tag container_category(const std::multimap&) From 91a21a559cdb0caf0a3f5b1a0523e4f5238787d8 Mon Sep 17 00:00:00 2001 From: Stephen Kelly Date: Fri, 11 Oct 2013 23:17:48 +0000 Subject: [PATCH 323/333] Remove BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION Process #ifndef...#else...#endif blocks. [SVN r86245] --- include/boost/graph/named_graph.hpp | 35 -------------------- include/boost/graph/stanford_graph.hpp | 44 -------------------------- 2 files changed, 79 deletions(-) diff --git a/include/boost/graph/named_graph.hpp b/include/boost/graph/named_graph.hpp index 974542541..e4d3314a2 100644 --- a/include/boost/graph/named_graph.hpp +++ b/include/boost/graph/named_graph.hpp @@ -455,7 +455,6 @@ add_edge(typename BGL_NAMED_GRAPH::vertex_name_type const& u_name, * Maybe named graph mixin * *******************************************************************/ -#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION /** * A graph mixin that can provide a mapping from names to vertices, * and use that mapping to simplify creation and manipulation of @@ -503,40 +502,6 @@ struct maybe_named_graph return optional(); } }; -#else -template::type> -struct maybe_named_graph -{ - /// The type of the "bundled" property, from which the name can be - /// extracted. - typedef typename detail::extract_bundled_vertex::type - bundled_vertex_property_type; - - /// Notify the named_graph that we have added the given vertex. This - /// is a no-op. - void added_vertex(Vertex) { } - - /// Notify the named_graph that we are removing the given - /// vertex. This is a no-op. - template - void removing_vertex(Vertex, VertexIterStability) { } - - /// Notify the named_graph that we are clearing the graph. This is a - /// no-op. - void clearing_graph() { } - - /// Search for a vertex that has the given property (based on its - /// name). This always returns an empty optional<> - template - optional - vertex_by_property(const bundled_vertex_property_type&) - { - return optional(); - } -}; -#endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION } } // end namespace boost::graph diff --git a/include/boost/graph/stanford_graph.hpp b/include/boost/graph/stanford_graph.hpp index 99dd835fc..b2d3987d7 100644 --- a/include/boost/graph/stanford_graph.hpp +++ b/include/boost/graph/stanford_graph.hpp @@ -442,7 +442,6 @@ namespace boost { typedef sgb_vertex_name_map const_type; }; -#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) namespace detail { template @@ -508,49 +507,6 @@ namespace boost { sgb_##KIND##_util_map< X##_property, T&>()[key] = value; \ } -#else // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION - -#define SGB_UTIL_ACCESSOR_TYPE(KIND,TAG,TYPE) \ - inline sgb_##KIND##_util_map< TAG, TYPE& > \ - get(TAG, sgb_graph_ptr&) { \ - return sgb_##KIND##_util_map< TAG, TYPE& >(); \ - } \ - inline sgb_##KIND##_util_map< TAG, const TYPE& > \ - get(TAG, const sgb_graph_ptr&) { \ - return sgb_##KIND##_util_map< TAG, const TYPE& >(); \ - } \ - inline sgb_##KIND##_util_map< TAG, const TYPE& > \ - get(TAG, const sgb_const_graph_ptr&) { \ - return sgb_##KIND##_util_map< TAG, const TYPE& >(); \ - } \ - template \ - inline typename sgb_##KIND##_util_map< TAG, const TYPE& >::value_type \ - get(TAG, const sgb_graph_ptr&, const Key& key) { \ - return sgb_##KIND##_util_map< TAG, const TYPE& >()[key]; \ - } \ - template \ - inline typename sgb_##KIND##_util_map< TAG, const TYPE& >::value_type \ - get(TAG, const sgb_const_graph_ptr&, const Key& key) { \ - return sgb_##KIND##_util_map< TAG, const TYPE& >()[key]; \ - } \ - template \ - inline void \ - put(TAG, sgb_graph_ptr&, const Key& key, const Value& value) { \ - sgb_##KIND##_util_map< TAG, TYPE& >()[key] = value; \ - } \ - template <> struct property_map > { \ - typedef sgb_##KIND##_util_map< TAG, TYPE&> type; \ - typedef sgb_##KIND##_util_map< TAG, const TYPE&> const_type; \ - } - -#define SGB_UTIL_ACCESSOR(KIND,TAG) \ - SGB_UTIL_ACCESSOR_TYPE(KIND, TAG##_property, Vertex*); \ - SGB_UTIL_ACCESSOR_TYPE(KIND, TAG##_property, Arc*); \ - SGB_UTIL_ACCESSOR_TYPE(KIND, TAG##_property, sgb_graph_ptr); \ - SGB_UTIL_ACCESSOR_TYPE(KIND, TAG##_property, long); \ - SGB_UTIL_ACCESSOR_TYPE(KIND, TAG##_property, char*); - -#endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION SGB_UTIL_ACCESSOR(vertex, u) SGB_UTIL_ACCESSOR(vertex, v) From 74564d5a1c5f657913ada4e7c1bf462a2b7a8107 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Thu, 17 Oct 2013 02:51:14 +0000 Subject: [PATCH 324/333] Made some of changes from #9246: added new test case (modifying tests on callback usage to match current documentation); removed special-casing of empty graphs; added patch from #9246 for correct return values; did not make change to documentation suggested there since I chose to have the callback called even for empty graphs; fixes #9246 [SVN r86336] --- include/boost/graph/vf2_sub_graph_iso.hpp | 12 +- test/Jamfile.v2 | 1 + test/vf2_sub_graph_iso_test_2.cpp | 194 ++++++++++++++++++++++ 3 files changed, 199 insertions(+), 8 deletions(-) mode change 100755 => 100644 include/boost/graph/vf2_sub_graph_iso.hpp create mode 100644 test/vf2_sub_graph_iso_test_2.cpp diff --git a/include/boost/graph/vf2_sub_graph_iso.hpp b/include/boost/graph/vf2_sub_graph_iso.hpp old mode 100755 new mode 100644 index 21011b516..f86b6ee2a --- a/include/boost/graph/vf2_sub_graph_iso.hpp +++ b/include/boost/graph/vf2_sub_graph_iso.hpp @@ -690,11 +690,13 @@ namespace boost { typedef vf2_match_continuation match_continuation_type; std::vector k; + bool found_match = false; recur: if (s.success()) { if (!s.call_back(user_callback)) - return false; + return true; + found_match = true; goto back_track; } @@ -726,7 +728,7 @@ namespace boost { back_track: if (k.empty()) - return true; + return found_match; const match_continuation_type kk = k.back(); graph1_verts_iter = kk.graph1_verts_iter; @@ -887,9 +889,6 @@ namespace boost { if (num_edges_small > num_edges_large) return false; - if ((num_vertices(graph_small) == 0) && (num_vertices(graph_large) == 0)) - return true; - detail::state @@ -1123,9 +1122,6 @@ namespace boost { if (num_edges1 != num_edges2) return false; - if ((num_vertices(graph1) == 0) && (num_vertices(graph2) == 0)) - return true; - detail::state diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index a41d23361..5487631ff 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -128,6 +128,7 @@ test-suite graph_test : [ run stoer_wagner_test.cpp ../../test/build//boost_unit_test_framework/static : $(TEST_DIR) ] [ compile filtered_graph_properties_dijkstra.cpp ] [ run vf2_sub_graph_iso_test.cpp ] + [ run vf2_sub_graph_iso_test_2.cpp ] [ run hawick_circuits.cpp ] [ run successive_shortest_path_nonnegative_weights_test.cpp ../../test/build//boost_unit_test_framework/static ] [ run cycle_canceling_test.cpp ../../test/build//boost_unit_test_framework/static ] diff --git a/test/vf2_sub_graph_iso_test_2.cpp b/test/vf2_sub_graph_iso_test_2.cpp new file mode 100644 index 000000000..c5c7664ae --- /dev/null +++ b/test/vf2_sub_graph_iso_test_2.cpp @@ -0,0 +1,194 @@ +//======================================================================= +// Boost.Graph library vf2_sub_graph_iso test 2 +// Test of return value and behaviour with empty graphs +// +// Copyright (C) 2013 Jakob Lykke Andersen, University of Southern Denmark (jlandersen@imada.sdu.dk) +// +// 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) +//======================================================================= + +#include +#include +#include +#include + +struct test_callback { + test_callback(bool &got_hit, bool stop) : got_hit(got_hit), stop(stop) { } + + template + bool operator()(Map1To2 map1to2, Map2To1 map2to1) { + got_hit = true; + return stop; + } + + bool &got_hit; + bool stop; +}; + +struct false_predicate { + template + bool operator()(VertexOrEdge1 ve1, VertexOrEdge2 ve2) const { + return false; + } +}; + +void test_empty_graph_cases() { + typedef boost::adjacency_list Graph; + Graph gEmpty, gLarge; + add_vertex(gLarge); + + { // isomorphism + bool got_hit = false; + test_callback callback(got_hit, true); + bool exists = vf2_graph_iso(gEmpty, gEmpty, callback); + BOOST_CHECK(exists); + BOOST_CHECK(got_hit); // even empty matches are reported + } + { // subgraph isomorphism (induced) + { // empty vs. empty + bool got_hit = false; + test_callback callback(got_hit, true); + bool exists = vf2_subgraph_iso(gEmpty, gEmpty, callback); + BOOST_CHECK(exists); + BOOST_CHECK(got_hit); // even empty matches are reported + } + { // empty vs. non-empty + bool got_hit = false; + test_callback callback(got_hit, true); + bool exists = vf2_subgraph_iso(gEmpty, gLarge, callback); + BOOST_CHECK(exists); + BOOST_CHECK(got_hit); // even empty matches are reported + } + } + { // subgraph monomorphism (non-induced subgraph isomorphism) + { // empty vs. empty + bool got_hit = false; + test_callback callback(got_hit, true); + bool exists = vf2_subgraph_mono(gEmpty, gEmpty, callback); + BOOST_CHECK(exists); + BOOST_CHECK(got_hit); // even empty matches are reported + } + { // empty vs. non-empty + bool got_hit = false; + test_callback callback(got_hit, true); + bool exists = vf2_subgraph_mono(gEmpty, gLarge, callback); + BOOST_CHECK(exists); + BOOST_CHECK(got_hit); // even empty matches are reported + } + } +} + +void test_return_value() { + typedef boost::adjacency_list Graph; + typedef boost::graph_traits::vertex_descriptor Vertex; + Graph gSmall, gLarge; + add_vertex(gSmall); + Vertex v1 = add_vertex(gLarge); + Vertex v2 = add_vertex(gLarge); + add_edge(v1, v2, gLarge); + + { // isomorphism + { // no morphism due to sizes + bool got_hit = false; + test_callback callback(got_hit, true); + bool exists = vf2_graph_iso(gSmall, gLarge, callback); + BOOST_CHECK(!exists); + BOOST_CHECK(!got_hit); + } + { // no morphism due to vertex mismatches + bool got_hit = false; + test_callback callback(got_hit, true); + false_predicate pred; + bool exists = vf2_graph_iso(gLarge, gLarge, callback, vertex_order_by_mult(gLarge), + boost::edges_equivalent(pred).vertices_equivalent(pred)); + BOOST_CHECK(!exists); + BOOST_CHECK(!got_hit); + } + { // morphism, find all + bool got_hit = false; + test_callback callback(got_hit, false); + bool exists = vf2_graph_iso(gLarge, gLarge, callback); + BOOST_CHECK(exists); + BOOST_CHECK(got_hit); + } + { // morphism, stop after first hit + bool got_hit = false; + test_callback callback(got_hit, true); + bool exists = vf2_graph_iso(gLarge, gLarge, callback); + BOOST_CHECK(exists); + BOOST_CHECK(got_hit); + } + } + { // subgraph isomorphism (induced) + { // no morphism due to sizes + bool got_hit = false; + test_callback callback(got_hit, true); + bool exists = vf2_subgraph_iso(gLarge, gSmall, callback); + BOOST_CHECK(!exists); + BOOST_CHECK(!got_hit); + } + { // no morphism due to vertex mismatches + bool got_hit = false; + test_callback callback(got_hit, true); + false_predicate pred; + bool exists = vf2_subgraph_iso(gLarge, gLarge, callback, vertex_order_by_mult(gLarge), + boost::edges_equivalent(pred).vertices_equivalent(pred)); + BOOST_CHECK(!exists); + BOOST_CHECK(!got_hit); + } + { // morphism, find all + bool got_hit = false; + test_callback callback(got_hit, false); + bool exists = vf2_subgraph_iso(gLarge, gLarge, callback); + BOOST_CHECK(exists); + BOOST_CHECK(got_hit); + } + { // morphism, stop after first hit + bool got_hit = false; + test_callback callback(got_hit, true); + bool exists = vf2_subgraph_iso(gLarge, gLarge, callback); + BOOST_CHECK(exists); + BOOST_CHECK(got_hit); + } + } + { // subgraph monomorphism (non-induced subgraph isomorphism) + { // no morphism due to sizes + bool got_hit = false; + test_callback callback(got_hit, true); + bool exists = vf2_subgraph_mono(gLarge, gSmall, callback); + BOOST_CHECK(!exists); + BOOST_CHECK(!got_hit); + } + { // no morphism due to vertex mismatches + bool got_hit = false; + test_callback callback(got_hit, true); + false_predicate pred; + bool exists = vf2_subgraph_mono(gLarge, gLarge, callback, vertex_order_by_mult(gLarge), + boost::edges_equivalent(pred).vertices_equivalent(pred)); + BOOST_CHECK(!exists); + BOOST_CHECK(!got_hit); + } + { // morphism, find all + bool got_hit = false; + test_callback callback(got_hit, false); + bool exists = vf2_subgraph_mono(gLarge, gLarge, callback); + BOOST_CHECK(exists); + BOOST_CHECK(got_hit); + } + { // morphism, stop after first hit + bool got_hit = false; + test_callback callback(got_hit, true); + bool exists = vf2_subgraph_mono(gLarge, gLarge, callback); + BOOST_CHECK(exists); + BOOST_CHECK(got_hit); + } + } +} + +int test_main(int argc, char* argv[]) { + test_empty_graph_cases(); + test_return_value(); + return 0; +} From db6e8b798157b4fefa5d89a5b22d85d69f856082 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Mon, 21 Oct 2013 18:29:04 +0000 Subject: [PATCH 325/333] Moved parts of PBGL used by parallel property maps over to property map directories and namespaces; this fixes circular dependencies between these two libraries (assuming boost/property_map/parallel is treated as a separate library) [SVN r86381] --- include/boost/graph/detail/edge.hpp | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/include/boost/graph/detail/edge.hpp b/include/boost/graph/detail/edge.hpp index 253dae2d2..badf28d4f 100644 --- a/include/boost/graph/detail/edge.hpp +++ b/include/boost/graph/detail/edge.hpp @@ -105,5 +105,15 @@ namespace std { } } +// Boost's functional/hash +namespace boost { + template + struct hash > + { + std::size_t operator()(const boost::detail::edge_desc_impl & x) const + { return hash_value(x.get_property()); } + }; +} + #endif // BOOST_GRAPH_DETAIL_DETAIL_EDGE_HPP From 031ce8084b5ca6e79b359b3a3fee671115fffc41 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Sat, 26 Oct 2013 15:30:09 +0000 Subject: [PATCH 326/333] Changed random_access_iterator_property_map to iterator_property_map in documentation; fixes #9300 [SVN r86456] --- doc/using_property_maps.html | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/doc/using_property_maps.html b/doc/using_property_maps.html index 451e858e1..661e66e05 100644 --- a/doc/using_property_maps.html +++ b/doc/using_property_maps.html @@ -219,7 +219,7 @@

      The first method uses the adaptor class -random_access_iterator_property_map. This +iterator_property_map. This class wraps a random access iterator, creating a property map out of it. The random access iterator must point to the beginning of a range of property values, and the length of the range must be the @@ -229,7 +229,7 @@

      edge descriptor to the offset of the property value (offset from the random access iterator). The ID property map will typically be an interior property map of the graph. The following example shows -how the random_access_iterator_property_map +how the iterator_property_map can be used to create exterior property maps for the capacity and flow properties, which are stored in arrays. The arrays are indexed by edge ID. The edge ID is added to the graph using a property, and the values of the ID's are given when each edge is added to the @@ -257,7 +257,7 @@

      typedef property_map<Graph, edge_index_t>::type EdgeID_Map; EdgeID_Map edge_id = get(edge_index, G); - random_access_iterator_property_map + iterator_property_map <int*, int, int&, EdgeID_Map> capacity(capacity_array, edge_id), flow(flow_array, edge_id); @@ -276,7 +276,7 @@

      VertexList is not vecS, then the vertex descriptor is not an integer, and cannot be used with a pointer property map. Instead the method described above of using a -random_access_iterator_property_map with an ID +iterator_property_map with an ID property must be used. The edge_list class may also use an integer type for the vertex descriptor, depending on how the adapted edge iterator is defined. The example in @@ -388,10 +388,10 @@

      The implementation of the -random_access_iterator_property_map class +iterator_property_map class serves as a good example for how to build and exterior property map. Here we present a simplified implementation of the -random_access_iterator_property_map class +iterator_property_map class which we will name iterator_pa.

      @@ -462,7 +462,7 @@

      That is it. The iterator_map class is complete and could be used just like the -random_access_iterator_property_map in the +iterator_property_map in the previous section.

      From 4af610830bb19248019ae47fab6a06916c8b4916 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Sat, 26 Oct 2013 22:57:10 +0000 Subject: [PATCH 327/333] Fixed edge_range bug from http://stackoverflow.com/questions/19223692/boost-graph-library-directed-multigraph-edge-range-bug?rq=1 [SVN r86469] --- include/boost/graph/detail/adjacency_list.hpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/include/boost/graph/detail/adjacency_list.hpp b/include/boost/graph/detail/adjacency_list.hpp index 16cf02678..87fd55747 100644 --- a/include/boost/graph/detail/adjacency_list.hpp +++ b/include/boost/graph/detail/adjacency_list.hpp @@ -1610,8 +1610,7 @@ namespace boost { typename Config::OutEdgeList::iterator first, last; typename Config::EdgeContainer fake_edge_container; boost::tie(first, last) = graph_detail:: - equal_range(el, StoredEdge(v, fake_edge_container.end(), - &fake_edge_container)); + equal_range(el, StoredEdge(v)); return std::make_pair(out_edge_iterator(first, u), out_edge_iterator(last, u)); } From a9b0657fd3eb270230af1f2ee18336a6c32840f6 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Mon, 28 Oct 2013 16:40:16 +0000 Subject: [PATCH 328/333] Fixed figure caption; fixes #9312 [SVN r86502] --- doc/adjacency_matrix.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/adjacency_matrix.html b/doc/adjacency_matrix.html index f074f5b44..7bcd1c9ec 100644 --- a/doc/adjacency_matrix.html +++ b/doc/adjacency_matrix.html @@ -74,7 +74,7 @@

      - +
      Figure 1: Adjacency Matrix Representation of an Undirected Graph.Figure 2: Adjacency Matrix Representation of an Undirected Graph.
      From 332b49261c803b96e53582261946bba600ca1cd3 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Wed, 6 Nov 2013 21:16:55 +0000 Subject: [PATCH 329/333] Fixed invalid uses of "typename" [SVN r86577] --- test/make_connected_test.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/make_connected_test.cpp b/test/make_connected_test.cpp index bc4a9104d..d1d5d41df 100644 --- a/test/make_connected_test.cpp +++ b/test/make_connected_test.cpp @@ -116,7 +116,7 @@ int test_main(int, char* []) std::vector gVV_components(num_vertices(gVV)); boost::iterator_property_map< std::vector::iterator, - typename boost::property_map::const_type + boost::property_map::const_type > gVV_components_pm(gVV_components.begin(), get(boost::vertex_index, gVV)); BOOST_CHECK(connected_components(gVV, gVV_components_pm) == static_cast(num_cycles)); @@ -132,7 +132,7 @@ int test_main(int, char* []) std::vector gLV_components(num_vertices(gLV)); boost::iterator_property_map< std::vector::iterator, - typename boost::property_map::const_type + boost::property_map::const_type > gLV_components_pm(gLV_components.begin(), get(boost::vertex_index, gLV)); BOOST_CHECK(connected_components(gLV, gLV_components_pm) == static_cast(num_cycles)); From 983be4b9e726ba25bc907ce968af709bf54bbfef Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Sat, 9 Nov 2013 19:06:06 +0000 Subject: [PATCH 330/333] Added graph property support to write_graphviz_dp [SVN r86604] --- include/boost/graph/graphviz.hpp | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/include/boost/graph/graphviz.hpp b/include/boost/graph/graphviz.hpp index df10806cd..1c8cb194a 100644 --- a/include/boost/graph/graphviz.hpp +++ b/include/boost/graph/graphviz.hpp @@ -536,6 +536,28 @@ namespace boost { const std::string* node_id; }; + template + class dynamic_graph_properties_writer + { + public: + dynamic_graph_properties_writer(const dynamic_properties& dp, const Graph& g) : g(&g), dp(&dp) { } + + void operator()(std::ostream& out) const + { + for (dynamic_properties::const_iterator i = dp->begin(); + i != dp->end(); ++i) { + if (typeid(Graph*) == i->second->key()) { + // const_cast here is to match interface used in read_graphviz + out << i->first << "=" << escape_dot_string(i->second->get_string(const_cast(g))) << ";\n"; + } + } + } + + private: + const Graph* g; + const dynamic_properties* dp; + }; + namespace graph { namespace detail { template @@ -587,7 +609,7 @@ namespace boost { (out, g, /*vertex_writer=*/dynamic_vertex_properties_writer(dp, node_id), /*edge_writer=*/dynamic_properties_writer(dp), - /*graph_writer=*/default_writer(), + /*graph_writer=*/dynamic_graph_properties_writer(dp, g), id); } From cec654dedbfe979dfcc1b209c6396ff47633f9fa Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Wed, 13 Nov 2013 17:36:02 +0000 Subject: [PATCH 331/333] Changed some names to fix shadowing warnings; refs #9371 [SVN r86680] --- include/boost/graph/graph_concepts.hpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/include/boost/graph/graph_concepts.hpp b/include/boost/graph/graph_concepts.hpp index 90a7cb043..875f81848 100644 --- a/include/boost/graph/graph_concepts.hpp +++ b/include/boost/graph/graph_concepts.hpp @@ -469,10 +469,10 @@ typename T::ThereReallyIsNoMemberByThisNameInT vertices(T const&); const_constraints(g); } - void const_constraints(const Graph& g) + void const_constraints(const Graph& g_) { typedef typename property_map::const_type Map; - Map m = get(vertex_index, g); + Map m = get(vertex_index, g_); ignore_unused_variable_warning(m); } private: @@ -496,10 +496,10 @@ typename T::ThereReallyIsNoMemberByThisNameInT vertices(T const&); const_constraints(g); } - void const_constraints(const Graph& g) + void const_constraints(const Graph& g_) { typedef typename property_map::const_type Map; - Map m = get(edge_index, g); + Map m = get(edge_index, g_); ignore_unused_variable_warning(m); } private: From cb26ccf2ba18e0110585b939bac2c212b514c473 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Sun, 17 Nov 2013 02:18:42 +0000 Subject: [PATCH 332/333] Changed to use unique_ptr when C++11 is enabled; made other fixes to enable move semantics [SVN r86733] --- include/boost/graph/detail/adjacency_list.hpp | 30 +++++++++++++++-- include/boost/pending/container_traits.hpp | 32 +++++++++++++------ 2 files changed, 50 insertions(+), 12 deletions(-) diff --git a/include/boost/graph/detail/adjacency_list.hpp b/include/boost/graph/detail/adjacency_list.hpp index 87fd55747..9e6b623ee 100644 --- a/include/boost/graph/detail/adjacency_list.hpp +++ b/include/boost/graph/detail/adjacency_list.hpp @@ -38,6 +38,12 @@ #include #include +#ifdef BOOST_NO_CXX11_RVALUE_REFERENCES +#define BOOST_GRAPH_MOVE_IF_POSSIBLE(x) (x) +#else +#define BOOST_GRAPH_MOVE_IF_POSSIBLE(x) (std::move((x))) +#endif + /* Outline for this file: @@ -251,6 +257,7 @@ namespace boost { template no_property stored_edge::s_prop; +#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES) || defined(BOOST_NO_CXX11_DEFAULTED_FUNCTIONS) template class stored_edge_property : public stored_edge { typedef stored_edge_property self; @@ -277,6 +284,25 @@ namespace boost { // a perfect fit for the job, but it is darn close. std::auto_ptr m_property; }; +#else + template + class stored_edge_property : public stored_edge { + typedef stored_edge_property self; + typedef stored_edge Base; + public: + typedef Property property_type; + inline stored_edge_property() { } + inline stored_edge_property(Vertex target, + const Property& p = Property()) + : stored_edge(target), m_property(new Property(p)) { } + stored_edge_property(self&& x) = default; + self& operator=(self&& x) = default; + inline Property& get_property() { return *m_property; } + inline const Property& get_property() const { return *m_property; } + protected: + std::unique_ptr m_property; + }; +#endif template @@ -384,7 +410,7 @@ namespace boost { if (first != last) for (++i; i != last; ++i) if (!pred(*i)) { - *first.base() = *i.base(); + *first.base() = BOOST_GRAPH_MOVE_IF_POSSIBLE(*i.base()); ++first; } el.erase(first.base(), el.end()); @@ -432,7 +458,7 @@ namespace boost { self_loop_removed = false; } else if (!pred(*i)) { - *first.base() = *i.base(); + *first.base() = BOOST_GRAPH_MOVE_IF_POSSIBLE(*i.base()); ++first; } else { if (source(*i, g) == target(*i, g)) self_loop_removed = true; diff --git a/include/boost/pending/container_traits.hpp b/include/boost/pending/container_traits.hpp index 3577487f6..a58b52450 100644 --- a/include/boost/pending/container_traits.hpp +++ b/include/boost/pending/container_traits.hpp @@ -15,6 +15,7 @@ #include #include // for std::remove +#include #include #include #include @@ -38,6 +39,14 @@ #include #endif +#ifdef BOOST_NO_CXX11_RVALUE_REFERENCES +#define BOOST_PENDING_FWD_TYPE(type) const type& +#define BOOST_PENDING_FWD_VALUE(type, var) (var) +#else +#define BOOST_PENDING_FWD_TYPE(type) type&& +#define BOOST_PENDING_FWD_VALUE(type, var) (std::forward((var))) +#endif + // The content of this file is in 'graph_detail' because otherwise // there will be name clashes with // sandbox/boost/sequence_algo/container_traits.hpp @@ -484,41 +493,41 @@ namespace boost { namespace graph_detail { // Push template std::pair - push_dispatch(Container& c, const T& v, back_insertion_sequence_tag) + push_dispatch(Container& c, BOOST_PENDING_FWD_TYPE(T) v, back_insertion_sequence_tag) { - c.push_back(v); + c.push_back(BOOST_PENDING_FWD_VALUE(T, v)); return std::make_pair(boost::prior(c.end()), true); } template std::pair - push_dispatch(Container& c, const T& v, front_insertion_sequence_tag) + push_dispatch(Container& c, BOOST_PENDING_FWD_TYPE(T) v, front_insertion_sequence_tag) { - c.push_front(v); + c.push_front(BOOST_PENDING_FWD_VALUE(T, v)); return std::make_pair(c.begin(), true); } template std::pair - push_dispatch(AssociativeContainer& c, const T& v, + push_dispatch(AssociativeContainer& c, BOOST_PENDING_FWD_TYPE(T) v, unique_associative_container_tag) { - return c.insert(v); + return c.insert(BOOST_PENDING_FWD_VALUE(T, v)); } template std::pair - push_dispatch(AssociativeContainer& c, const T& v, + push_dispatch(AssociativeContainer& c, BOOST_PENDING_FWD_TYPE(T) v, multiple_associative_container_tag) { - return std::make_pair(c.insert(v), true); + return std::make_pair(c.insert(BOOST_PENDING_FWD_VALUE(T, v)), true); } template std::pair - push(Container& c, const T& v) + push(Container& c, BOOST_PENDING_FWD_TYPE(T) v) { - return push_dispatch(c, v, container_category(c)); + return push_dispatch(c, BOOST_PENDING_FWD_VALUE(T, v), container_category(c)); } // Find @@ -615,4 +624,7 @@ namespace boost { namespace graph_detail { }} // namespace boost::graph_detail +#undef BOOST_PENDING_FWD_TYPE +#undef BOOST_PENDING_FWD_VALUE + #endif // BOOST_GRAPH_DETAIL_CONTAINER_TRAITS_H From 61e83ed675d041c07b0ef45acafc85b06755a955 Mon Sep 17 00:00:00 2001 From: Ciro Santilli Date: Mon, 28 Apr 2014 09:11:23 +0200 Subject: [PATCH 333/333] Rename color header to more precise title. --- doc/quick_tour.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/quick_tour.html b/doc/quick_tour.html index 5156bb7bf..cee009259 100644 --- a/doc/quick_tour.html +++ b/doc/quick_tour.html @@ -386,7 +386,7 @@

      Adjacent Vertices

      adjacent vertices: 0 1

        -

      Adding Some Color to your Graph

      +

      Vertex and Edge Properties

      BGL attempts to be as flexible as possible in terms of accommodating how properties are attached to a graph. For instance, a property such as edge weight may need to be used throughout a graph object's lifespan and therefore it would

  • Table of Contents: the Boost Graph Library
  • Miscellaneous Algorithms
    1. metric_tsp_approx
    2. -
    3. sequential_vertex_coloring -
    4. is_bipartite (including two-coloring of bipartite graphs) -
    5. find_odd_cycle -
    6. maximum_adjacency_search +
    7. sequential_vertex_coloring
    8. +
    9. is_bipartite (including two-coloring of bipartite graphs)
    10. +
    11. find_odd_cycle
    12. +
    13. maximum_adjacency_search
    14. +
    15. hawick_circuits (find all circuits of a directed graph)
  • diff --git a/example/Jamfile.v2 b/example/Jamfile.v2 index ce155c676..e2b45201a 100644 --- a/example/Jamfile.v2 +++ b/example/Jamfile.v2 @@ -50,4 +50,5 @@ exe subgraph_properties : subgraph_properties.cpp ; exe vf2_sub_graph_iso_example : vf2_sub_graph_iso_example.cpp ; exe vf2_sub_graph_iso_multi_example : vf2_sub_graph_iso_multi_example.cpp ; exe sloan_ordering : sloan_ordering.cpp ; +exe hawick_circuits : hawick_circuits.cpp ; diff --git a/example/hawick_circuits.cpp b/example/hawick_circuits.cpp new file mode 100644 index 000000000..b29467b9e --- /dev/null +++ b/example/hawick_circuits.cpp @@ -0,0 +1,96 @@ +// Copyright Louis Dionne 2013 + +// Use, modification and distribution is subject to 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) + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +template +struct cycle_printer +{ + cycle_printer(OutputStream& stream) + : os(stream) + { } + + template + void cycle(Path const& p, Graph const& g) + { + if (p.empty()) + return; + + // Get the property map containing the vertex indices + // so we can print them. + typedef typename boost::property_map< + Graph, boost::vertex_index_t + >::const_type IndexMap; + + IndexMap indices = get(boost::vertex_index, g); + + // Iterate over path printing each vertex that forms the cycle. + typename Path::const_iterator i, before_end = boost::prior(p.end()); + for (i = p.begin(); i != before_end; ++i) { + os << get(indices, *i) << " "; + } + os << get(indices, *i) << '\n'; + } + OutputStream& os; +}; + + +// VertexPairIterator is an iterator over pairs of whitespace separated +// vertices `u` and `v` representing a directed edge from `u` to `v`. +template +void build_graph(Graph& graph, unsigned int const nvertices, + VertexPairIterator first, VertexPairIterator last) { + typedef boost::graph_traits Traits; + typedef typename Traits::vertex_descriptor vertex_descriptor; + std::map vertices; + + for (unsigned int i = 0; i < nvertices; ++i) + vertices[i] = add_vertex(graph); + + for (; first != last; ++first) { + unsigned int u = *first++; + + BOOST_ASSERT_MSG(first != last, + "there is a lonely vertex at the end of the edge list"); + + unsigned int v = *first; + + BOOST_ASSERT_MSG(vertices.count(u) == 1 && vertices.count(v) == 1, + "specified a vertex over the number of vertices in the graph"); + + add_edge(vertices[u], vertices[v], graph); + } + BOOST_ASSERT(num_vertices(graph) == nvertices); +} + + +int main(int argc, char const* argv[]) { + if (argc < 2) { + std::cout << "usage: " << argv[0] << " num_vertices < input\n"; + return EXIT_FAILURE; + } + + unsigned int num_vertices = boost::lexical_cast(argv[1]); + std::istream_iterator first_vertex(std::cin), last_vertex; + boost::directed_graph<> graph; + build_graph(graph, num_vertices, first_vertex, last_vertex); + + cycle_printer visitor(std::cout); + boost::hawick_circuits(graph, visitor); + + return EXIT_SUCCESS; +} diff --git a/include/boost/graph/hawick_circuits.hpp b/include/boost/graph/hawick_circuits.hpp new file mode 100644 index 000000000..f2500354f --- /dev/null +++ b/include/boost/graph/hawick_circuits.hpp @@ -0,0 +1,381 @@ +// Copyright Louis Dionne 2013 + +// Use, modification and distribution is subject to 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_GRAPH_HAWICK_CIRCUITS_HPP +#define BOOST_GRAPH_HAWICK_CIRCUITS_HPP + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include // for boost::tie +#include +#include +#include +#include // for std::pair +#include + + +namespace boost { +namespace hawick_circuits_detail { +//! @internal Functor returning all the vertices adjacent to a vertex. +struct get_all_adjacent_vertices { + template + struct result; + + template + struct result { + private: + typedef typename remove_reference::type RawGraph; + typedef graph_traits Traits; + typedef typename Traits::adjacency_iterator AdjacencyIterator; + + public: + typedef std::pair type; + }; + + template + typename result< + get_all_adjacent_vertices(BOOST_FWD_REF(Vertex), BOOST_FWD_REF(Graph)) + >::type + operator()(BOOST_FWD_REF(Vertex) v, BOOST_FWD_REF(Graph) g) const { + return adjacent_vertices(boost::forward(v), + boost::forward(g)); + } +}; + +//! @internal Functor returning a set of the vertices adjacent to a vertex. +struct get_unique_adjacent_vertices { + template + struct result; + + template + struct result { + typedef std::set::type> type; + }; + + template + typename result::type + operator()(Vertex v, Graph const& g) const { + typedef typename result< + get_unique_adjacent_vertices(Vertex, Graph const&) + >::type Set; + return Set(adjacent_vertices(v, g).first, + adjacent_vertices(v, g).second); + } +}; + +//! @internal +//! Return whether a container contains a given value. +//! This is not meant as a general purpose membership testing function; it +//! would have to be more clever about possible optimizations. +template +bool contains(Container const& c, Value const& v) { + return std::find(boost::begin(c), boost::end(c), v) != boost::end(c); +} + +/*! + * @internal + * Algorithm finding all the cycles starting from a given vertex. + * + * The search is only done in the subgraph induced by the starting vertex + * and the vertices with an index higher than the starting vertex. + */ +template < + typename Graph, + typename Visitor, + typename VertexIndexMap, + typename Stack, + typename ClosedMatrix, + typename GetAdjacentVertices +> +struct hawick_circuits_from { +private: + typedef graph_traits Traits; + typedef typename Traits::vertex_descriptor Vertex; + typedef typename Traits::edge_descriptor Edge; + typedef typename Traits::vertices_size_type VerticesSize; + typedef typename property_traits::reference VertexIndex; + + typedef typename result_of< + GetAdjacentVertices(Vertex, Graph const&) + >::type AdjacentVertices; + typedef typename range_iterator::type AdjacencyIterator; + + // The one_bit_color_map starts all white, i.e. not blocked. + // Since we make that assumption (I looked at the implementation, but + // I can't find anything that documents this behavior), we're gonna + // assert it in the constructor. + typedef one_bit_color_map BlockedMap; + typedef typename property_traits::value_type BlockedColor; + + static BlockedColor blocked_false_color() + { return color_traits::white(); } + + static BlockedColor blocked_true_color() + { return color_traits::black(); } + + // This is used by the constructor to secure the assumption + // documented above. + bool blocked_map_starts_all_unblocked() const { + BOOST_FOREACH(Vertex v, vertices(graph_)) + if (is_blocked(v)) + return false; + return true; + } + + // This is only used in the constructor to make sure the optimization of + // sharing data structures between iterations does not break the code. + bool all_closed_rows_are_empty() const { + BOOST_FOREACH(typename ClosedMatrix::reference row, closed_) + if (!row.empty()) + return false; + return true; + } + +public: + hawick_circuits_from(Graph const& graph, Visitor& visitor, + VertexIndexMap const& vim, + Stack& stack, ClosedMatrix& closed, + VerticesSize n_vertices) + : graph_(graph), visitor_(visitor), vim_(vim), stack_(stack), + closed_(closed), blocked_(n_vertices, vim_) + { + BOOST_ASSERT(blocked_map_starts_all_unblocked()); + + // Since sharing the data structures between iterations is + // just an optimization, it must always be equivalent to + // constructing new ones in this constructor. + BOOST_ASSERT(stack_.empty()); + BOOST_ASSERT(closed_.size() == n_vertices); + BOOST_ASSERT(all_closed_rows_are_empty()); + } + +private: + //! @internal Return the index of a given vertex. + VertexIndex index_of(Vertex v) const { + return get(vim_, v); + } + + + //! @internal Return whether a vertex `v` is closed to a vertex `u`. + bool is_closed_to(Vertex u, Vertex v) const { + typedef typename ClosedMatrix::const_reference VertexList; + VertexList closed_to_u = closed_[index_of(u)]; + return contains(closed_to_u, v); + } + + //! @internal Close a vertex `v` to a vertex `u`. + void close_to(Vertex u, Vertex v) { + BOOST_ASSERT(!is_closed_to(u, v)); + closed_[index_of(u)].push_back(v); + } + + + //! @internal Return whether a given vertex is blocked. + bool is_blocked(Vertex v) const { + return get(blocked_, v) == blocked_true_color(); + } + + //! @internal Block a given vertex. + void block(Vertex v) { + put(blocked_, v, blocked_true_color()); + } + + //! @internal Unblock a given vertex. + void unblock(Vertex u) { + typedef typename ClosedMatrix::reference VertexList; + + put(blocked_, u, blocked_false_color()); + VertexList closed_to_u = closed_[index_of(u)]; + + while (!closed_to_u.empty()) { + Vertex const w = closed_to_u.back(); + closed_to_u.pop_back(); + if (is_blocked(w)) + unblock(w); + } + BOOST_ASSERT(closed_to_u.empty()); + } + + //! @internal Main procedure as described in the paper. + bool circuit(Vertex start, Vertex v) { + bool found_circuit = false; + stack_.push_back(v); + block(v); + + // Cache some values that are used more than once in the function. + VertexIndex const index_of_start = index_of(start); + AdjacentVertices const adj_vertices = GetAdjacentVertices()(v, graph_); + AdjacencyIterator const w_end = boost::end(adj_vertices); + + for (AdjacencyIterator w_it = boost::begin(adj_vertices); + w_it != w_end; + ++w_it) + { + Vertex const w = *w_it; + // Since we're only looking in the subgraph induced by `start` + // and the vertices with an index higher than `start`, we skip + // any vertex that does not satisfy that. + if (index_of(w) < index_of_start) + continue; + + // If the last vertex is equal to `start`, we have a circuit. + else if (w == start) { + // const_cast to ensure the visitor does not modify the stack + visitor_.cycle(const_cast(stack_), graph_); + found_circuit = true; + } + + // If `w` is not blocked, we continue searching further down the + // same path for a cycle with `w` in it. + else if (!is_blocked(w) && circuit(start, w)) + found_circuit = true; + } + + if (found_circuit) + unblock(v); + else + for (AdjacencyIterator w_it = boost::begin(adj_vertices); + w_it != w_end; + ++w_it) + { + Vertex const w = *w_it; + // Like above, we skip vertices that are not in the subgraph + // we're considering. + if (index_of(w) < index_of_start) + continue; + + // If `v` is not closed to `w`, we make it so. + if (!is_closed_to(w, v)) + close_to(w, v); + } + + BOOST_ASSERT(v == stack_.back()); + stack_.pop_back(); + return found_circuit; + } + +public: + void operator()(Vertex start) { + circuit(start, start); + } + +private: + Graph const& graph_; + Visitor& visitor_; + VertexIndexMap const& vim_; + Stack& stack_; + ClosedMatrix& closed_; + BlockedMap blocked_; +}; + +template < + typename GetAdjacentVertices, + typename Graph, typename Visitor, typename VertexIndexMap +> +void call_hawick_circuits(Graph const& graph, + Visitor /* by value */ visitor, + VertexIndexMap const& vertex_index_map) { + typedef graph_traits Traits; + typedef typename Traits::vertex_descriptor Vertex; + typedef typename Traits::vertices_size_type VerticesSize; + typedef typename Traits::vertex_iterator VertexIterator; + + typedef std::vector Stack; + typedef std::vector > ClosedMatrix; + + typedef hawick_circuits_from< + Graph, Visitor, VertexIndexMap, Stack, ClosedMatrix, + GetAdjacentVertices + > SubAlgorithm; + + VerticesSize const n_vertices = num_vertices(graph); + Stack stack; stack.reserve(n_vertices); + ClosedMatrix closed(n_vertices); + + VertexIterator start, last; + for (boost::tie(start, last) = vertices(graph); start != last; ++start) { + // Note1: The sub algorithm may NOT be reused once it has been called. + + // Note2: We reuse the Stack and the ClosedMatrix (after clearing them) + // in each iteration to avoid redundant destruction and construction. + // It would be strictly equivalent to have these as member variables + // of the sub algorithm. + SubAlgorithm sub_algo(graph, visitor, vertex_index_map, + stack, closed, n_vertices); + sub_algo(*start); + stack.clear(); + typename ClosedMatrix::iterator row, last_row = closed.end(); + for (row = closed.begin(); row != last_row; ++row) + row->clear(); + } +} + +template +void call_hawick_circuits(Graph const& graph, BOOST_FWD_REF(Visitor) visitor) { + call_hawick_circuits( + graph, boost::forward(visitor), get(vertex_index, graph) + ); +} +} // end namespace hawick_circuits_detail + +//! Enumerate all the elementary circuits in a directed multigraph. +template +void hawick_circuits(BOOST_FWD_REF(Graph) graph, + BOOST_FWD_REF(Visitor) visitor, + BOOST_FWD_REF(VertexIndexMap) vertex_index_map) { + hawick_circuits_detail::call_hawick_circuits< + hawick_circuits_detail::get_all_adjacent_vertices + >( + boost::forward(graph), + boost::forward(visitor), + boost::forward(vertex_index_map) + ); +} + +template +void hawick_circuits(BOOST_FWD_REF(Graph) graph, + BOOST_FWD_REF(Visitor) visitor) { + hawick_circuits_detail::call_hawick_circuits< + hawick_circuits_detail::get_all_adjacent_vertices + >(boost::forward(graph), boost::forward(visitor)); +} + +/*! + * Same as `boost::hawick_circuits`, but duplicate circuits caused by parallel + * edges will not be considered. Each circuit will be considered only once. + */ +template +void hawick_unique_circuits(BOOST_FWD_REF(Graph) graph, + BOOST_FWD_REF(Visitor) visitor, + BOOST_FWD_REF(VertexIndexMap) vertex_index_map) { + hawick_circuits_detail::call_hawick_circuits< + hawick_circuits_detail::get_unique_adjacent_vertices + >( + boost::forward(graph), + boost::forward(visitor), + boost::forward(vertex_index_map) + ); +} + +template +void hawick_unique_circuits(BOOST_FWD_REF(Graph) graph, + BOOST_FWD_REF(Visitor) visitor) { + hawick_circuits_detail::call_hawick_circuits< + hawick_circuits_detail::get_unique_adjacent_vertices + >(boost::forward(graph), boost::forward(visitor)); +} +} // end namespace boost + +#endif // !BOOST_GRAPH_HAWICK_CIRCUITS_HPP diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 88d824608..37cebaa57 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -127,6 +127,7 @@ test-suite graph_test : [ run stoer_wagner_test.cpp ../../test/build//boost_unit_test_framework/static : $(TEST_DIR) ] [ compile filtered_graph_properties_dijkstra.cpp ] [ run vf2_sub_graph_iso_test.cpp ] + [ run hawick_circuits.cpp ] ; # Run SDB tests only when -sSDB= is set. diff --git a/test/cycle_test.hpp b/test/cycle_test.hpp new file mode 100644 index 000000000..b60bc3073 --- /dev/null +++ b/test/cycle_test.hpp @@ -0,0 +1,80 @@ +// (C) Copyright 2013 Louis Dionne +// +// Modified from `tiernan_all_cycles.cpp`. +// +// Use, modification and distribution are subject to the +// Boost Software License, Version 1.0 (See accompanying file +// LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GRAPH_TEST_CYCLE_TEST_HPP +#define BOOST_GRAPH_TEST_CYCLE_TEST_HPP + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +namespace cycle_test_detail { + using namespace boost; + + struct cycle_validator { + explicit cycle_validator(std::size_t& number_of_cycles) + : cycles(number_of_cycles) + { } + + template + void cycle(Path const& p, Graph const& g) { + ++cycles; + // Check to make sure that each of the vertices in the path + // is truly connected and that the back is connected to the + // front - it's not validating that we find all paths, just + // that the paths are valid. + typename Path::const_iterator i, j, last = prior(p.end()); + for (i = p.begin(); i != last; ++i) { + j = next(i); + BOOST_ASSERT(edge(*i, *j, g).second); + } + BOOST_ASSERT(edge(p.back(), p.front(), g).second); + } + + std::size_t& cycles; + }; + + template + void test_one(Algorithm algorithm) { + typedef erdos_renyi_iterator er; + + // Generate random graphs with 15 vertices and 15% probability + // of edge connection. + static std::size_t const N = 20; + static double const P = 0.1; + minstd_rand rng; + + Graph g(er(rng, N, P), er(), N); + renumber_indices(g); + print_edges(g, get(vertex_index, g)); + + std::size_t cycles = 0; + cycle_validator vis(cycles); + algorithm(g, vis); + std::cout << "# cycles: " << vis.cycles << "\n"; + } +} // end namespace cycle_test_detail + +template +void cycle_test(Algorithm const& algorithm) { + std::cout << "*** undirected ***\n"; + cycle_test_detail::test_one >(algorithm); + + std::cout << "*** directed ***\n"; + cycle_test_detail::test_one >(algorithm); +} + +#endif // !BOOST_GRAPH_TEST_CYCLE_TEST_HPP diff --git a/test/hawick_circuits.cpp b/test/hawick_circuits.cpp new file mode 100644 index 000000000..29b6470be --- /dev/null +++ b/test/hawick_circuits.cpp @@ -0,0 +1,32 @@ +// (C) Copyright 2013 Louis Dionne +// +// Use, modification and distribution are subject to the +// Boost Software License, Version 1.0 (See accompanying file +// LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + +#include "cycle_test.hpp" +#include +#include + + +struct call_hawick_circuits { + template + void operator()(Graph const& g, Visitor const& v) const { + boost::hawick_circuits(g, v); + } +}; + +struct call_hawick_unique_circuits { + template + void operator()(Graph const& g, Visitor const& v) const { + boost::hawick_unique_circuits(g, v); + } +}; + +int main() { + std::cout << "---------hawick_circuits---------\n"; + cycle_test(call_hawick_circuits()); + + std::cout << "\n\n---------hawick_unique_circuits---------\n"; + cycle_test(call_hawick_unique_circuits()); +} From 5297423229b60322e1652dfdc8c8b7475d863448 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Sat, 31 Aug 2013 19:44:08 +0000 Subject: [PATCH 300/333] Added edge coloring code from Maciej Piechotka; fixes #8317 [SVN r85534] --- doc/edge_coloring.html | 98 +++++++++++++ doc/table_of_contents.html | 1 + example/Jamfile.v2 | 1 + example/edge_coloring.cpp | 70 +++++++++ include/boost/graph/edge_coloring.hpp | 196 ++++++++++++++++++++++++++ 5 files changed, 366 insertions(+) create mode 100644 doc/edge_coloring.html create mode 100644 example/edge_coloring.cpp create mode 100644 include/boost/graph/edge_coloring.hpp diff --git a/doc/edge_coloring.html b/doc/edge_coloring.html new file mode 100644 index 000000000..7febb4692 --- /dev/null +++ b/doc/edge_coloring.html @@ -0,0 +1,98 @@ + + + + + +Boost Graph Library: Edge Coloring + +C++ Boost + +
    + +

    + +edge_coloring +

    + + +

    +

    + + + + + + + + + + +
    Graphs:undirected, loop-free
    Properties:color
    Complexity:time: O(|E| |V|)
    +
    + + +
    +  template <class Graph, class ColorMap>
    +  typename boost::property_traits::value_type
    +  edge_coloring(const Graph &g, ColorMap color);
    +
    + +

    Computes an edge coloring for the vertices in the graph, using +an algorithm proposed by Mista et al. []. Given edges ordered +e1, e2, ..., en it assignes a +colors c1, c2, ..., cn in a way +that no vertex connects with 2 edges of the same color. Furthermore +at most m + 1 colors are used. + + + +

    Where defined

    +boost/graph/edge_coloring.hpp + +

    Parameters

    + +IN: const Graph& g +
    + The graph object on which the algorithm will be applied. The type + Graph must be a model of + Edge List Graph and Incidence + Graph. +
    + +OUT: ColorMap color +
    + This property map records the colors of each edges. It must be a + model of + Read/Write Property Map whose key type is the same as the edge + descriptor type of the graph and whose value type is an integral type + that can store all values smaller or equal to m. +
    + + +

    Example

    + +See example/king_ordering.cpp. + +

    See Also

    + +sequential vertex ordering
    . + +
    +
    + + +
    Copyright © 2013 +Maciej Piechotka (uzytkownik2@gmail.com) +
    + + + diff --git a/doc/table_of_contents.html b/doc/table_of_contents.html index a2f5edf1a..1e5664e39 100644 --- a/doc/table_of_contents.html +++ b/doc/table_of_contents.html @@ -285,6 +285,7 @@