From 40af610e8f6e7065d56e8a2bc70159de3d3e88ae Mon Sep 17 00:00:00 2001 From: "K. Noel Belcourt" Date: Sat, 26 Jan 2008 18:35:59 +0000 Subject: [PATCH 001/224] Fixes #416 Fixed spelling of Jack Edmonds name and renamed files where necessary. Updated the documentation as well. Tested changes by building/running tests in libs/graph/test. [SVN r42984] --- ...x_flow.html => edmonds_karp_max_flow.html} | 20 +++++------ doc/kolmogorov_max_flow.html | 2 +- doc/push_relabel_max_flow.html | 2 +- example/edge-connectivity.cpp | 4 +-- ...dmunds-karp-eg.cpp => edmonds-karp-eg.cpp} | 8 ++--- example/regression.cfg | 2 +- include/boost/graph/edge_connectivity.hpp | 4 +-- ...max_flow.hpp => edmonds_karp_max_flow.hpp} | 36 +++++++++---------- test/max_flow_test.cpp | 6 ++-- 9 files changed, 42 insertions(+), 42 deletions(-) rename doc/{edmunds_karp_max_flow.html => edmonds_karp_max_flow.html} (93%) rename example/{edmunds-karp-eg.cpp => edmonds-karp-eg.cpp} (93%) rename include/boost/graph/{edmunds_karp_max_flow.hpp => edmonds_karp_max_flow.hpp} (92%) diff --git a/doc/edmunds_karp_max_flow.html b/doc/edmonds_karp_max_flow.html similarity index 93% rename from doc/edmunds_karp_max_flow.html rename to doc/edmonds_karp_max_flow.html index 0bf59675..d88adaca 100644 --- a/doc/edmunds_karp_max_flow.html +++ b/doc/edmonds_karp_max_flow.html @@ -7,7 +7,7 @@ -- http://www.boost.org/LICENSE_1_0.txt) --> -Boost Graph Library: Edmunds-Karp Maximum Flow +Boost Graph Library: Edmonds-Karp Maximum Flow -

-edmunds_karp_max_flow +

+edmonds_karp_max_flow

 // named paramter version
 template <class Graph, class P, class T, class R>
 typename detail::edge_capacity_value<Graph, P, T, R>::value_type
-edmunds_karp_max_flow(Graph& g, 
+edmonds_karp_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)
@@ -33,7 +33,7 @@ template <class Graph,
 	  class CapacityEdgeMap, class ResidualCapacityEdgeMap,
 	  class ReverseEdgeMap, class ColorMap, class PredEdgeMap>
 typename property_traits<CapacityEdgeMap>::value_type
-edmunds_karp_max_flow(Graph& g, 
+edmonds_karp_max_flow(Graph& g, 
    typename graph_traits<Graph>::vertex_descriptor src,
    typename graph_traits<Graph>::vertex_descriptor sink,
    CapacityEdgeMap cap, ResidualCapacityEdgeMap res, ReverseEdgeMap rev, 
@@ -41,7 +41,7 @@ edmunds_karp_max_flow(Graph& g,
 

-The edmunds_karp_max_flow() function calculates the maximum flow +The edmonds_karp_max_flow() function calculates the maximum flow of a network. See Section Network Flow Algorithms for a description of maximum flow. The calculated @@ -93,7 +93,7 @@ algorithm.

Where Defined

-boost/graph/edmunds_karp_max_flow.hpp +boost/graph/edmonds_karp_max_flow.hpp

@@ -209,7 +209,7 @@ some constant U.

Example

The program in example/edmunds-karp-eg.cpp +href="../example/edmonds-karp-eg.cpp">example/edmonds-karp-eg.cpp reads an example maximum flow problem (a graph with edge capacities) from a file in the DIMACS format and computes the maximum flow. @@ -229,9 +229,9 @@ from a file in the DIMACS format and computes the maximum flow. - - diff --git a/doc/kolmogorov_max_flow.html b/doc/kolmogorov_max_flow.html index b9b0aa2e..2e99d5a7 100644 --- a/doc/kolmogorov_max_flow.html +++ b/doc/kolmogorov_max_flow.html @@ -364,7 +364,7 @@ f 6 4 0 f 7 6 0 f 7 5 0

See Also

-

edmunds_karp_max_flow(),
push_relabel_max_flow(). +

edmonds_karp_max_flow(),
push_relabel_max_flow().


diff --git a/doc/push_relabel_max_flow.html b/doc/push_relabel_max_flow.html index a2137b3a..3142ad80 100644 --- a/doc/push_relabel_max_flow.html +++ b/doc/push_relabel_max_flow.html @@ -225,7 +225,7 @@ f 6 7 1

See Also

-edmunds_karp_max_flow()
+edmonds_karp_max_flow()
kolmogorov_max_flow().
diff --git a/example/edge-connectivity.cpp b/example/edge-connectivity.cpp index 87cc00a8..f51694e2 100644 --- a/example/edge-connectivity.cpp +++ b/example/edge-connectivity.cpp @@ -8,7 +8,7 @@ #include #include #include -#include +#include #include #include #include @@ -110,7 +110,7 @@ namespace boost while (!nonneighbor_S.empty()) { k = nonneighbor_S.front(); - alpha_S_k = edmunds_karp_max_flow + alpha_S_k = edmonds_karp_max_flow (flow_g, p, k, cap, res_cap, rev_edge, &color[0], &pred[0]); if (alpha_S_k < alpha_star) { alpha_star = alpha_S_k; diff --git a/example/edmunds-karp-eg.cpp b/example/edmonds-karp-eg.cpp similarity index 93% rename from example/edmunds-karp-eg.cpp rename to example/edmonds-karp-eg.cpp index f6cd1995..4b5c6fac 100644 --- a/example/edmunds-karp-eg.cpp +++ b/example/edmonds-karp-eg.cpp @@ -8,13 +8,13 @@ #include #include #include -#include +#include #include #include #include // Use a DIMACS network flow file as stdin. -// edmunds-karp-eg < max_flow.dat +// edmonds-karp-eg < max_flow.dat // // Sample output: // c The total flow: @@ -68,10 +68,10 @@ main() #if defined(BOOST_MSVC) && BOOST_MSVC <= 1300 std::vector color(num_vertices(g)); std::vector pred(num_vertices(g)); - long flow = edmunds_karp_max_flow + long flow = edmonds_karp_max_flow (g, s, t, capacity, residual_capacity, rev, &color[0], &pred[0]); #else - long flow = edmunds_karp_max_flow(g, s, t); + long flow = edmonds_karp_max_flow(g, s, t); #endif std::cout << "c The total flow:" << std::endl; diff --git a/example/regression.cfg b/example/regression.cfg index 762d2e6c..4fa1cef4 100644 --- a/example/regression.cfg +++ b/example/regression.cfg @@ -44,7 +44,7 @@ compile libs/graph/example/edge_basics.cpp compile libs/graph/example/edge_connectivity.cpp compile libs/graph/example/edge_iterator_constructor.cpp compile libs/graph/example/edge_property.cpp -compile libs/graph/example/edmunds-karp-eg.cpp +compile libs/graph/example/edmonds-karp-eg.cpp compile libs/graph/example/exterior_properties.cpp compile libs/graph/example/exterior_property_map.cpp compile libs/graph/example/family-tree-eg.cpp diff --git a/include/boost/graph/edge_connectivity.hpp b/include/boost/graph/edge_connectivity.hpp index d78e3ee4..d52bf9cc 100644 --- a/include/boost/graph/edge_connectivity.hpp +++ b/include/boost/graph/edge_connectivity.hpp @@ -16,7 +16,7 @@ #include #include #include -#include +#include namespace boost { @@ -139,7 +139,7 @@ namespace boost { while (!non_neighbor_S.empty()) { // at most n - 1 times k = non_neighbor_S.front(); - alpha_S_k = edmunds_karp_max_flow + alpha_S_k = edmonds_karp_max_flow (flow_g, p, k, cap, res_cap, rev_edge, &color[0], &pred[0]); if (alpha_S_k < alpha_star) { diff --git a/include/boost/graph/edmunds_karp_max_flow.hpp b/include/boost/graph/edmonds_karp_max_flow.hpp similarity index 92% rename from include/boost/graph/edmunds_karp_max_flow.hpp rename to include/boost/graph/edmonds_karp_max_flow.hpp index ddb49dc6..2564acd6 100644 --- a/include/boost/graph/edmunds_karp_max_flow.hpp +++ b/include/boost/graph/edmonds_karp_max_flow.hpp @@ -7,8 +7,8 @@ // http://www.boost.org/LICENSE_1_0.txt) //======================================================================= -#ifndef EDMUNDS_KARP_MAX_FLOW_HPP -#define EDMUNDS_KARP_MAX_FLOW_HPP +#ifndef EDMONDS_KARP_MAX_FLOW_HPP +#define EDMONDS_KARP_MAX_FLOW_HPP #include #include @@ -25,7 +25,7 @@ namespace boost { // The "labeling" algorithm from "Network Flows" by Ahuja, Magnanti, // Orlin. I think this is the same as or very similar to the original - // Edmunds-Karp algorithm. This solves the maximum flow problem. + // Edmonds-Karp algorithm. This solves the maximum flow problem. namespace detail { @@ -76,7 +76,7 @@ namespace boost { class CapacityEdgeMap, class ResidualCapacityEdgeMap, class ReverseEdgeMap, class ColorMap, class PredEdgeMap> typename property_traits::value_type - edmunds_karp_max_flow + edmonds_karp_max_flow (Graph& g, typename graph_traits::vertex_descriptor src, typename graph_traits::vertex_descriptor sink, @@ -111,7 +111,7 @@ namespace boost { for (tie(ei, e_end) = out_edges(src, g); ei != e_end; ++ei) flow += (cap[*ei] - res[*ei]); return flow; - } // edmunds_karp_max_flow() + } // edmonds_karp_max_flow() namespace detail { //------------------------------------------------------------------------- @@ -119,7 +119,7 @@ namespace boost { // use of class here is a VC++ workaround template - struct edmunds_karp_dispatch2 { + struct edmonds_karp_dispatch2 { template static typename edge_capacity_value::type apply @@ -130,7 +130,7 @@ namespace boost { const bgl_named_params& params, ColorMap color) { - return edmunds_karp_max_flow + return edmonds_karp_max_flow (g, src, sink, choose_const_pmap(get_param(params, edge_capacity), g, edge_capacity), choose_pmap(get_param(params, edge_residual_capacity), @@ -140,7 +140,7 @@ namespace boost { } }; template<> - struct edmunds_karp_dispatch2 { + struct edmonds_karp_dispatch2 { template static typename edge_capacity_value::type apply @@ -156,7 +156,7 @@ namespace boost { size_type n = is_default_param(get_param(params, vertex_color)) ? num_vertices(g) : 1; std::vector color_vec(n); - return edmunds_karp_max_flow + return edmonds_karp_max_flow (g, src, sink, choose_const_pmap(get_param(params, edge_capacity), g, edge_capacity), choose_pmap(get_param(params, edge_residual_capacity), @@ -174,7 +174,7 @@ namespace boost { // use of class here is a VC++ workaround template - struct edmunds_karp_dispatch1 { + struct edmonds_karp_dispatch1 { template static typename edge_capacity_value::type apply(Graph& g, @@ -184,12 +184,12 @@ namespace boost { PredMap pred) { typedef typename property_value< bgl_named_params, vertex_color_t>::type C; - return edmunds_karp_dispatch2::apply + return edmonds_karp_dispatch2::apply (g, src, sink, pred, params, get_param(params, vertex_color)); } }; template<> - struct edmunds_karp_dispatch1 { + struct edmonds_karp_dispatch1 { template static typename edge_capacity_value::type @@ -207,7 +207,7 @@ namespace boost { std::vector pred_vec(n); typedef typename property_value< bgl_named_params, vertex_color_t>::type C; - return edmunds_karp_dispatch2::apply + return edmonds_karp_dispatch2::apply (g, src, sink, make_iterator_property_map(pred_vec.begin(), choose_const_pmap (get_param(params, vertex_index), @@ -221,14 +221,14 @@ namespace boost { template typename detail::edge_capacity_value::type - edmunds_karp_max_flow + edmonds_karp_max_flow (Graph& g, typename graph_traits::vertex_descriptor src, typename graph_traits::vertex_descriptor sink, const bgl_named_params& params) { typedef typename property_value< bgl_named_params, vertex_predecessor_t>::type Pred; - return detail::edmunds_karp_dispatch1::apply + return detail::edmonds_karp_dispatch1::apply (g, src, sink, params, get_param(params, vertex_predecessor)); } @@ -236,15 +236,15 @@ namespace boost { typename property_traits< typename property_map::const_type >::value_type - edmunds_karp_max_flow + edmonds_karp_max_flow (Graph& g, typename graph_traits::vertex_descriptor src, typename graph_traits::vertex_descriptor sink) { bgl_named_params params(0); - return edmunds_karp_max_flow(g, src, sink, params); + return edmonds_karp_max_flow(g, src, sink, params); } } // namespace boost -#endif // EDMUNDS_KARP_MAX_FLOW_HPP +#endif // EDMONDS_KARP_MAX_FLOW_HPP diff --git a/test/max_flow_test.cpp b/test/max_flow_test.cpp index 1ecd904c..02d829de 100644 --- a/test/max_flow_test.cpp +++ b/test/max_flow_test.cpp @@ -39,7 +39,7 @@ //three max_flows we test here #include #include -#include +#include //boost utilities we use #include #include @@ -127,10 +127,10 @@ int test_main(int argc, char* argv[]) tEdgeVal kolmo = kolmogorov_max_flow(g,source_vertex,sink_vertex); tEdgeVal push_relabel = push_relabel_max_flow(g,source_vertex,sink_vertex); - tEdgeVal edmunds_karp = edmunds_karp_max_flow(g,source_vertex,sink_vertex); + tEdgeVal edmonds_karp = edmonds_karp_max_flow(g,source_vertex,sink_vertex); BOOST_REQUIRE( kolmo == push_relabel ); - BOOST_REQUIRE( push_relabel == edmunds_karp ); + BOOST_REQUIRE( push_relabel == edmonds_karp ); return 0; } From 231f4c3573e4e3ab891aa8cc2f1efecf7100572a Mon Sep 17 00:00:00 2001 From: Douglas Gregor Date: Tue, 5 Feb 2008 20:51:23 +0000 Subject: [PATCH 002/224] Fix add_vertex and add_vertices when the CSR graph has vertex properties [SVN r43117] --- include/boost/graph/compressed_sparse_row_graph.hpp | 2 ++ include/boost/graph/detail/indexed_properties.hpp | 3 +++ test/csr_graph_test.cpp | 11 ++++++++++- 3 files changed, 15 insertions(+), 1 deletion(-) diff --git a/include/boost/graph/compressed_sparse_row_graph.hpp b/include/boost/graph/compressed_sparse_row_graph.hpp index 8615eda3..d093b6a5 100644 --- a/include/boost/graph/compressed_sparse_row_graph.hpp +++ b/include/boost/graph/compressed_sparse_row_graph.hpp @@ -347,6 +347,7 @@ inline Vertex add_vertex(BOOST_CSR_GRAPH_TYPE& g) { Vertex old_num_verts_plus_one = g.m_rowstart.size(); g.m_rowstart.push_back(EdgeIndex(0)); + g.vertex_properties().resize(num_vertices(g)); return old_num_verts_plus_one - 1; } @@ -355,6 +356,7 @@ inline Vertex add_vertices(typename BOOST_CSR_GRAPH_TYPE::vertices_size_type count, BOOST_CSR_GRAPH_TYPE& g) { Vertex old_num_verts_plus_one = g.m_rowstart.size(); g.m_rowstart.resize(old_num_verts_plus_one + count, EdgeIndex(0)); + g.vertex_properties().resize(num_vertices(g)); return old_num_verts_plus_one - 1; } diff --git a/include/boost/graph/detail/indexed_properties.hpp b/include/boost/graph/detail/indexed_properties.hpp index e5fdb71c..17bbdad1 100644 --- a/include/boost/graph/detail/indexed_properties.hpp +++ b/include/boost/graph/detail/indexed_properties.hpp @@ -49,6 +49,7 @@ protected: // Initialize with n default-constructed property values indexed_vertex_properties(std::size_t n) : m_vertex_properties(n) { } +public: // Resize the properties vector void resize(std::size_t n) { @@ -92,6 +93,8 @@ class indexed_vertex_properties // All operations do nothing. indexed_vertex_properties() { } indexed_vertex_properties(std::size_t) { } + +public: void resize(std::size_t) { } void reserve(std::size_t) { } }; diff --git a/test/csr_graph_test.cpp b/test/csr_graph_test.cpp index e388b2ee..67bea538 100644 --- a/test/csr_graph_test.cpp +++ b/test/csr_graph_test.cpp @@ -38,7 +38,13 @@ typedef boost::adjacency_list<> GraphT; typedef boost::erdos_renyi_iterator ERGen; -typedef boost::compressed_sparse_row_graph<> CSRGraphT; +struct VertexData +{ + int index; +}; + +typedef boost::compressed_sparse_row_graph + CSRGraphT; template void assert_graphs_equal(const G1& g1, const VI1& vi1, @@ -191,6 +197,9 @@ void test(const OrigGraph& g) CSRGraphT g4; BOOST_CHECK(num_vertices(g4) == 0); std::size_t first_vert = add_vertices(num_vertices(g3), g4); + BGL_FORALL_VERTICES(v, g4, CSRGraphT) + g4[v].index = v; + BOOST_CHECK(first_vert == 0); BOOST_CHECK(num_vertices(g4) == num_vertices(g3)); CSRGraphT::edge_iterator ei, ei_end; From e45cfb0ee36ff8440c43e7dddfdffb8b37f822f4 Mon Sep 17 00:00:00 2001 From: Daniel James Date: Sun, 10 Feb 2008 14:56:22 +0000 Subject: [PATCH 003/224] Link to people pages on the website, as they've been removed from the download. [SVN r43209] --- doc/AdjacencyGraph.html | 2 +- doc/AdjacencyMatrix.html | 2 +- doc/BFSVisitor.html | 4 ++-- doc/BasicMatrix.html | 2 +- doc/BellmanFordVisitor.html | 4 ++-- doc/BidirectionalGraph.html | 2 +- doc/Buffer.html | 2 +- doc/ColorValue.html | 4 ++-- doc/DFSVisitor.html | 4 ++-- doc/DijkstraVisitor.html | 4 ++-- doc/EdgeListGraph.html | 2 +- doc/EdgeMutableGraph.html | 2 +- doc/EventVisitor.html | 4 ++-- doc/EventVisitorList.html | 4 ++-- doc/Graph.html | 2 +- doc/IncidenceGraph.html | 4 ++-- doc/IteratorConstructibleGraph.html | 4 ++-- doc/Monoid.html | 4 ++-- doc/MutableGraph.html | 2 +- doc/MutablePropertyGraph.html | 2 +- doc/PropertyGraph.html | 2 +- doc/PropertyTag.html | 2 +- doc/VertexAndEdgeListGraph.html | 2 +- doc/VertexListGraph.html | 2 +- doc/VertexMutableGraph.html | 4 ++-- doc/acknowledgements.html | 4 ++-- doc/adjacency_list.html | 4 ++-- doc/adjacency_list_traits.html | 4 ++-- doc/bandwidth.html | 2 +- doc/bc_clustering.html | 2 +- doc/bellman_ford_shortest.html | 2 +- doc/bellman_visitor.html | 4 ++-- doc/betweenness_centrality.html | 2 +- doc/bfs_visitor.html | 4 ++-- doc/bgl_named_params.html | 4 ++-- doc/bibliography.html | 2 +- doc/biconnected_components.html | 4 ++-- doc/breadth_first_search.html | 2 +- doc/breadth_first_visit.html | 2 +- doc/bundles.html | 2 +- doc/challenge.html | 2 +- doc/circle_layout.html | 4 ++-- doc/compressed_sparse_row.html | 2 +- doc/connected_components.html | 2 +- doc/constructing_algorithms.html | 4 ++-- doc/copy_graph.html | 2 +- doc/cuthill_mckee_ordering.html | 2 +- doc/dag_shortest_paths.html | 2 +- doc/depth_first_search.html | 4 ++-- doc/depth_first_visit.html | 2 +- doc/dfs_visitor.html | 4 ++-- doc/dijkstra_shortest_paths.html | 2 +- doc/dijkstra_visitor.html | 4 ++-- doc/distance_recorder.html | 4 ++-- doc/edge_list.html | 4 ++-- doc/edmonds_karp_max_flow.html | 2 +- doc/erdos_renyi_generator.html | 2 +- doc/file_dependency_example.html | 2 +- doc/filtered_graph.html | 4 ++-- doc/fruchterman_reingold.html | 2 +- doc/graph_coloring.html | 4 ++-- doc/graph_concepts.html | 2 +- doc/graph_theory_review.html | 2 +- doc/graph_traits.html | 4 ++-- doc/gursoy_atun_layout.html | 2 +- doc/history.html | 4 ++-- doc/incident.html | 4 ++-- doc/incremental_components.html | 4 ++-- doc/index.html | 4 ++-- doc/isomorphism.html | 2 +- doc/johnson_all_pairs_shortest.html | 2 +- doc/kamada_kawai_spring_layout.html | 4 ++-- doc/kevin_bacon.html | 2 +- doc/king_ordering.html | 2 +- doc/known_problems.html | 4 ++-- doc/kruskal_min_spanning_tree.html | 2 +- doc/layout_tolerance.html | 2 +- doc/leda_conversion.html | 4 ++-- doc/minimum_degree_ordering.html | 4 ++-- doc/null_visitor.html | 4 ++-- doc/opposite.html | 4 ++-- doc/plod_generator.html | 2 +- doc/predecessor_recorder.html | 4 ++-- doc/prim_minimum_spanning_tree.html | 2 +- doc/property_map.html | 4 ++-- doc/property_writer.html | 4 ++-- doc/publications.html | 4 ++-- doc/push_relabel_max_flow.html | 2 +- doc/python.html | 2 +- doc/quick_tour.html | 2 +- doc/random_layout.html | 2 +- doc/reverse_graph.html | 4 ++-- doc/sequential_vertex_coloring.html | 2 +- doc/small_world_generator.html | 2 +- doc/sorted_erdos_renyi_gen.html | 2 +- doc/sparse_matrix_ordering.html | 2 +- doc/stanford_graph.html | 4 ++-- doc/strong_components.html | 2 +- doc/table_of_contents.html | 4 ++-- doc/time_stamper.html | 4 ++-- doc/topological_sort.html | 2 +- doc/transitive_closure.html | 2 +- doc/transpose_graph.html | 2 +- doc/trouble_shooting.html | 4 ++-- doc/undirected_dfs.html | 4 ++-- doc/using_adjacency_list.html | 2 +- doc/using_property_maps.html | 2 +- doc/visitor_concepts.html | 4 ++-- doc/write-graphviz.html | 4 ++-- 109 files changed, 159 insertions(+), 159 deletions(-) diff --git a/doc/AdjacencyGraph.html b/doc/AdjacencyGraph.html index e644814b..317b34bb 100644 --- a/doc/AdjacencyGraph.html +++ b/doc/AdjacencyGraph.html @@ -161,7 +161,7 @@ experience with graph algorithm implementations.
Copyright © 2000-2001 -Jeremy Siek, Indiana University (jsiek@osl.iu.edu) +Jeremy Siek, Indiana University (jsiek@osl.iu.edu)
diff --git a/doc/AdjacencyMatrix.html b/doc/AdjacencyMatrix.html index 22c4f17c..cb458547 100644 --- a/doc/AdjacencyMatrix.html +++ b/doc/AdjacencyMatrix.html @@ -96,7 +96,7 @@ The edge() function must return in constant time.
Copyright © 2000-2001 -Jeremy Siek, Indiana University (jsiek@osl.iu.edu) +Jeremy Siek, Indiana University (jsiek@osl.iu.edu)
diff --git a/doc/BFSVisitor.html b/doc/BFSVisitor.html index 7f8de201..326d3654 100644 --- a/doc/BFSVisitor.html +++ b/doc/BFSVisitor.html @@ -207,10 +207,10 @@ class count_tree_edges_bfs_visitor(bgl.Graph.BFSVisitor):
Copyright © 2000-2001 -Jeremy Siek, +Jeremy Siek, Indiana University (jsiek@osl.iu.edu)
-Lie-Quan Lee, Indiana University (llee@cs.indiana.edu)
+Lie-Quan Lee, Indiana University (llee@cs.indiana.edu)
Andrew Lumsdaine, Indiana University (lums@osl.iu.edu) diff --git a/doc/BasicMatrix.html b/doc/BasicMatrix.html index 56d24991..986abaea 100644 --- a/doc/BasicMatrix.html +++ b/doc/BasicMatrix.html @@ -94,7 +94,7 @@ Element access is constant time.
Copyright © 2000-2001 -Jeremy Siek, +Jeremy Siek, Indiana University (jsiek@osl.iu.edu)
diff --git a/doc/BellmanFordVisitor.html b/doc/BellmanFordVisitor.html index 790624e0..40b2b425 100644 --- a/doc/BellmanFordVisitor.html +++ b/doc/BellmanFordVisitor.html @@ -171,10 +171,10 @@ class count_tree_edges_bellman_ford_visitor(bgl.Graph.BellmanFordVisitor):
Copyright © 2000-2001 -Jeremy Siek, +Jeremy Siek, Indiana University (jsiek@osl.iu.edu)
-Lie-Quan Lee, Indiana University (llee@cs.indiana.edu)
+Lie-Quan Lee, Indiana University (llee@cs.indiana.edu)
Andrew Lumsdaine, Indiana University (lums@osl.iu.edu) diff --git a/doc/BidirectionalGraph.html b/doc/BidirectionalGraph.html index 4aaf00b1..404b1c72 100644 --- a/doc/BidirectionalGraph.html +++ b/doc/BidirectionalGraph.html @@ -168,7 +168,7 @@ undirected graphs).
Copyright © 2000-2001 -Jeremy Siek, Indiana University (jsiek@osl.iu.edu) +Jeremy Siek, Indiana University (jsiek@osl.iu.edu)
diff --git a/doc/Buffer.html b/doc/Buffer.html index 2e3b0659..3a52b1b1 100644 --- a/doc/Buffer.html +++ b/doc/Buffer.html @@ -110,7 +110,7 @@ most linear time complexity in the size of the Generalized Queue.
Copyright © 2000-2001 -Jeremy Siek, Indiana University and C++ Library & Compiler Group/SGI (jsiek@engr.sgi.com) +Jeremy Siek, Indiana University and C++ Library & Compiler Group/SGI (jsiek@engr.sgi.com)
diff --git a/doc/ColorValue.html b/doc/ColorValue.html index 28b15e48..090d039e 100644 --- a/doc/ColorValue.html +++ b/doc/ColorValue.html @@ -95,10 +95,10 @@ href="http://www.sgi.com/tech/stl/DefaultConstructible.html">DefaultConstructibl
Copyright © 2000-2001 -Jeremy Siek, +Jeremy Siek, Indiana University (jsiek@osl.iu.edu)
-Lie-Quan Lee, Indiana University (llee@cs.indiana.edu)
+Lie-Quan Lee, Indiana University (llee@cs.indiana.edu)
Andrew Lumsdaine, Indiana University (lums@osl.iu.edu) diff --git a/doc/DFSVisitor.html b/doc/DFSVisitor.html index 246303ac..1242f520 100644 --- a/doc/DFSVisitor.html +++ b/doc/DFSVisitor.html @@ -199,10 +199,10 @@ class count_tree_edges_dfs_visitor(bgl.Graph.DFSVisitor):
Copyright © 2000-2001 -Jeremy Siek, +Jeremy Siek, Indiana University (jsiek@osl.iu.edu)
-Lie-Quan Lee, Indiana University (llee@cs.indiana.edu)
+Lie-Quan Lee, Indiana University (llee@cs.indiana.edu)
Andrew Lumsdaine, Indiana University (lums@osl.iu.edu) diff --git a/doc/DijkstraVisitor.html b/doc/DijkstraVisitor.html index b8854c99..4b889b89 100644 --- a/doc/DijkstraVisitor.html +++ b/doc/DijkstraVisitor.html @@ -209,10 +209,10 @@ class count_tree_edges_dijkstra_visitor(bgl.Graph.DijkstraVisitor):
Copyright © 2000-2001 -Jeremy Siek, +Jeremy Siek, Indiana University (jsiek@osl.iu.edu)
-Lie-Quan Lee, Indiana University (llee@cs.indiana.edu)
+Lie-Quan Lee, Indiana University (llee@cs.indiana.edu)
Andrew Lumsdaine, Indiana University (lums@osl.iu.edu) diff --git a/doc/EdgeListGraph.html b/doc/EdgeListGraph.html index a4b7a2dd..f5d086ce 100644 --- a/doc/EdgeListGraph.html +++ b/doc/EdgeListGraph.html @@ -177,7 +177,7 @@ must all return in constant time.
Copyright © 2000-2001 -Jeremy Siek, Indiana University (jsiek@osl.iu.edu) +Jeremy Siek, Indiana University (jsiek@osl.iu.edu)
diff --git a/doc/EdgeMutableGraph.html b/doc/EdgeMutableGraph.html index 0301eb29..07818d49 100644 --- a/doc/EdgeMutableGraph.html +++ b/doc/EdgeMutableGraph.html @@ -101,7 +101,7 @@ UNDER CONSTRUCTION
Copyright © 2000-2001 -Jeremy Siek, Indiana University (jsiek@osl.iu.edu) +Jeremy Siek, Indiana University (jsiek@osl.iu.edu)
diff --git a/doc/EventVisitor.html b/doc/EventVisitor.html index 358fc0a7..efb0c70c 100644 --- a/doc/EventVisitor.html +++ b/doc/EventVisitor.html @@ -148,10 +148,10 @@ either a vertex or edge descriptor of the graph.
Copyright © 2000-2001 -Jeremy Siek, +Jeremy Siek, Indiana University (jsiek@osl.iu.edu)
-Lie-Quan Lee, Indiana University (llee@cs.indiana.edu)
+Lie-Quan Lee, Indiana University (llee@cs.indiana.edu)
Andrew Lumsdaine, Indiana University (lums@osl.iu.edu) diff --git a/doc/EventVisitorList.html b/doc/EventVisitorList.html index b83eae1d..3cb03bd6 100644 --- a/doc/EventVisitorList.html +++ b/doc/EventVisitorList.html @@ -114,10 +114,10 @@ std::make_pair(visitor1,
Copyright © 2000-2001 -Jeremy Siek, +Jeremy Siek, Indiana University (jsiek@osl.iu.edu)
-Lie-Quan Lee, Indiana University (llee@cs.indiana.edu)
+Lie-Quan Lee, Indiana University (llee@cs.indiana.edu)
Andrew Lumsdaine, Indiana University (lums@osl.iu.edu) diff --git a/doc/Graph.html b/doc/Graph.html index 9a38fcd2..50812786 100644 --- a/doc/Graph.html +++ b/doc/Graph.html @@ -142,7 +142,7 @@ any vertex of graph object which type is G.
Copyright © 2000-2001 -Jeremy Siek, Indiana University (jsiek@osl.iu.edu) +Jeremy Siek, Indiana University (jsiek@osl.iu.edu)
diff --git a/doc/IncidenceGraph.html b/doc/IncidenceGraph.html index efd49eab..a1ab72c8 100644 --- a/doc/IncidenceGraph.html +++ b/doc/IncidenceGraph.html @@ -189,10 +189,10 @@ Therefore, the extra requirement is added that the out-edge connecting
Copyright © 2000-2001 -Jeremy Siek, +Jeremy Siek, Indiana University (jsiek@osl.iu.edu)
-Lie-Quan Lee, Indiana University (llee@cs.indiana.edu)
+Lie-Quan Lee, Indiana University (llee@cs.indiana.edu)
Andrew Lumsdaine, Indiana University (lums@osl.iu.edu) diff --git a/doc/IteratorConstructibleGraph.html b/doc/IteratorConstructibleGraph.html index 1f71359e..55982585 100644 --- a/doc/IteratorConstructibleGraph.html +++ b/doc/IteratorConstructibleGraph.html @@ -148,10 +148,10 @@ constructor lacking the graph size information.
Copyright © 2000-2001 -Jeremy Siek, +Jeremy Siek, Indiana University (jsiek@osl.iu.edu)
-Lie-Quan Lee, Indiana University (llee@cs.indiana.edu)
+Lie-Quan Lee, Indiana University (llee@cs.indiana.edu)
Andrew Lumsdaine, Indiana University (lums@osl.iu.edu) diff --git a/doc/Monoid.html b/doc/Monoid.html index 37287c35..ba2366fb 100644 --- a/doc/Monoid.html +++ b/doc/Monoid.html @@ -109,10 +109,10 @@ Return type: bool
Copyright © 2000-2001 -Jeremy Siek, +Jeremy Siek, Indiana University (jsiek@osl.iu.edu)
-Lie-Quan Lee, Indiana University (llee@cs.indiana.edu)
+Lie-Quan Lee, Indiana University (llee@cs.indiana.edu)
Andrew Lumsdaine, Indiana University (lums@osl.iu.edu) diff --git a/doc/MutableGraph.html b/doc/MutableGraph.html index ae608838..b50890ca 100644 --- a/doc/MutableGraph.html +++ b/doc/MutableGraph.html @@ -292,7 +292,7 @@ is no longer a valid vertex descriptor.
Copyright © 2000-2001 -Jeremy Siek, Indiana University (jsiek@osl.iu.edu) +Jeremy Siek, Indiana University (jsiek@osl.iu.edu)
diff --git a/doc/MutablePropertyGraph.html b/doc/MutablePropertyGraph.html index 31f3dbcd..15f17711 100644 --- a/doc/MutablePropertyGraph.html +++ b/doc/MutablePropertyGraph.html @@ -143,7 +143,7 @@ Return type: vertex_descriptor
Copyright © 2000-2001 -Jeremy Siek, Indiana University (jsiek@osl.iu.edu) +Jeremy Siek, Indiana University (jsiek@osl.iu.edu)
diff --git a/doc/PropertyGraph.html b/doc/PropertyGraph.html index f78ccade..2ed567b6 100644 --- a/doc/PropertyGraph.html +++ b/doc/PropertyGraph.html @@ -203,7 +203,7 @@ The get() property map function must be constant time.
Copyright © 2000-2001 -Jeremy Siek, Indiana University (jsiek@osl.iu.edu) +Jeremy Siek, Indiana University (jsiek@osl.iu.edu)
diff --git a/doc/PropertyTag.html b/doc/PropertyTag.html index 8bc8a901..6b0c0267 100644 --- a/doc/PropertyTag.html +++ b/doc/PropertyTag.html @@ -110,7 +110,7 @@ type is also required to specialize
Copyright © 2000-2001 -Jeremy Siek, Indiana University (jsiek@osl.iu.edu) +Jeremy Siek, Indiana University (jsiek@osl.iu.edu)
diff --git a/doc/VertexAndEdgeListGraph.html b/doc/VertexAndEdgeListGraph.html index 785f78e0..50c6a134 100644 --- a/doc/VertexAndEdgeListGraph.html +++ b/doc/VertexAndEdgeListGraph.html @@ -63,7 +63,7 @@ requirements are added.
Copyright © 2000-2001 -Jeremy Siek, Indiana University (jsiek@osl.iu.edu) +Jeremy Siek, Indiana University (jsiek@osl.iu.edu)
diff --git a/doc/VertexListGraph.html b/doc/VertexListGraph.html index 7de114b8..e49cdfca 100644 --- a/doc/VertexListGraph.html +++ b/doc/VertexListGraph.html @@ -147,7 +147,7 @@ groups these requirements together, hence the VertexListGraph concept.
Copyright © 2000-2001 -Jeremy Siek, Indiana University (jsiek@osl.iu.edu) +Jeremy Siek, Indiana University (jsiek@osl.iu.edu)
diff --git a/doc/VertexMutableGraph.html b/doc/VertexMutableGraph.html index b73306f4..cec0a001 100644 --- a/doc/VertexMutableGraph.html +++ b/doc/VertexMutableGraph.html @@ -74,8 +74,8 @@ No additional associated types.
Copyright © 2000-2001 -Jeremy Siek, Indiana University (jsiek@osl.iu.edu) -Lie-Quan Lee, Indiana University (llee@cs.indiana.edu) +Jeremy Siek, Indiana University (jsiek@osl.iu.edu) +Lie-Quan Lee, Indiana University (llee@cs.indiana.edu)
diff --git a/doc/acknowledgements.html b/doc/acknowledgements.html index 09c30cfb..7c827689 100644 --- a/doc/acknowledgements.html +++ b/doc/acknowledgements.html @@ -63,10 +63,10 @@ Science of the U.S. Department of Energy.
Copyright © 2000-2001 -Jeremy Siek, +Jeremy Siek, Indiana University (jsiek@osl.iu.edu)
-Lie-Quan Lee, Indiana University (llee@cs.indiana.edu)
+Lie-Quan Lee, Indiana University (llee@cs.indiana.edu)
Andrew Lumsdaine, Indiana University (lums@osl.iu.edu) diff --git a/doc/adjacency_list.html b/doc/adjacency_list.html index f4e04811..ef626e33 100644 --- a/doc/adjacency_list.html +++ b/doc/adjacency_list.html @@ -1100,10 +1100,10 @@ Include boost/graph/ad
Copyright © 2000-2001 -Jeremy Siek, +Jeremy Siek, Indiana University (jsiek@osl.iu.edu)
-Lie-Quan Lee, Indiana University (llee@cs.indiana.edu)
+Lie-Quan Lee, Indiana University (llee@cs.indiana.edu)
Andrew Lumsdaine, Indiana University (lums@osl.iu.edu) diff --git a/doc/adjacency_list_traits.html b/doc/adjacency_list_traits.html index 793bcbae..6b38c3e0 100644 --- a/doc/adjacency_list_traits.html +++ b/doc/adjacency_list_traits.html @@ -145,10 +145,10 @@ parallel edges (disallow_parallel_edge_tag).
Copyright © 2000-2001 -Jeremy Siek, +Jeremy Siek, Indiana University (jsiek@osl.iu.edu)
-Lie-Quan Lee, Indiana University (llee@cs.indiana.edu)
+Lie-Quan Lee, Indiana University (llee@cs.indiana.edu)
Andrew Lumsdaine, Indiana University (lums@osl.iu.edu) diff --git a/doc/bandwidth.html b/doc/bandwidth.html index a9424645..53877877 100644 --- a/doc/bandwidth.html +++ b/doc/bandwidth.html @@ -86,7 +86,7 @@ of the i-th bandwidths Bi(G).
Copyright © 2000-2001 -Jeremy Siek, Indiana University (jsiek@osl.iu.edu) +Jeremy Siek, Indiana University (jsiek@osl.iu.edu)
diff --git a/doc/bc_clustering.html b/doc/bc_clustering.html index d7be582f..9fa60e50 100644 --- a/doc/bc_clustering.html +++ b/doc/bc_clustering.html @@ -140,7 +140,7 @@ IN: VertexIndexMap vertex_index -
Copyright © 2004Douglas Gregor, +Douglas Gregor, Indiana University (dgregor@cs.indiana.edu)
Andrew Lumsdaine, Indiana University (examples/bellman-example.cpp.
Copyright © 2000 -Jeremy Siek, Indiana University (jsiek@osl.iu.edu) +Jeremy Siek, Indiana University (jsiek@osl.iu.edu)
diff --git a/doc/bellman_visitor.html b/doc/bellman_visitor.html index 0a5124f2..1259cd78 100644 --- a/doc/bellman_visitor.html +++ b/doc/bellman_visitor.html @@ -98,10 +98,10 @@ and property_writer.
Copyright © 2000-2001 -Jeremy Siek, +Jeremy Siek, Indiana University (jsiek@osl.iu.edu)
-Lie-Quan Lee, Indiana University (llee@cs.indiana.edu)
+Lie-Quan Lee, Indiana University (llee@cs.indiana.edu)
Andrew Lumsdaine, Indiana University (lums@osl.iu.edu) diff --git a/doc/betweenness_centrality.html b/doc/betweenness_centrality.html index e8eab286..47731524 100644 --- a/doc/betweenness_centrality.html +++ b/doc/betweenness_centrality.html @@ -296,7 +296,7 @@ is O(VE).
Copyright © 2004 -Douglas Gregor, Indiana University (dgregor@cs.indiana.edu)
+Douglas Gregor, Indiana University (dgregor@cs.indiana.edu)
Andrew Lumsdaine, Indiana University (lums@osl.iu.edu) diff --git a/doc/bfs_visitor.html b/doc/bfs_visitor.html index 608669b3..9bf31938 100644 --- a/doc/bfs_visitor.html +++ b/doc/bfs_visitor.html @@ -115,10 +115,10 @@ and property_writer.
Copyright © 2000-2001 -Jeremy Siek, +Jeremy Siek, Indiana University (jsiek@osl.iu.edu)
-Lie-Quan Lee, Indiana University (llee@cs.indiana.edu)
+Lie-Quan Lee, Indiana University (llee@cs.indiana.edu)
Andrew Lumsdaine, Indiana University (lums@osl.iu.edu) diff --git a/doc/bgl_named_params.html b/doc/bgl_named_params.html index 30eaebd0..2e9635b5 100644 --- a/doc/bgl_named_params.html +++ b/doc/bgl_named_params.html @@ -83,10 +83,10 @@ like boost::weight_map that create an instance of
Copyright © 2000-2001 -Jeremy Siek, +Jeremy Siek, Indiana University (jsiek@osl.iu.edu)
-Lie-Quan Lee, Indiana University (llee@cs.indiana.edu)
+Lie-Quan Lee, Indiana University (llee@cs.indiana.edu)
Andrew Lumsdaine, Indiana University (lums@osl.iu.edu) diff --git a/doc/bibliography.html b/doc/bibliography.html index da96b674..19799338 100644 --- a/doc/bibliography.html +++ b/doc/bibliography.html @@ -439,7 +439,7 @@ Combinatorica 10: 41-51, 1990.
Copyright © 2000-2001 -Jeremy Siek, Indiana University (jsiek@osl.iu.edu) +Jeremy Siek, Indiana University (jsiek@osl.iu.edu)
diff --git a/doc/biconnected_components.html b/doc/biconnected_components.html index 96457a62..3b1afa95 100644 --- a/doc/biconnected_components.html +++ b/doc/biconnected_components.html @@ -244,10 +244,10 @@ articulation points of an undirected graph.
Copyright © 2000-2004 -Jeremy Siek, Indiana +Jeremy Siek, Indiana University (jsiek@osl.iu.edu)
-Doug Gregor, Indiana University +Doug Gregor, Indiana University
diff --git a/doc/breadth_first_search.html b/doc/breadth_first_search.html index a7c8edab..169fc103 100644 --- a/doc/breadth_first_search.html +++ b/doc/breadth_first_search.html @@ -331,7 +331,7 @@ to listS.
Copyright © 2000-2001 -Jeremy Siek, Indiana University (jsiek@osl.iu.edu) +Jeremy Siek, Indiana University (jsiek@osl.iu.edu)
diff --git a/doc/breadth_first_visit.html b/doc/breadth_first_visit.html index bd51793d..0747b426 100644 --- a/doc/breadth_first_visit.html +++ b/doc/breadth_first_visit.html @@ -182,7 +182,7 @@ The time complexity is O(E).
Copyright © 2000-2001 -Jeremy Siek, Indiana University (jsiek@osl.iu.edu) +Jeremy Siek, Indiana University (jsiek@osl.iu.edu)
diff --git a/doc/bundles.html b/doc/bundles.html index 08e46c89..bafbbdd5 100644 --- a/doc/bundles.html +++ b/doc/bundles.html @@ -168,7 +168,7 @@ dijkstra_shortest_paths(map, from, specialization.


-Copyright © 2004 Doug Gregor. +Copyright © 2004 Doug Gregor.
diff --git a/doc/challenge.html b/doc/challenge.html index 7a562285..2fa7740a 100644 --- a/doc/challenge.html +++ b/doc/challenge.html @@ -113,7 +113,7 @@ It is currently difficult to use from a C++ program.
Copyright © 2000-2001 -Jeremy Siek, Indiana University (jsiek@osl.iu.edu) +Jeremy Siek, Indiana University (jsiek@osl.iu.edu)
diff --git a/doc/circle_layout.html b/doc/circle_layout.html index 9e06dce1..0b1cb9bd 100644 --- a/doc/circle_layout.html +++ b/doc/circle_layout.html @@ -5,7 +5,7 @@ -- (See accompanying file LICENSE_1_0.txt or copy at -- http://www.boost.org/LICENSE_1_0.txt) --> -Function template circle_graph_layout
boost.png (6897 bytes)HomeLibrariesPeopleFAQMore

(Python)Function template circle_graph_layout

boost::circle_graph_layout — Layout the graph with the vertices at the points of a regular n-polygon.

Synopsis

+Function template circle_graph_layout
boost.png (6897 bytes)HomeLibrariesPeopleFAQMore

(Python)Function template circle_graph_layout

boost::circle_graph_layout — Layout the graph with the vertices at the points of a regular n-polygon.

Synopsis

 template<typename VertexListGraph, typename PositionMap, typename Radius> 
   void circle_graph_layout(const VertexListGraph & g, PositionMap position, 
                            Radius radius);

Where Defined

boost/graph/circle_layout.hpp

Description

The distance from the center of the polygon to each point is determined by the radius parameter. The position parameter must be an Lvalue Property Map whose value type is a class type containing x and y members that will be set to the x and y coordinates. @@ -44,7 +44,7 @@ IN: Radius radius
Copyright © 2004 -Douglas Gregor, Indiana University (dgregor -at- cs.indiana.edu)
+Douglas Gregor, Indiana University (dgregor -at- cs.indiana.edu)
Andrew Lumsdaine, Indiana University (lums -at- osl.iu.edu)
diff --git a/doc/compressed_sparse_row.html b/doc/compressed_sparse_row.html index 9323a4db..9eedf0b3 100644 --- a/doc/compressed_sparse_row.html +++ b/doc/compressed_sparse_row.html @@ -711,7 +711,7 @@ BGL_FORALL_EDGES(e, g, WebGraph)
Copyright © 2005 -Doug Gregor, Indiana University ()
+Doug Gregor, Indiana University ()
Jeremiah Willcock, Indiana University ()
Andrew Lumsdaine, Indiana University () diff --git a/doc/connected_components.html b/doc/connected_components.html index c1811365..dcfbe8e2 100644 --- a/doc/connected_components.html +++ b/doc/connected_components.html @@ -150,7 +150,7 @@ undirected graph.
Copyright © 2000-2001 -Jeremy Siek, Indiana University (jsiek@osl.iu.edu) +Jeremy Siek, Indiana University (jsiek@osl.iu.edu)
diff --git a/doc/constructing_algorithms.html b/doc/constructing_algorithms.html index c04c8bda..14c33674 100644 --- a/doc/constructing_algorithms.html +++ b/doc/constructing_algorithms.html @@ -170,10 +170,10 @@ namespace boost {
Copyright © 2000-2001 -Jeremy Siek, +Jeremy Siek, Indiana University (jsiek@osl.iu.edu)
-Lie-Quan Lee, Indiana University (llee@cs.indiana.edu)
+Lie-Quan Lee, Indiana University (llee@cs.indiana.edu)
Andrew Lumsdaine, Indiana University (lums@osl.iu.edu) diff --git a/doc/copy_graph.html b/doc/copy_graph.html index 368fc7e0..ab31940f 100644 --- a/doc/copy_graph.html +++ b/doc/copy_graph.html @@ -109,7 +109,7 @@ The time complexity is O(V + E).
Copyright © 2000-2001 -Jeremy Siek, Indiana University (jsiek@osl.iu.edu) +Jeremy Siek, Indiana University (jsiek@osl.iu.edu)
diff --git a/doc/cuthill_mckee_ordering.html b/doc/cuthill_mckee_ordering.html index 1af288db..aa176270 100644 --- a/doc/cuthill_mckee_ordering.html +++ b/doc/cuthill_mckee_ordering.html @@ -240,7 +240,7 @@ and degree_property_map in boost/graph/properties.hpp.
Copyright © 2000-2001 -Jeremy Siek, Indiana University (jsiek@osl.iu.edu) +Jeremy Siek, Indiana University (jsiek@osl.iu.edu)
diff --git a/doc/dag_shortest_paths.html b/doc/dag_shortest_paths.html index ad6c675e..4768dc0c 100644 --- a/doc/dag_shortest_paths.html +++ b/doc/dag_shortest_paths.html @@ -318,7 +318,7 @@ algorithm.
Copyright © 2000-2001 -Jeremy Siek, Indiana University (jsiek@osl.iu.edu) +Jeremy Siek, Indiana University (jsiek@osl.iu.edu)
diff --git a/doc/depth_first_search.html b/doc/depth_first_search.html index 6bc6f110..ae52e253 100644 --- a/doc/depth_first_search.html +++ b/doc/depth_first_search.html @@ -301,10 +301,10 @@ The example in
Copyright © 2000-2001 -Jeremy Siek, +Jeremy Siek, Indiana University (jsiek@osl.iu.edu)
-Lie-Quan Lee, Indiana University (llee@cs.indiana.edu)
+Lie-Quan Lee, Indiana University (llee@cs.indiana.edu)
Andrew Lumsdaine, Indiana University (lums@osl.iu.edu) diff --git a/doc/depth_first_visit.html b/doc/depth_first_visit.html index 329d2cf2..7f1b704e 100644 --- a/doc/depth_first_visit.html +++ b/doc/depth_first_visit.html @@ -137,7 +137,7 @@ Time complexity is O(E).
Copyright © 2000-2001 -Jeremy Siek, Indiana University (jsiek@osl.iu.edu) +Jeremy Siek, Indiana University (jsiek@osl.iu.edu)
diff --git a/doc/dfs_visitor.html b/doc/dfs_visitor.html index 6b79d823..035ff59d 100644 --- a/doc/dfs_visitor.html +++ b/doc/dfs_visitor.html @@ -98,10 +98,10 @@ and property_writer.
Copyright © 2000-2001 -Jeremy Siek, +Jeremy Siek, Indiana University (jsiek@osl.iu.edu)
-Lie-Quan Lee, Indiana University (llee@cs.indiana.edu)
+Lie-Quan Lee, Indiana University (llee@cs.indiana.edu)
Andrew Lumsdaine, Indiana University (lums@osl.iu.edu) diff --git a/doc/dijkstra_shortest_paths.html b/doc/dijkstra_shortest_paths.html index a7bdd166..7a439ae1 100644 --- a/doc/dijkstra_shortest_paths.html +++ b/doc/dijkstra_shortest_paths.html @@ -436,7 +436,7 @@ distance less than infinity.
Copyright © 2000-2001 -Jeremy Siek, Indiana University (jsiek@osl.iu.edu) +Jeremy Siek, Indiana University (jsiek@osl.iu.edu)
diff --git a/doc/dijkstra_visitor.html b/doc/dijkstra_visitor.html index 995030f8..c238053e 100644 --- a/doc/dijkstra_visitor.html +++ b/doc/dijkstra_visitor.html @@ -112,10 +112,10 @@ and property_writer.
Copyright © 2000-2001 -Jeremy Siek, +Jeremy Siek, Indiana University (jsiek@osl.iu.edu)
-Lie-Quan Lee, Indiana University (llee@cs.indiana.edu)
+Lie-Quan Lee, Indiana University (llee@cs.indiana.edu)
Andrew Lumsdaine, Indiana University (lums@osl.iu.edu) diff --git a/doc/distance_recorder.html b/doc/distance_recorder.html index eb1d137a..f4fe2baf 100644 --- a/doc/distance_recorder.html +++ b/doc/distance_recorder.html @@ -163,10 +163,10 @@ and property_writer.
Copyright © 2000-2001 -Jeremy Siek, +Jeremy Siek, Indiana University (jsiek@osl.iu.edu)
-Lie-Quan Lee, Indiana University (llee@cs.indiana.edu)
+Lie-Quan Lee, Indiana University (llee@cs.indiana.edu)
Andrew Lumsdaine, Indiana University (lums@osl.iu.edu) diff --git a/doc/edge_list.html b/doc/edge_list.html index 4a556cef..d00e12ba 100644 --- a/doc/edge_list.html +++ b/doc/edge_list.html @@ -208,10 +208,10 @@ Returns the target vertex of edge e.
Copyright © 2000-2001 -Jeremy Siek, +Jeremy Siek, Indiana University (jsiek@osl.iu.edu)
-Lie-Quan Lee, Indiana University (llee@cs.indiana.edu)
+Lie-Quan Lee, Indiana University (llee@cs.indiana.edu)
Andrew Lumsdaine, Indiana University (lums@osl.iu.edu) diff --git a/doc/edmonds_karp_max_flow.html b/doc/edmonds_karp_max_flow.html index d88adaca..f0178a8e 100644 --- a/doc/edmonds_karp_max_flow.html +++ b/doc/edmonds_karp_max_flow.html @@ -224,7 +224,7 @@ from a file in the DIMACS format and computes the maximum flow.
Copyright © 2000-2001 -Jeremy Siek, Indiana University (jsiek@osl.iu.edu) +Jeremy Siek, Indiana University (jsiek@osl.iu.edu)
diff --git a/doc/erdos_renyi_generator.html b/doc/erdos_renyi_generator.html index 1e17b7cd..4531437f 100644 --- a/doc/erdos_renyi_generator.html +++ b/doc/erdos_renyi_generator.html @@ -143,7 +143,7 @@ int main()
Copyright © 2005 -Doug Gregor, Indiana University ()
+Doug Gregor, Indiana University ()
Andrew Lumsdaine, Indiana University ()
diff --git a/doc/file_dependency_example.html b/doc/file_dependency_example.html index 7aa0e68a..1b7ff931 100644 --- a/doc/file_dependency_example.html +++ b/doc/file_dependency_example.html @@ -356,7 +356,7 @@ dependency would be flagged as a user error.
Copyright © 2000-2001 -Jeremy Siek, Indiana University (jsiek@osl.iu.edu) +Jeremy Siek, Indiana University (jsiek@osl.iu.edu)
diff --git a/doc/filtered_graph.html b/doc/filtered_graph.html index 74bfcb7a..106ea617 100644 --- a/doc/filtered_graph.html +++ b/doc/filtered_graph.html @@ -522,10 +522,10 @@ num_edges(g))) which is assumed in many of the algorithms.
Copyright © 2000-2001 -Jeremy Siek, +Jeremy Siek, Indiana University (jsiek@osl.iu.edu)
-Lie-Quan Lee, Indiana University (llee@cs.indiana.edu)
+Lie-Quan Lee, Indiana University (llee@cs.indiana.edu)
Andrew Lumsdaine, Indiana University (lums@osl.iu.edu) diff --git a/doc/fruchterman_reingold.html b/doc/fruchterman_reingold.html index 2aa0a19a..89b58e62 100644 --- a/doc/fruchterman_reingold.html +++ b/doc/fruchterman_reingold.html @@ -234,7 +234,7 @@ determined by the cooling schedule.
Copyright © 2004 -Doug Gregor, Indiana University +Doug Gregor, Indiana University
diff --git a/doc/graph_coloring.html b/doc/graph_coloring.html index e99470af..22ac4471 100644 --- a/doc/graph_coloring.html +++ b/doc/graph_coloring.html @@ -178,10 +178,10 @@ namespace boost {
Copyright © 2000-2001 -Jeremy Siek, +Jeremy Siek, Indiana University (jsiek@osl.iu.edu)
-Lie-Quan Lee, Indiana University (llee@cs.indiana.edu)
+Lie-Quan Lee, Indiana University (llee@cs.indiana.edu)
Andrew Lumsdaine, Indiana University (lums@osl.iu.edu) diff --git a/doc/graph_concepts.html b/doc/graph_concepts.html index cb82769b..1291c10b 100644 --- a/doc/graph_concepts.html +++ b/doc/graph_concepts.html @@ -486,7 +486,7 @@ weight[(v,u)] = 3.1
Copyright © 2000-2001 -Jeremy Siek, Indiana University (jsiek@osl.iu.edu) +Jeremy Siek, Indiana University (jsiek@osl.iu.edu)
diff --git a/doc/graph_theory_review.html b/doc/graph_theory_review.html index a541936d..4d5f64ea 100644 --- a/doc/graph_theory_review.html +++ b/doc/graph_theory_review.html @@ -583,7 +583,7 @@ which is based on the notion of a preflow introduced by
Copyright © 2000-2001 -Jeremy Siek, Indiana University (jsiek@osl.iu.edu) +Jeremy Siek, Indiana University (jsiek@osl.iu.edu)
diff --git a/doc/graph_traits.html b/doc/graph_traits.html index 8831c34b..a5dc4ee6 100644 --- a/doc/graph_traits.html +++ b/doc/graph_traits.html @@ -239,10 +239,10 @@ of vertices in the graph.
Copyright © 2000-2001 -Jeremy Siek, +Jeremy Siek, Indiana University (jsiek@osl.iu.edu)
-Lie-Quan Lee, Indiana University (llee@cs.indiana.edu)
+Lie-Quan Lee, Indiana University (llee@cs.indiana.edu)
Andrew Lumsdaine, Indiana University (lums@osl.iu.edu) diff --git a/doc/gursoy_atun_layout.html b/doc/gursoy_atun_layout.html index 16bf2be8..1d8fc0c2 100644 --- a/doc/gursoy_atun_layout.html +++ b/doc/gursoy_atun_layout.html @@ -453,7 +453,7 @@ class heart_topology
Copyright © 2004 Jeremiah Willcock, Indiana University ()
-Doug Gregor, Indiana University ()
+Doug Gregor, Indiana University ()
Andrew Lumsdaine, Indiana University ()
diff --git a/doc/history.html b/doc/history.html index 6c9d4a7d..a7a8f5ea 100644 --- a/doc/history.html +++ b/doc/history.html @@ -189,10 +189,10 @@ September 27, 2000.
Copyright © 2000-2001 -Jeremy Siek, +Jeremy Siek, Indiana University (jsiek@osl.iu.edu)
-Lie-Quan Lee, Indiana University (llee@cs.indiana.edu)
+Lie-Quan Lee, Indiana University (llee@cs.indiana.edu)
Andrew Lumsdaine, Indiana University (lums@osl.iu.edu) diff --git a/doc/incident.html b/doc/incident.html index aefdfb88..68cf6c72 100644 --- a/doc/incident.html +++ b/doc/incident.html @@ -66,10 +66,10 @@ is the target. This function is equivalent to the expression
Copyright © 2000-2001 -Jeremy Siek, +Jeremy Siek, Indiana University (jsiek@osl.iu.edu)
-Lie-Quan Lee, Indiana University (llee@cs.indiana.edu)
+Lie-Quan Lee, Indiana University (llee@cs.indiana.edu)
Andrew Lumsdaine, Indiana University (lums@osl.iu.edu) diff --git a/doc/incremental_components.html b/doc/incremental_components.html index 9ddb695b..7aed1a69 100644 --- a/doc/incremental_components.html +++ b/doc/incremental_components.html @@ -408,10 +408,10 @@ Returns the number of components in the graph.
Copyright © 2000-2001 -Jeremy Siek, +Jeremy Siek, Indiana University (jsiek@osl.iu.edu)
-Lie-Quan Lee, Indiana University (llee@cs.indiana.edu)
+Lie-Quan Lee, Indiana University (llee@cs.indiana.edu)
Andrew Lumsdaine, Indiana University (lums@osl.iu.edu) diff --git a/doc/index.html b/doc/index.html index 96028ecc..eae700d9 100644 --- a/doc/index.html +++ b/doc/index.html @@ -289,10 +289,10 @@ iterator and implements an Edge List Graph. +"http://www.boost.org/people/people.htm">People @@ -295,7 +295,7 @@ the WeightMap.
Copyright © 2000-2001 -Jeremy Siek, +Jeremy Siek, Indiana University (jsiek@osl.iu.edu)
-Lie-Quan Lee, Indiana University (llee@cs.indiana.edu)
+Lie-Quan Lee, Indiana University (llee@cs.indiana.edu)
Andrew Lumsdaine, Indiana University (lums@osl.iu.edu) diff --git a/doc/isomorphism.html b/doc/isomorphism.html index 09d54f7d..a64391ab 100644 --- a/doc/isomorphism.html +++ b/doc/isomorphism.html @@ -193,7 +193,7 @@ See libs/graph/example/isomorphism.cpp<
Copyright © 2000-2001 -Jeremy Siek, Indiana University (jsiek@osl.iu.edu) +Jeremy Siek, Indiana University (jsiek@osl.iu.edu)
diff --git a/doc/johnson_all_pairs_shortest.html b/doc/johnson_all_pairs_shortest.html index dbaa259b..4afc6dda 100644 --- a/doc/johnson_all_pairs_shortest.html +++ b/doc/johnson_all_pairs_shortest.html @@ -205,7 +205,7 @@ HREF="bibliography.html#clr90">8
].
Copyright © 2000-2001 -Jeremy Siek, Indiana University (jsiek@osl.iu.edu) +Jeremy Siek, Indiana University (jsiek@osl.iu.edu)
diff --git a/doc/kamada_kawai_spring_layout.html b/doc/kamada_kawai_spring_layout.html index ce2b26ad..5d46353e 100644 --- a/doc/kamada_kawai_spring_layout.html +++ b/doc/kamada_kawai_spring_layout.html @@ -23,7 +23,7 @@ alink="#0000FF">
Home Libraries People FAQ More
-
Copyright © 2004Douglas Gregor, +Douglas Gregor, Indiana University (dgregor -at cs.indiana.edu)
Andrew Lumsdaine, Indiana University (
Copyright © 2000-2001 -Jeremy Siek, Indiana University (jsiek@osl.iu.edu) +Jeremy Siek, Indiana University (jsiek@osl.iu.edu)
diff --git a/doc/king_ordering.html b/doc/king_ordering.html index 9e425d5a..e4cfb0fb 100644 --- a/doc/king_ordering.html +++ b/doc/king_ordering.html @@ -228,7 +228,7 @@ and degree_property_map in boost/graph/properties.hpp.
Copyright © 2000-2001 -Jeremy Siek, Indiana University (jsiek@osl.iu.edu) +Jeremy Siek, Indiana University (jsiek@osl.iu.edu)
diff --git a/doc/known_problems.html b/doc/known_problems.html index e4add304..ae5e2fff 100644 --- a/doc/known_problems.html +++ b/doc/known_problems.html @@ -47,10 +47,10 @@
Copyright © 2000-2001 -Jeremy Siek, +Jeremy Siek, Indiana University (jsiek@osl.iu.edu)
-Lie-Quan Lee, Indiana University (llee@cs.indiana.edu)
+Lie-Quan Lee, Indiana University (llee@cs.indiana.edu)
Andrew Lumsdaine, Indiana University (lums@osl.iu.edu) diff --git a/doc/kruskal_min_spanning_tree.html b/doc/kruskal_min_spanning_tree.html index 623dbf74..e6e210df 100644 --- a/doc/kruskal_min_spanning_tree.html +++ b/doc/kruskal_min_spanning_tree.html @@ -192,7 +192,7 @@ contains an example of using Kruskal's algorithm.
Copyright © 2000-2001 -Jeremy Siek, Indiana University (jsiek@osl.iu.edu) +Jeremy Siek, Indiana University (jsiek@osl.iu.edu)
diff --git a/doc/layout_tolerance.html b/doc/layout_tolerance.html index e242ce7b..b0d9f92d 100644 --- a/doc/layout_tolerance.html +++ b/doc/layout_tolerance.html @@ -5,7 +5,7 @@ -- (See accompanying file LICENSE_1_0.txt or copy at -- http://www.boost.org/LICENSE_1_0.txt) --> -Struct template layout_tolerance
boost.png (6897 bytes)HomeLibrariesPeopleFAQMore

Struct template layout_tolerance

boost::layout_tolerance — Determines when to terminate layout of a particular graph based on a given relative tolerance.

Synopsis

template<typename T = double> 
+Struct template layout_tolerance
boost.png (6897 bytes)HomeLibrariesPeopleFAQMore

Struct template layout_tolerance

boost::layout_tolerance — Determines when to terminate layout of a particular graph based on a given relative tolerance.

Synopsis

template<typename T = double> 
 struct layout_tolerance {
   // construct/copy/destruct
   layout_tolerance(const T & = T(0.001));
diff --git a/doc/leda_conversion.html b/doc/leda_conversion.html
index 035ecd8a..8844760d 100644
--- a/doc/leda_conversion.html
+++ b/doc/leda_conversion.html
@@ -250,10 +250,10 @@ href="../test/graph.cpp">test/graph.cpp.
 
Copyright © 2000-2001 -Jeremy Siek, +Jeremy Siek, Indiana University (jsiek@osl.iu.edu)
-Lie-Quan Lee, Indiana University (llee@cs.indiana.edu)
+Lie-Quan Lee, Indiana University (llee@cs.indiana.edu)
Andrew Lumsdaine, Indiana University (lums@osl.iu.edu) diff --git a/doc/minimum_degree_ordering.html b/doc/minimum_degree_ordering.html index 322a35e2..e85e70cd 100644 --- a/doc/minimum_degree_ordering.html +++ b/doc/minimum_degree_ordering.html @@ -170,8 +170,8 @@ elimination on row i of matrix A is equivalent to
Copyright © 2001 -Lie-Quan Lee, Indiana University (llee@cs.indiana.edu)
-Jeremy Siek, Indiana University (jsiek@osl.iu.edu) +Lie-Quan Lee, Indiana University (llee@cs.indiana.edu)
+Jeremy Siek, Indiana University (jsiek@osl.iu.edu)
diff --git a/doc/null_visitor.html b/doc/null_visitor.html index d5cb7520..e6842032 100644 --- a/doc/null_visitor.html +++ b/doc/null_visitor.html @@ -81,10 +81,10 @@ This does nothing.
Copyright © 2000-2001 -Jeremy Siek, +Jeremy Siek, Indiana University (jsiek@osl.iu.edu)
-Lie-Quan Lee, Indiana University (llee@cs.indiana.edu)
+Lie-Quan Lee, Indiana University (llee@cs.indiana.edu)
Andrew Lumsdaine, Indiana University (lums@osl.iu.edu) diff --git a/doc/opposite.html b/doc/opposite.html index 8af5ce56..252c47f3 100644 --- a/doc/opposite.html +++ b/doc/opposite.html @@ -66,10 +66,10 @@ assert(u == opposite(e, v, g));
Copyright © 2000-2001 -Jeremy Siek, +Jeremy Siek, Indiana University (jsiek@osl.iu.edu)
-Lie-Quan Lee, Indiana University (llee@cs.indiana.edu)
+Lie-Quan Lee, Indiana University (llee@cs.indiana.edu)
Andrew Lumsdaine, Indiana University (lums@osl.iu.edu) diff --git a/doc/plod_generator.html b/doc/plod_generator.html index 5ee7ea8a..8e78ef3e 100644 --- a/doc/plod_generator.html +++ b/doc/plod_generator.html @@ -130,7 +130,7 @@ int main()
Copyright © 2005 -Doug Gregor, Indiana University ()
+Doug Gregor, Indiana University ()
Andrew Lumsdaine, Indiana University ()
diff --git a/doc/predecessor_recorder.html b/doc/predecessor_recorder.html index 78ad4626..6f933b4f 100644 --- a/doc/predecessor_recorder.html +++ b/doc/predecessor_recorder.html @@ -173,10 +173,10 @@ and property_writer.
Copyright © 2000-2001 -Jeremy Siek, +Jeremy Siek, Indiana University (jsiek@osl.iu.edu)
-Lie-Quan Lee, Indiana University (llee@cs.indiana.edu)
+Lie-Quan Lee, Indiana University (llee@cs.indiana.edu)
Andrew Lumsdaine, Indiana University (lums@osl.iu.edu) diff --git a/doc/prim_minimum_spanning_tree.html b/doc/prim_minimum_spanning_tree.html index 3b6fa8bc..1f85695d 100644 --- a/doc/prim_minimum_spanning_tree.html +++ b/doc/prim_minimum_spanning_tree.html @@ -281,7 +281,7 @@ contains an example of using Prim's algorithm.
Copyright © 2000-2001 -Jeremy Siek, Indiana University (jsiek@osl.iu.edu) +Jeremy Siek, Indiana University (jsiek@osl.iu.edu)
diff --git a/doc/property_map.html b/doc/property_map.html index cf418402..b39c4ed3 100644 --- a/doc/property_map.html +++ b/doc/property_map.html @@ -73,10 +73,10 @@ href="../../property_map/property_map.html">property map.
Copyright © 2000-2001 -Jeremy Siek, +Jeremy Siek, Indiana University (jsiek@osl.iu.edu)
-Lie-Quan Lee, Indiana University (llee@cs.indiana.edu)
+Lie-Quan Lee, Indiana University (llee@cs.indiana.edu)
Andrew Lumsdaine, Indiana University (lums@osl.iu.edu) diff --git a/doc/property_writer.html b/doc/property_writer.html index 9372fded..c4d4155a 100644 --- a/doc/property_writer.html +++ b/doc/property_writer.html @@ -184,10 +184,10 @@ and time_stamper.
Copyright © 2000-2001 -Jeremy Siek, +Jeremy Siek, Indiana University (jsiek@osl.iu.edu)
-Lie-Quan Lee, Indiana University (llee@cs.indiana.edu)
+Lie-Quan Lee, Indiana University (llee@cs.indiana.edu)
Andrew Lumsdaine, Indiana University (lums@osl.iu.edu) diff --git a/doc/publications.html b/doc/publications.html index 535a32b9..fc919bcb 100644 --- a/doc/publications.html +++ b/doc/publications.html @@ -33,10 +33,10 @@
Copyright © 2000-2001 -Jeremy Siek, +Jeremy Siek, Indiana University (jsiek@osl.iu.edu)
-Lie-Quan Lee, Indiana University (llee@cs.indiana.edu)
+Lie-Quan Lee, Indiana University (llee@cs.indiana.edu)
Andrew Lumsdaine, Indiana University (lums@osl.iu.edu) diff --git a/doc/push_relabel_max_flow.html b/doc/push_relabel_max_flow.html index 3142ad80..52d3061b 100644 --- a/doc/push_relabel_max_flow.html +++ b/doc/push_relabel_max_flow.html @@ -233,7 +233,7 @@ f 6 7 1
Copyright © 2000-2001 -Jeremy Siek, Indiana University (jsiek@osl.iu.edu) +Jeremy Siek, Indiana University (jsiek@osl.iu.edu)
diff --git a/doc/python.html b/doc/python.html index 6e85e0b5..52ef6fcb 100644 --- a/doc/python.html +++ b/doc/python.html @@ -43,7 +43,7 @@
Copyright © 2005 - Doug Gregor, Indiana University ()
+ Doug Gregor, Indiana University ()
Andrew Lumsdaine, Indiana University ()
diff --git a/doc/quick_tour.html b/doc/quick_tour.html index 981b7b9e..0a959c00 100644 --- a/doc/quick_tour.html +++ b/doc/quick_tour.html @@ -594,7 +594,7 @@ is no long necessary, though this still makes for a good example. -
Copyright © 2000Jeremy Siek, + Jeremy Siek, Indiana University (jsiek@osl.iu.edu)
diff --git a/doc/random_layout.html b/doc/random_layout.html index a54e8929..c08f2959 100644 --- a/doc/random_layout.html +++ b/doc/random_layout.html @@ -94,7 +94,7 @@ concept.
Copyright © 2004 -Doug Gregor, Indiana University +Doug Gregor, Indiana University
diff --git a/doc/reverse_graph.html b/doc/reverse_graph.html index caa6de62..24a867b5 100644 --- a/doc/reverse_graph.html +++ b/doc/reverse_graph.html @@ -408,9 +408,9 @@ href="../../../boost/pending/property.hpp">boost/pending/property.hpp
Copyright © 2000-2001 -Dave Abrahams +Dave Abrahams (david.abrahams@rcn.com)
-Jeremy Siek, +Jeremy Siek, Indiana University (jsiek@osl.iu.edu)
diff --git a/doc/sequential_vertex_coloring.html b/doc/sequential_vertex_coloring.html index 0cd7ace4..504c8f39 100644 --- a/doc/sequential_vertex_coloring.html +++ b/doc/sequential_vertex_coloring.html @@ -110,7 +110,7 @@ in the graph, and k is the number of colors used. Andrew Lumsdaine, Indiana University (lums@osl.iu.edu)
-Douglas Gregor, Indiana University (dgregor -at- cs.indiana.edu)) +Douglas Gregor, Indiana University (dgregor -at- cs.indiana.edu))
diff --git a/doc/small_world_generator.html b/doc/small_world_generator.html index 6151f6b6..2f44c06a 100644 --- a/doc/small_world_generator.html +++ b/doc/small_world_generator.html @@ -117,7 +117,7 @@ int main()
Copyright © 2005 -Doug Gregor, Indiana University ()
+Doug Gregor, Indiana University ()
Andrew Lumsdaine, Indiana University ()
diff --git a/doc/sorted_erdos_renyi_gen.html b/doc/sorted_erdos_renyi_gen.html index 54e13a72..e03cbcf6 100644 --- a/doc/sorted_erdos_renyi_gen.html +++ b/doc/sorted_erdos_renyi_gen.html @@ -124,7 +124,7 @@ int main()
Copyright © 2005 Jeremiah Willcock, Indiana University ()
-Doug Gregor, Indiana University ()
+Doug Gregor, Indiana University ()
Andrew Lumsdaine, Indiana University ()
diff --git a/doc/sparse_matrix_ordering.html b/doc/sparse_matrix_ordering.html index a2bec08c..aed7d2d6 100644 --- a/doc/sparse_matrix_ordering.html +++ b/doc/sparse_matrix_ordering.html @@ -370,7 +370,7 @@ which is to extend partial PSAW in case by case and function
Copyright © 2000-2001 -Jeremy Siek, Indiana University (jsiek@osl.iu.edu) +Jeremy Siek, Indiana University (jsiek@osl.iu.edu)
diff --git a/doc/stanford_graph.html b/doc/stanford_graph.html index d1d10922..f4aa4bee 100644 --- a/doc/stanford_graph.html +++ b/doc/stanford_graph.html @@ -443,10 +443,10 @@ class.

Andreas Scherer, Aachen (andreas_freenet@freenet.de)
-Jeremy Siek, +Jeremy Siek, Indiana University (jsiek@osl.iu.edu)
-Lie-Quan Lee, +Lie-Quan Lee, Indiana University (llee@cs.indiana.edu)
Andrew Lumsdaine, diff --git a/doc/strong_components.html b/doc/strong_components.html index 491b62d8..8b6ebdcd 100644 --- a/doc/strong_components.html +++ b/doc/strong_components.html @@ -194,7 +194,7 @@ href="../example/strong_components.cpp">examples/strong_components.cpp<
Copyright © 2000-2001 -Jeremy Siek, Indiana University (jsiek@osl.iu.edu) +Jeremy Siek, Indiana University (jsiek@osl.iu.edu)
diff --git a/doc/table_of_contents.html b/doc/table_of_contents.html index b537d799..a23e1f47 100644 --- a/doc/table_of_contents.html +++ b/doc/table_of_contents.html @@ -282,10 +282,10 @@
Copyright © 2000-2001 -Jeremy Siek, +Jeremy Siek, Indiana University (jsiek@osl.iu.edu)
-Lie-Quan Lee, Indiana University (llee@cs.indiana.edu)
+Lie-Quan Lee, Indiana University (llee@cs.indiana.edu)
Andrew Lumsdaine, Indiana University (lums@osl.iu.edu) diff --git a/doc/time_stamper.html b/doc/time_stamper.html index daf7c1a7..08efa10d 100644 --- a/doc/time_stamper.html +++ b/doc/time_stamper.html @@ -183,10 +183,10 @@ and property_writer.
Copyright © 2000-2001 -Jeremy Siek, +Jeremy Siek, Indiana University (jsiek@osl.iu.edu)
-Lie-Quan Lee, Indiana University (llee@cs.indiana.edu)
+Lie-Quan Lee, Indiana University (llee@cs.indiana.edu)
Andrew Lumsdaine, Indiana University (lums@osl.iu.edu) diff --git a/doc/topological_sort.html b/doc/topological_sort.html index e9751767..eae0400f 100644 --- a/doc/topological_sort.html +++ b/doc/topological_sort.html @@ -148,7 +148,7 @@ The output is:
Copyright © 2000-2001 -Jeremy Siek, Indiana University (jsiek@osl.iu.edu) +Jeremy Siek, Indiana University (jsiek@osl.iu.edu)
diff --git a/doc/transitive_closure.html b/doc/transitive_closure.html index c3f9ce14..ba596f25 100644 --- a/doc/transitive_closure.html +++ b/doc/transitive_closure.html @@ -216,7 +216,7 @@ component of u to any of the vertices in the component of
Copyright © 2001 -Jeremy Siek, Indiana Univ.(jsiek@cs.indiana.edu) +Jeremy Siek, Indiana Univ.(jsiek@cs.indiana.edu)
diff --git a/doc/transpose_graph.html b/doc/transpose_graph.html index 726a6946..bae82f47 100644 --- a/doc/transpose_graph.html +++ b/doc/transpose_graph.html @@ -120,7 +120,7 @@ The time complexity is O(V + E).
Copyright © 2000-2001 -Jeremy Siek, Indiana University (jsiek@osl.iu.edu) +Jeremy Siek, Indiana University (jsiek@osl.iu.edu)
diff --git a/doc/trouble_shooting.html b/doc/trouble_shooting.html index aec8ad06..c14e8b67 100644 --- a/doc/trouble_shooting.html +++ b/doc/trouble_shooting.html @@ -115,10 +115,10 @@ for (std::size_t j = 0; j < n_edges; ++j)
Copyright © 2000-2001 -Jeremy Siek, +Jeremy Siek, Indiana University (jsiek@osl.iu.edu)
-Lie-Quan Lee, Indiana University (llee@cs.indiana.edu)
+Lie-Quan Lee, Indiana University (llee@cs.indiana.edu)
Andrew Lumsdaine, Indiana University (lums@osl.iu.edu) diff --git a/doc/undirected_dfs.html b/doc/undirected_dfs.html index 5ce3a136..53bd726b 100644 --- a/doc/undirected_dfs.html +++ b/doc/undirected_dfs.html @@ -323,10 +323,10 @@ An example is in
Copyright © 2000-2001 -Jeremy Siek, +Jeremy Siek, Indiana University (jsiek@osl.iu.edu)
-Lie-Quan Lee, Indiana University (llee@cs.indiana.edu)
+Lie-Quan Lee, Indiana University (llee@cs.indiana.edu)
Andrew Lumsdaine, Indiana University (lums@osl.iu.edu) diff --git a/doc/using_adjacency_list.html b/doc/using_adjacency_list.html index bcd498d6..ba8867e0 100644 --- a/doc/using_adjacency_list.html +++ b/doc/using_adjacency_list.html @@ -781,7 +781,7 @@ href="http://www.sgi.com/tech/stl/AssociativeContainer.html">AssociativeContaine
Copyright © 2000-2001 -Jeremy Siek, Indiana University (jsiek@osl.iu.edu) +Jeremy Siek, Indiana University (jsiek@osl.iu.edu)
diff --git a/doc/using_property_maps.html b/doc/using_property_maps.html index 8429cde4..412b5fe5 100644 --- a/doc/using_property_maps.html +++ b/doc/using_property_maps.html @@ -473,7 +473,7 @@ previous section.
Copyright © 2000-2001 -Jeremy Siek, Indiana University (jsiek@osl.iu.edu) +Jeremy Siek, Indiana University (jsiek@osl.iu.edu)
diff --git a/doc/visitor_concepts.html b/doc/visitor_concepts.html index 7189c0c5..da86e1dc 100644 --- a/doc/visitor_concepts.html +++ b/doc/visitor_concepts.html @@ -48,10 +48,10 @@ the following visitor concepts: - +
Copyright © 2000-2001 -Jeremy Siek, +Jeremy Siek, Indiana University (jsiek@osl.iu.edu)
-Lie-Quan Lee, Indiana University (llee@cs.indiana.edu)
+Lie-Quan Lee, Indiana University (llee@cs.indiana.edu)
Andrew Lumsdaine, Indiana University (lums@osl.iu.edu) diff --git a/doc/write-graphviz.html b/doc/write-graphviz.html index 778963ab..188c5edf 100644 --- a/doc/write-graphviz.html +++ b/doc/write-graphviz.html @@ -338,8 +338,8 @@ without the library libbglviz.a.
Copyright © 2000-2001 -Lie-Quan Lee, Indiana University (llee@cs.indiana.edu)
-Jeremy Siek, Indiana University (jsiek@osl.iu.edu) +Lie-Quan Lee, Indiana University (llee@cs.indiana.edu)
+Jeremy Siek, Indiana University (jsiek@osl.iu.edu)
From 07eee8a2a1ec16803a9c3fc848a781da29f4b3b9 Mon Sep 17 00:00:00 2001 From: Daniel James Date: Sun, 10 Feb 2008 15:02:17 +0000 Subject: [PATCH 004/224] Point links to the pages that used to be in 'more' to the site. [SVN r43210] --- doc/circle_layout.html | 2 +- doc/kamada_kawai_spring_layout.html | 2 +- doc/layout_tolerance.html | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/circle_layout.html b/doc/circle_layout.html index 0b1cb9bd..109d84c1 100644 --- a/doc/circle_layout.html +++ b/doc/circle_layout.html @@ -5,7 +5,7 @@ -- (See accompanying file LICENSE_1_0.txt or copy at -- http://www.boost.org/LICENSE_1_0.txt) --> -Function template circle_graph_layout
boost.png (6897 bytes)HomeLibrariesPeopleFAQMore

(Python)Function template circle_graph_layout

boost::circle_graph_layout — Layout the graph with the vertices at the points of a regular n-polygon.

Synopsis

+Function template circle_graph_layout
boost.png (6897 bytes)HomeLibrariesPeopleFAQMore

(Python)Function template circle_graph_layout

boost::circle_graph_layout — Layout the graph with the vertices at the points of a regular n-polygon.

Synopsis

 template<typename VertexListGraph, typename PositionMap, typename Radius> 
   void circle_graph_layout(const VertexListGraph & g, PositionMap position, 
                            Radius radius);

Where Defined

boost/graph/circle_layout.hpp

Description

The distance from the center of the polygon to each point is determined by the radius parameter. The position parameter must be an Lvalue Property Map whose value type is a class type containing x and y members that will be set to the x and y coordinates. diff --git a/doc/kamada_kawai_spring_layout.html b/doc/kamada_kawai_spring_layout.html index 5d46353e..fccccfcd 100644 --- a/doc/kamada_kawai_spring_layout.html +++ b/doc/kamada_kawai_spring_layout.html @@ -24,7 +24,7 @@ alink="#0000FF">

Libraries PeopleFAQFAQ More
diff --git a/doc/layout_tolerance.html b/doc/layout_tolerance.html index b0d9f92d..6cb97fec 100644 --- a/doc/layout_tolerance.html +++ b/doc/layout_tolerance.html @@ -5,7 +5,7 @@ -- (See accompanying file LICENSE_1_0.txt or copy at -- http://www.boost.org/LICENSE_1_0.txt) --> -Struct template layout_tolerance
boost.png (6897 bytes)HomeLibrariesPeopleFAQMore

Struct template layout_tolerance

boost::layout_tolerance — Determines when to terminate layout of a particular graph based on a given relative tolerance.

Synopsis

template<typename T = double> 
+Struct template layout_tolerance
boost.png (6897 bytes)HomeLibrariesPeopleFAQMore

Struct template layout_tolerance

boost::layout_tolerance — Determines when to terminate layout of a particular graph based on a given relative tolerance.

Synopsis

template<typename T = double> 
 struct layout_tolerance {
   // construct/copy/destruct
   layout_tolerance(const T & = T(0.001));

From ecedcaa5a3acc01445aa9cf7635a62dbab91c232 Mon Sep 17 00:00:00 2001
From: Douglas Gregor 
Date: Mon, 17 Mar 2008 17:34:46 +0000
Subject: [PATCH 005/224] Fix some documentation issues. Fixes #1655, fixes
 #1660

[SVN r43680]
---
 doc/breadth_first_visit.html | 3 ---
 doc/depth_first_search.html  | 2 +-
 doc/read_graphml.html        | 2 +-
 doc/read_graphviz.html       | 2 +-
 doc/sloan_ordering.htm       | 2 +-
 doc/table_of_contents.html   | 2 +-
 doc/write_dimacs.html        | 2 +-
 7 files changed, 6 insertions(+), 9 deletions(-)

diff --git a/doc/breadth_first_visit.html b/doc/breadth_first_visit.html
index 0747b426..c5aa5c1c 100644
--- a/doc/breadth_first_visit.html
+++ b/doc/breadth_first_visit.html
@@ -125,9 +125,6 @@ The time complexity is O(E).
 

Visitor Event Points

    -
  • vis.initialize_vertex(v, g) is invoked on every vertex - before the start of the search. -
  • vis.examine_vertex(u, g)r is invoked in each vertex as it is removed from the queue. diff --git a/doc/depth_first_search.html b/doc/depth_first_search.html index ae52e253..838420b6 100644 --- a/doc/depth_first_search.html +++ b/doc/depth_first_search.html @@ -66,7 +66,7 @@ The depth_first_search() function invokes user-defined actions at certain event-points within the algorithm. This provides a mechanism for adapting the generic DFS algorithm to the many situations in which it can be used. In the pseudo-code below, the -event points for DFS are indicated in by the triangles and labels on +event points for DFS 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 DFS Visitor. In the pseudo-code diff --git a/doc/read_graphml.html b/doc/read_graphml.html index 87d096d2..c28c584d 100644 --- a/doc/read_graphml.html +++ b/doc/read_graphml.html @@ -113,7 +113,7 @@ graph attribute in the graphml format.

    Building the graphml reader

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

    +Boost Jam Build Instructions for the subdirectory libs/graph/build.

Notes

diff --git a/doc/read_graphviz.html b/doc/read_graphviz.html index 02758b43..5efc6386 100644 --- a/doc/read_graphviz.html +++ b/doc/read_graphviz.html @@ -177,7 +177,7 @@ bool status = read_graphviz(gvgraph,graph,dp,"node_id");

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.

+Boost Jam Build Instructions for the subdirectory libs/graph/build.

Deprecated Readers

diff --git a/doc/sloan_ordering.htm b/doc/sloan_ordering.htm index ec99d926..0c13c491 100755 --- a/doc/sloan_ordering.htm +++ b/doc/sloan_ordering.htm @@ -203,7 +203,7 @@ For version 1: See example/sloan_ordering.cpp.

See Also

-

sloan_start_end_vertices, +

sloan_start_end_vertices, bandwidth, profile, wavefront and degree_property_map in boost/graph/properties.hpp.

diff --git a/doc/table_of_contents.html b/doc/table_of_contents.html index a23e1f47..50db4e33 100644 --- a/doc/table_of_contents.html +++ b/doc/table_of_contents.html @@ -241,7 +241,7 @@
  • Graph Input/Output
    1. AT&T Graphviz: read_graphviz, write_graphviz
    2. -
    3. DIMACS Max-flow: read_dimacs_max_flow, write_dimacs
    4. +
    5. DIMACS Max-flow: read_dimacs_max_flow, write_dimacs_max_flow
    6. GraphML: read_graphml and write_graphml
  • diff --git a/doc/write_dimacs.html b/doc/write_dimacs.html index 07d36a44..636177f0 100644 --- a/doc/write_dimacs.html +++ b/doc/write_dimacs.html @@ -42,7 +42,7 @@

    -write_dimacs +write_dimacs_max_flow

    From 476e8dd7d10aa9fcd83ab6f9561e81ef13d49793 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jurko=20Gospodneti=C4=87?= Date: Thu, 17 Apr 2008 00:27:30 +0000 Subject: [PATCH 006/224] Corrected the documentation related to installing new internal property types. [SVN r44481] --- doc/using_adjacency_list.html | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/doc/using_adjacency_list.html b/doc/using_adjacency_list.html index ba8867e0..06872a28 100644 --- a/doc/using_adjacency_list.html +++ b/doc/using_adjacency_list.html @@ -470,27 +470,26 @@ struct capacity_t {

    -You can also use enum's instead of struct's to create tag types. -Create an enum type for each property. The first part of the name of -the enum type must be edge, vertex, or -graph followed by an underscore, the new property name, and -a _t at the -end. Inside the enum, define a value with the same name minus the -_t. Then invoke the BOOST_INSTALL_PROPERTY macro. +You can also use enum's instead of struct's to create tag types. Create an enum +type for each property inside the boost namespace. The first part of the name of +the enum type must be edge, vertex, or graph followed +by an underscore, the new property name, and a _t at the end. Inside +the enum, define a value with the same name minus the _t. Then invoke +the BOOST_INSTALL_PROPERTY macro.

    -enum edge_flow_t { edge_flow };
    -enum edge_capacity_t { edge_capacity };
    -
     namespace boost {
    +  enum edge_flow_t { edge_flow };
    +  enum edge_capacity_t { edge_capacity };
    +
       BOOST_INSTALL_PROPERTY(edge, flow);
       BOOST_INSTALL_PROPERTY(edge, capacity);
     }
     

    -Now you can use your new property tag in the definition of properties -just as you would one of the builtin tags. +Now you can use your new property tag in the definition of properties just as +you would one of the builtin tags.

    
    From bb1977b17abcbe39c5a79fefbeed608781de679b Mon Sep 17 00:00:00 2001
    From: Douglas Gregor 
    Date: Tue, 22 Apr 2008 12:24:25 +0000
    Subject: [PATCH 007/224] Resource-constrained shortest paths, from Michael
     Drexl
    
    [SVN r44717]
    ---
     doc/history.html                           |   6 +
     doc/r_c_shortest_paths.html                | 576 ++++++++++++++++
     doc/table_of_contents.html                 |   1 +
     example/r_c_shortest_paths_example.cpp     | 354 ++++++++++
     include/boost/graph/r_c_shortest_paths.hpp | 729 +++++++++++++++++++++
     test/Jamfile.v2                            |   2 +
     test/r_c_shortest_paths_test.cpp           | 641 ++++++++++++++++++
     7 files changed, 2309 insertions(+)
     create mode 100755 doc/r_c_shortest_paths.html
     create mode 100755 example/r_c_shortest_paths_example.cpp
     create mode 100644 include/boost/graph/r_c_shortest_paths.hpp
     create mode 100755 test/r_c_shortest_paths_test.cpp
    
    diff --git a/doc/history.html b/doc/history.html
    index a7a8f5ea..3f3b3794 100644
    --- a/doc/history.html
    +++ b/doc/history.html
    @@ -76,6 +76,12 @@ September 27, 2000.
     

    Changes by version

      +
    • Version 1.35.0
      New algorithms and components + +
    • +
    • Version 1.35.0
      New algorithms and components
      • kolmogorov_max_flow, from Stephan Diederich as part of the 2006 Google Summer of Code.
      • diff --git a/doc/r_c_shortest_paths.html b/doc/r_c_shortest_paths.html new file mode 100755 index 00000000..776b3eb1 --- /dev/null +++ b/doc/r_c_shortest_paths.html @@ -0,0 +1,576 @@ + + + +Boost Graph Library: Resource-Constrained Shortest Paths + +C++ Boost + +
        + +

        +r_c_shortest_paths +

        + +

        +

        +
        +template<class Graph,
        +         class VertexIndexMap,
        +         class EdgeIndexMap,
        +         class Resource_Container,
        +         class Resource_Extension_Function,
        +         class Dominance_Function,
        +         class Label_Allocator,
        +         class Visitor>
        +void r_c_shortest_paths( const Graph& g,
        +                         const VertexIndexMap& vertex_index_map,
        +                         const EdgeIndexMap& edge_index_map,
        +                         typename graph_traits<Graph>::vertex_descriptor s,
        +                         typename graph_traits<Graph>::vertex_descriptor t,
        +                         std::vector<std::vector<typename graph_traits<Graph>::edge_descriptor> >& pareto_optimal_solutions,
        +                         std::vector<Resource_Container>& pareto_optimal_resource_containers,
        +                         const Resource_Container& rc,
        +                         const Resource_Extension_Function& ref,
        +                         const Dominance_Function& dominance,
        +                         Label_Allocator la,
        +                         Visitor vis )
        +
        +template<class Graph,
        +         class VertexIndexMap,
        +         class EdgeIndexMap,
        +         class Resource_Container,
        +         class Resource_Extension_Function,
        +         class Dominance_Function,
        +         class Label_Allocator,
        +         class Visitor>
        +void r_c_shortest_paths( const Graph& g,
        +                         const VertexIndexMap& vertex_index_map,
        +                         const EdgeIndexMap& edge_index_map,
        +                         typename graph_traits<Graph>::vertex_descriptor s,
        +                         typename graph_traits<Graph>::vertex_descriptor t,
        +                         std::vector<typename graph_traits<Graph>::edge_descriptor>& pareto_optimal_solution,
        +                         Resource_Container>& pareto_optimal_resource_container,
        +                         const Resource_Container& rc,
        +                         const Resource_Extension_Function& ref,
        +                         const Dominance_Function& dominance,
        +                         Label_Allocator la,
        +                         Visitor vis )
        +
        +template<class Graph,
        +         class VertexIndexMap,
        +         class EdgeIndexMap,
        +         class Resource_Container,
        +         class Resource_Extension_Function,
        +         class Dominance_Function>
        +void r_c_shortest_paths( const Graph& g,
        +                         const VertexIndexMap& vertex_index_map,
        +                         const EdgeIndexMap& edge_index_map,
        +                         typename graph_traits<Graph>::vertex_descriptor s,
        +                         typename graph_traits<Graph>::vertex_descriptor t,
        +                         std::vector<std::vector<typename graph_traits<Graph>::edge_descriptor> >& pareto_optimal_solutions,
        +                         std::vector<Resource_Container>& pareto_optimal_resource_containers,
        +                         const Resource_Container& rc,
        +                         const Resource_Extension_Function& ref,
        +                         const Dominance_Function& dominance )
        +
        +template<class Graph,
        +         class VertexIndexMap,
        +         class EdgeIndexMap,
        +         class Resource_Container,
        +         class Resource_Extension_Function,
        +         class Dominance_Function>
        +void r_c_shortest_paths( const Graph& g,
        +                         const VertexIndexMap& vertex_index_map,
        +                         const EdgeIndexMap& edge_index_map,
        +                         typename graph_traits<Graph>::vertex_descriptor s,
        +                         typename graph_traits<Graph>::vertex_descriptor t,
        +                         std::vector<typename graph_traits<Graph>::edge_descriptor>& pareto_optimal_solution,
        +                         Resource_Container>& pareto_optimal_resource_container,
        +                         const Resource_Container& rc,
        +                         const Resource_Extension_Function& ref,
        +                         const Dominance_Function& dominance )
        +
        +
        + +

        Introduction and Problem Description

        + +The shortest path problem with resource constraints (SPPRC) seeks a shortest (cheapest, fastest) path in a directed graph with arbitrary arc lengths (travel times, costs) from an origin node to a destination node subject to one or more resource constraints. For example, one might seek a path of minimum length from s to t subject to the constraints that +
          +
        • +the total travel time must not exceed some upper bound and/or +
        • +the total amount of some good that has to be picked up at the vertices along the path be less than or equal to some capacity limit and/or +
        • +if two vertices i and j are visited on a path, then i must be visited before j +
        • +etc. +
        + +

        +The problem is NP-hard in the strong sense. If the path need not be elementary, i.e., if it is allowed that vertices are visited more than once, the problem can be solved in pseudopolynomial time. A central aspect is that two (partial) paths in an SPPRC can be incomparable, contrary to the SPP without resource constraints. This makes the SPPRC similar to a multi-criteria decision problem.
        +A recent survey on the problem is:
        +Irnich, S.; Desaulniers, G. (2005):
        +Shortest Path Problems with Resource Constraints
        +in:
        +Desaulniers, G.; Desrosiers, J.; Solomon, M. (eds.) (2005):
        +Column Generation
        +Springer, New York, pp. 33–65
        +(available online +here) +

        + +

        +The present document cannot give a complete introduction to SPPRCs. To get a thorough understanding of the problem, the reader is referred to the above paper. However, to understand the algorithm and its implementation, it is necessary to explain some fundamental ideas and point out the differences to a labelling algorithm for the shortest path problem without resource constraints (SPP). +

        + +

        +The standard solution technique for SPPRCs is a labelling algorithm based on dynamic programming. This approach uses the concepts of resources and resource extension functions. A resource is an arbitrarily scaled one-dimensional piece of information that can be determined or measured at the vertices of a directed walk in a graph. Examples are cost, time, load, or the information ‘Is a vertex i visited on the current path?’. A resource is constrained if there is at least one vertex in the graph where the resource must not take all possible values. The resource window of a resource at a vertex is the set of allowed values for the resource at this vertex. +

        + +

        +A resource extension function is defined on each arc in a graph for each resource considered. A resource extension function for a resource maps the set of all possible vectors (in a mathematical sense, not to be confused with a std::vector) of resource values at the source of an arc to the set of possible values of the resource at the target of the arc. This means that the value of a resource at a vertex may depend on the values of one or more other resources at the preceding vertex. +

        + +

        +Labels are used to store the information on the resource values for partial paths. A label in an SPPRC labelling algorithm is not a mere triple of resident vertex, current cost and predecessor vertex, as it is the case in labelling algorithms for the SPP. A label for an SPPRC labelling algorithm stores its resident vertex, its predecessor arc over which it has been extended, its predecessor label, and its current vector of resource values. The criterion to be minimized (cost, travel time, travel distance, whatsoever) is also treated as a (possibly unconstrained) resource. It is necessary to store the predecessor arc instead of the predecessor vertex, because, due to the resource constraints, one can not assume that the underlying graph is simple. Labels reside at vertices, and they are propagated via resource extension functions when they are extended along an arc. An extension of a label along an arc (i, j) is feasible if the resulting label l at j is feasible, which is the case if and only if all resource values of l are within their resource windows. +

        + +

        +To keep the number of labels as small as possible, it is decisive to perform a dominance step for eliminating unnecessary labels. A label l1 dominates a label l2 if both reside at the same vertex and if, for each feasible extension of l2, there is also a feasible extension of l1 where the value of each cardinally scaled resource is less than or equal to the value of the resource in the extension of l2, and where the value of each nominally scaled resource is equal to the value of the resource in the extension of l2. Dominated labels need not be extended. A label which is not dominated by any other label is called undominated or Pareto-optimal. The application of the dominance principle is optional—at least from a theoretical perspective. +

        + +

        +The implementation is a label-setting algorithm. This means that there must be one or more resources whose cumulated consumption(s) after extension is/are always at least as high as before. This is similar to the Dijkstra algorithm for the SPP without resource constraints where the distance measure must be non-negative. It is sufficient if there is one resource with a non-negative resource consumption along all arcs (for example, non-negative arc lengths or non-negative arc traversal times). +

        + +

        Concepts

        + +

        ResourceContainer

        + +

        +A type modelling the ResourceContainer concept is used to store the current resource consumptions of a label. +

        + +

        +Refinement of
        +DefaultConstructible, CopyConstructible, Assignable, LessThanComparable, EqualityComparable +

        + +

        +Valid Expressions
        +See ResourceExtensionFunction concept. +

        + +

        Label

        + +

        +This concept defines the interface for a label in the r_c_shortest_paths functions. It is a design decision not to parameterize the functions on the type of label. The type template<class Graph, class Resource_Container> struct r_c_shortest_paths_label is used to model this concept. +

        + +

        +Valid Expressions
        +If label is an object of type r_c_shortest_paths_label, the following expressions are valid:
        + + + + + + + + + + + + + + + + + + + + + + + + + +
        +label.num + +Returns an unsigned integer value specifying the number of the label. Labels are numbered consecutively in order of their creation. +
        +label.cumulated_resource_consumption + +Returns the object associated with label modelling the ResourceContainer concept. +
        +label.p_pred_label + +Returns a const pointer to the predecessor label, i.e., to the label whose extension along label.pred_edge yielded the label} object. +
        +label.pred_edge + +Returns an edge descriptor for the arc along which label.p_pred_label was extended to yield the label object. +
        +label.resident_vertex + +Returns a vertex descriptor for the vertex at which the label object resides. +
        +label.b_is_dominated + +Returns a boolean value indicating whether the label object is dominated by some other label residing at the vertex label.resident_vertex. Is useful only after dominance checking has been performed, i.e. only in the visitor functions on_label_dominated and on_label_not_dominated (see below). +
        + +

        +Invariants
        +Every r_c_shortest_paths_label object, except for the first label, has a valid (not null) p_pred_label pointer and a valid pred_edge member. The p_pred_label pointer of the label with num member equal to zero is a null pointer, and the pred_edge member of this label is a default-constructed edge descriptor. +

        + +

        ResourceExtensionFunction

        + +

        +A model of the ResourceExtensionFunction concept is used to specify how a label is to be extended along an arc. +

        + +

        +Valid Expressions
        +If ref models the ResourceExtensionFunction concept, and if the type Resource_Container models the ResourceContainer concept, the following expression is valid:
        + + + + + +
        +
        +bool b = ref( const Graph& g,
        +              Resource_Container& new_cont,
        +              const Resource_Container& old_cont,
        +              graph_traits<Graph>::edge_descriptor ed )
        +
        +
        +ref must return true if and only if the extension is feasible, i.e., if new_cont fulfills all resource constraints at the target vertex of ed. +
        +Moreover, a reference to a type modelling the ResourceExtensionFunction concept can be passed as a parameter to r_c_shortest_paths, see above.
        +

        + +

        +Hence, a type modelling the ResourceExtensionFunction concept is likely to be a function or a function object. +

        + +

        +Invariants
        +If ref models the ResourceExtensionFunction concept, and if the type Resource_Container models the ResourceContainer concept, after the call +

        +ref( const Graph& g,
        +     Resource_Container& new_cont,
        +     const Resource_Container& old_cont,
        +     graph_traits<Graph>::edge_descriptor )
        +
        +the expression old_cont <= new_cont evaluates to true.
        +This is because, as stated above, the implementation is a label-setting algorithm. Therefore, the Less-Than operator for ResourceContainer must compare one or more resource(s) whose resource consumption(s) along any arc is/are non-decreasing in order for the algorithm to work properly. +

        + +

        DominanceFunction

        + +

        +A model of DominanceFunction is used to specify a dominance relation between two labels. +

        + +

        +Refinement of
        +BinaryPredicate +

        + +

        +Valid Expressions
        +If dominance models the DominanceFunction concept, and if the type Resource_Container models the ResourceContainer concept, the following expression is valid: + + + + + +
        +
        +bool b = dominance(const Resource_Container& rc1, const Resource_Container& rc2)
        +
        +
        +dominance must return true if and only if rc1 dominates rc2. +
        +Moreover, a reference to a type modelling the DominanceFunction concept can be passed as a parameter to r_c_shortest_paths, see above. +

        + +

        +Invariants
        +A type modelling the DominanceFunction concept must return true if and only if rc1<=rc2. It must not return false if rc1==rc2. Then, it is guaranteed that no two labels with identical resource consumption dominate each other and are both considered as dominated by the r_c_shortest_paths functions. +

        + +

        ResourceConstrainedShortestPathsVisitor

        + +

        +This concept defines the visitor interface for r_c_shortest_paths. A user can define a type with this interface and pass an object of this type to r_c_shortest_paths to perform user-defined actions at the event points of the algorithm. Note that the object is passed by value. +

        + +

        +Refinement of
        +DefaultConstructible, CopyConstructible +

        + +

        +Valid Expressions
        +If vis is an object of a type modelling the ResourceConstrainedShortestPathsVisitor concept, and if g is an object of a type Graph modelling the IncidenceGraph and the PropertyGraph concepts, and if it is a directed graph, and if l is an object of a type Label modelling the Label concept, the following expressions are valid:
        + + + + + + + + + + + + + + + + +
        +vis.on_label_popped( const Label& l, const Graph& g ) +
        +vis.on_label_feasible( const Label& l, const Graph& g ) +
        +vis.on_label_not_feasible( const Label& l, const Graph& g ) +
        +vis.on_label_dominated( const Label& l, const Graph& g ) +
        +vis.on_label_not_dominated( const Label& l, const Graph& g ) +
        +See the description of the Label concept for the interface of a Label. See the algorithm description for information on when these functions are called. +

        + +

        Functions Description

        + +

        +The functions are an implementation of a priority-queue-based label-setting algorithm. At each iteration, the algorithm picks a label l from a priority queue (the set of unprocessed labels) and checks it for dominance against the current set of labels at the vertex i where l resides. If l is dominated by some other label residing at i, l is deleted from the set of labels residing at i. If l is undominated, it is extended along all out-edges of i. Each resulting new label is checked for feasibility, and if it is feasible, it is added to the set of unprocessed labels and to the set of labels residing at the respective successor vertex of i. If a new label is not feasible, it is discarded. The algorithm stops when there are no more unprocessed labels. It then checks whether the destination vertex could be reached (which may not be the case even for a strongly connected graph because of the resource constraints), constructs one or all Pareto-optimal (i.e., undominated) s-t-path(s) and returns. A pseudo-code of the algorithm follows. +

        + +
        +r_c_shortest_paths( g,
        +                    vertex_index_map,
        +                    edge_index_map,
        +                    s,
        +                    t,
        +                    pareto_optimal_solutions,
        +                    pareto_optimal_resource_containers,
        +                    rc,
        +                    ref,
        +                    dominance,
        +                    la,
        +                    vis )
        +{
        +  Label first_label, cur_label, new_label
        +  Set of Labels unprocessed_labels, labels_cur_vertex
        +  initialize first_label with rc
        +  INSERT(unprocessed_labels, first_label)
        +  while(unprocessed_labels != Ø)
        +    cur_label := EXTRACTMIN(unprocessed_labels)                      ◁ vis.on_label_popped(cur_label)
        +    if(cur_label is not dominated)
        +      vertex i = ResidentVertex(cur_label)
        +      perform pairwise dominance check over labels resident at i
        +      mark all dominated labels as dominated
        +      DELETE all labels which are dominated AND processed
        +    if(cur_label is not dominated)                                   ◁ vis.on_label_not_dominated(cur_label)
        +      mark cur_label as processed
        +      for each arc (i, j) in the forward star of i
        +        new_label := ref(cur_label)
        +        if(new_label is not feasible)                                ◁ vis.on_label_not_feasible(new_label)
        +          DELETE(new_label)
        +        else                                                         ◁ vis.on_label_feasible(new_label)
        +          INSERT(unprocessed_labels, new_label)
        +          INSERT(set of labels resident at j,new_label)
        +    else                                                             ◁ vis.on_label_dominated(cur_label)
        +      DELETE(cur_label)
        +  if(t could be reached from s)
        +    for each label resident at t
        +      INSERT(pareto_optimal_resource_containers, label.resource_container)
        +      recursively construct pareto_optimal_path
        +      INSERT(pareto_optimal_solutions, pareto_optimal_path)
        +      if(only one Pareto-optimal solution is sought)
        +        BREAK
        +}
        +
        + +

        Where Defined

        + +boost/graph/r_c_shortest_paths.hpp + +

        Parameters

        + +IN: const Graph& g +
        +The graph object on which the algorithm is applied. The type Graph must be directed and must be a model of Incidence Graph and PropertyGraph. +
        +IN: const VertexIndexMap& vertex_index_map +
        +A ReadablePropertyMap mapping vertex descriptors to integers in [0, num_vertices(g)). +
        +IN: const EdgeIndexMap& edge_index_map +
        +A ReadablePropertyMap mapping edge descriptors to integers in [0, num_edges(g)). +
        +IN: typename graph_traits<Graph>::vertex_descriptor s +
        +A vertex descriptor describing the start vertex of the path. +
        +IN: typename graph_traits<Graph>::vertex_descriptor t +
        +A vertex descriptor describing the end vertex of the path. +
        +OUT: std::vector<std::vector<typename graph_traits<Graph>::edge_descriptor> >& +pareto_optimal_solutions +
        +A container for storing the Pareto-optimal (undominated) solutions (s-t-paths) in the overloads where all Pareto-optimal solutions are returned. The paths are returned as sequences of edge descriptors in reverse order (from t to s). +
        +OUT: std::vector<Resource_Container>& pareto_optimal_resource_containers +
        +A container for storing the Pareto-optimal resource containers in the overloads where all Pareto-optimal solutions are returned. +
        +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). +
        +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. +
        +IN: const Resource_Container& rc +
        +An object specifying the initial resource consumptions at vertex s. The type Resource_Container must be a model of the ResourceContainer concept. +
        +IN: Resource_Extension_Function& ref +
        +A function object or function pointer or function specifying how a label is to be extended along an arc. The type Resource_Extension_Function must be a model of the ResourceExtensionFunction concept. +
        +IN: Dominance_Function& dominance +
        +A function object or function pointer or function specifying a dominance relation between two labels. The type Dominance_Function must be a model of the DominanceFunction concept. +
        +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. +
        +IN: Visitor vis +
        +A visitor object specifying what operations are to be performed at the event points in the algorithm. The type Visitor must be a model of the ResourceConstrainedShortestPathsVisitor concept. There is a default type default_r_c_shortest_paths_visitor for this parameter with empty function bodies. If the third or the fourth overload of the function is used, an object of this type is used as Visitor 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 use only a specialized allocator, one can use default_r_c_shortest_paths_visitor as Visitor parameter. +
        + +

        Preconditions

        + +
          +
        • +s and t are valid vertex descriptors for g. +
        • +rc is within the resource windows at s, i.e., it constitutes a feasible Resource_Container object at s (see discussion). +
        + +

        Throws

        + +

        +The function itself does not throw any exceptions. However, depending on the template parameters, exceptions may be thrown from within the function. +

        + +

        Complexity

        + +

        +The time complexity is problem-dependent. For a non-elementary problem or for a problem on a graph without negative cycles, the complexity is polynomial in the number of vertices and edges and a term dependent on the resources and resource extension functions used. For the elementary problem on a graph with negative cycles, the complexity is exponential in the number of vertices and edges and a term dependent on the resources and resource extension functions used. +

        + +

        Discussion

        + +

        +The function leaves a lot of work to the user. It is almost like a small framework for SPPRCs. This, however, is a property inherent to the problem. It is entirely up to the user to make sure that he stores the ‘right’ resources in his resource container object, that the resource extension function extends a label in the desired way, and that the dominance function declares the ‘right’ labels as dominated and not dominated. In particular, the precondition that the initial ResourceContainer object supplied to the function must be feasible is as important as it is unpleasant. The implementation does not check this and, hence, sacrifices comfort for genericity here. It was a design decision not to make any assumptions with respect to the relationship between the type modelling ResourceContainer and the vertex properties of the graph type. +

        + +

        +In case the underlying graph does not contain negative cycles (cycles with overall negative resource consumption for the unconstrained resource whose consumption is to be minimized, such as cost or distance), the resulting paths will always be elementary, i.e., without repetitions of vertices. In the presence of negative cycles, the algorithm is finite if there is at least one strictly increasing resource, i.e., one resource with strictly positive resource consumption on all arcs (this is a sufficient condition). Otherwise, one must provide a customized type for the ResourceContainer concept to ensure finiteness. See, for example
        +Feillet, D.; Dejax, P.; Gendreau, M.; Gueguen, C. (2004):
        +An Exact Algorithm for the Elementary Shortest Path Problem with Resource Constraints: Application to Some Vehicle Routing Problems
        +Networks, vol. 44, pp. 216–229. +

        + +

        +Experience shows that for ‘small’ resource containers, it may be useful to try a specialized small object allocator, e.g., from the Boost Pool library. For larger resource containers (i.e., for a large number of resources), the default allocator is the right choice. +

        + +

        +There is a utility function called check_path that can be used for debugging purposes, if r_c_shortest_paths returns a path as feasible and Pareto-optimal and the user is of the opinion that the path is either infeasible or not optimal: +

        +template<class Graph,
        +         class Resource_Container,
        +         class Resource_Extension_Function>
        +void check_r_c_path( const Graph& g,
        +                     const std::vector<typename graph_traits<Graph>::edge_descriptor>& ed_vec_path,
        +                     const Resource_Container& initial_resource_levels,
        +                     bool b_result_must_be_equal_to_desired_final_resource_levels,
        +                     const Resource_Container& desired_final_resource_levels,
        +                     Resource_Container& actual_final_resource_levels,
        +                     const Resource_Extension_Function& ref,
        +                     bool& b_is_a_path_at_all,
        +                     bool& b_feasible,
        +                     bool& b_correctly_extended,
        +                     typename graph_traits<Graph>::edge_descriptor&
        +                     ed_last_extended_arc )
        +
        +

        + +The boolean parameters have the following meaning: +
          +
        • +If b_result_must_be_equal_to_desired_final_resource_levels==true, computed accumulated final resource levels must be equal to desired_final_resource_levels. +
        • +If b_result_must_be_equal_to_desired_final_resource_levels==false, computed accumulated final resource levels must be less than or equal to desired_final_resource_levels. +
        • +b_is_a_path_at_all==true if and only if ed_vec_path specifies a walk in a graph-theoretical sense, i.e., a sequence of arcs where the target of an arc is the source of the next arc, or a reverse walk, where the source of one arc is the target of the next arc. Note that in the world of resource-constrained shortest paths, a path need not be elementary: Repetitions of vertices or arcs are allowed. When the graph does not have any cycles of negative cost (traversal cost, travel time etc.), the paths returned by r_c_shortest_paths will be elementary. Otherwise, one must use appropriate resource containers and resource extension and dominance functions (see the abovementioned references). +
        • +b_feasible==true if and only if b_is_a_path_at_all==true and all resource windows at all vertices along the path are maintained. +
        • +When b_result_must_be_equal_to_desired_final_resource_levels==true (false), b_correctly_extended==true if and only if b_feasible==true and the computed resource levels at the end of the path are equal to (less than or equal to) the desired final resource levels as specified in desired_final_resource_levels. +
        + +

        +ed_last_extended_arc stores the edge descriptor of the last extended arc. If ed_vec_path is a path of positive length and b_feasible==false, ed_last_extended_arc is the edge descriptor of the arc at whose target vertex the first violation of a resource window occured. +

        + +

        Examples

        + +

        +The file +example/r_c_shortest_paths_example.cpp provides examples for how SPPRCs can be solved with the r_c_shortest_paths functions. There is an example for an SPP without resource constraints and an example for a shortest path problem with time windows.
        +It is obvious that one would not use the algorithm for SPPs without resource constraints, because there are faster algorithms for this problem, but one would expect a code for the SPP with resource constraints to be able to handle such a case. +

        + +
        +
        + + + +
        Copyright © 2006 +Michael Drexl (michaeldrexl at web dot de) +
        + + + diff --git a/doc/table_of_contents.html b/doc/table_of_contents.html index 50db4e33..4c045f61 100644 --- a/doc/table_of_contents.html +++ b/doc/table_of_contents.html @@ -143,6 +143,7 @@
      • johnson_all_pairs_shortest_paths
      • floyd_warshall_all_pairs_shortest_paths
      • +
      • r_c_shortest_paths - resource-constrained shortest paths
      • Minimum Spanning Tree Algorithms
          diff --git a/example/r_c_shortest_paths_example.cpp b/example/r_c_shortest_paths_example.cpp new file mode 100755 index 00000000..5024c459 --- /dev/null +++ b/example/r_c_shortest_paths_example.cpp @@ -0,0 +1,354 @@ +// Copyright Michael Drexl 2005, 2006. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://boost.org/LICENSE_1_0.txt) + +// Example use of the resource-constrained shortest paths algorithm. +#include + +#ifdef BOOST_MSVC +# pragma warning(disable: 4267) +#endif + +#include + +#include +#include + +using namespace boost; + +struct SPPRC_Example_Graph_Vert_Prop +{ + SPPRC_Example_Graph_Vert_Prop( int n = 0, int e = 0, int l = 0 ) + : num( n ), eat( e ), lat( l ) {} + int num; + // earliest arrival time + int eat; + // latest arrival time + int lat; +}; + +struct SPPRC_Example_Graph_Arc_Prop +{ + SPPRC_Example_Graph_Arc_Prop( int n = 0, int c = 0, int t = 0 ) + : num( n ), cost( c ), time( t ) {} + int num; + // traversal cost + int cost; + // traversal time + int time; +}; + +typedef adjacency_list + SPPRC_Example_Graph; + +// data structures for spp without resource constraints: +// ResourceContainer model +struct spp_no_rc_res_cont +{ + spp_no_rc_res_cont( int c = 0 ) : cost( c ) {}; + spp_no_rc_res_cont& operator=( const spp_no_rc_res_cont& other ) + { + if( this == &other ) + return *this; + this->~spp_no_rc_res_cont(); + new( this ) spp_no_rc_res_cont( other ); + return *this; + } + int cost; +}; + +bool operator==( const spp_no_rc_res_cont& res_cont_1, + const spp_no_rc_res_cont& res_cont_2 ) +{ + return ( res_cont_1.cost == res_cont_2.cost ); +} + +bool operator<( const spp_no_rc_res_cont& res_cont_1, + const spp_no_rc_res_cont& res_cont_2 ) +{ + return ( res_cont_1.cost < res_cont_2.cost ); +} + +// ResourceExtensionFunction model +class ref_no_res_cont +{ +public: + inline bool operator()( const SPPRC_Example_Graph& g, + spp_no_rc_res_cont& new_cont, + const spp_no_rc_res_cont& old_cont, + graph_traits + ::edge_descriptor ed ) const + { + new_cont.cost = old_cont.cost + g[ed].cost; + return true; + } +}; + +// DominanceFunction model +class dominance_no_res_cont +{ +public: + inline bool operator()( const spp_no_rc_res_cont& res_cont_1, + const spp_no_rc_res_cont& res_cont_2 ) const + { + // must be "<=" here!!! + // must NOT be "<"!!! + return res_cont_1.cost <= res_cont_2.cost; + // this is not a contradiction to the documentation + // the documentation says: + // "A label $l_1$ dominates a label $l_2$ if and only if both are resident + // at the same vertex, and if, for each resource, the resource consumption + // of $l_1$ is less than or equal to the resource consumption of $l_2$, + // and if there is at least one resource where $l_1$ has a lower resource + // consumption than $l_2$." + // one can think of a new label with a resource consumption equal to that + // of an old label as being dominated by that old label, because the new + // one will have a higher number and is created at a later point in time, + // so one can implicitly use the number or the creation time as a resource + // for tie-breaking + } +}; +// end data structures for spp without resource constraints: + +// data structures for shortest path problem with time windows (spptw) +// ResourceContainer model +struct spp_spptw_res_cont +{ + spp_spptw_res_cont( int c = 0, int t = 0 ) : cost( c ), time( t ) {} + spp_spptw_res_cont& operator=( const spp_spptw_res_cont& other ) + { + if( this == &other ) + return *this; + this->~spp_spptw_res_cont(); + new( this ) spp_spptw_res_cont( other ); + return *this; + } + int cost; + int time; +}; + +bool operator==( const spp_spptw_res_cont& res_cont_1, + const spp_spptw_res_cont& res_cont_2 ) +{ + return ( res_cont_1.cost == res_cont_2.cost + && res_cont_1.time == res_cont_2.time ); +} + +bool operator<( const spp_spptw_res_cont& res_cont_1, + const spp_spptw_res_cont& res_cont_2 ) +{ + if( res_cont_1.cost > res_cont_2.cost ) + return false; + if( res_cont_1.cost == res_cont_2.cost ) + return res_cont_1.time < res_cont_2.time; + return true; +} + +// ResourceExtensionFunction model +class ref_spptw +{ +public: + inline bool operator()( const SPPRC_Example_Graph& g, + spp_spptw_res_cont& new_cont, + const spp_spptw_res_cont& old_cont, + graph_traits + ::edge_descriptor ed ) const + { + const SPPRC_Example_Graph_Arc_Prop& arc_prop = + get( edge_bundle, g )[ed]; + const SPPRC_Example_Graph_Vert_Prop& vert_prop = + get( vertex_bundle, g )[target( ed, g )]; + new_cont.cost = old_cont.cost + arc_prop.cost; + int& i_time = new_cont.time; + i_time = old_cont.time + arc_prop.time; + i_time < vert_prop.eat ? i_time = vert_prop.eat : 0; + return i_time <= vert_prop.lat ? true : false; + } +}; + +// DominanceFunction model +class dominance_spptw +{ +public: + inline bool operator()( const spp_spptw_res_cont& res_cont_1, + const spp_spptw_res_cont& res_cont_2 ) const + { + // must be "<=" here!!! + // must NOT be "<"!!! + return res_cont_1.cost <= res_cont_2.cost + && res_cont_1.time <= res_cont_2.time; + // this is not a contradiction to the documentation + // the documentation says: + // "A label $l_1$ dominates a label $l_2$ if and only if both are resident + // at the same vertex, and if, for each resource, the resource consumption + // of $l_1$ is less than or equal to the resource consumption of $l_2$, + // and if there is at least one resource where $l_1$ has a lower resource + // consumption than $l_2$." + // one can think of a new label with a resource consumption equal to that + // of an old label as being dominated by that old label, because the new + // one will have a higher number and is created at a later point in time, + // so one can implicitly use the number or the creation time as a resource + // for tie-breaking + } +}; +// end data structures for shortest path problem with time windows (spptw) + +// example graph structure and cost from +// http://www.boost.org/libs/graph/example/dijkstra-example.cpp +const int num_nodes = 5; +enum nodes { A, B, C, D, E }; +char name[] = "ABCDE"; + +int main() +{ + SPPRC_Example_Graph g; + + add_vertex( SPPRC_Example_Graph_Vert_Prop( A, 0, 0 ), g ); + add_vertex( SPPRC_Example_Graph_Vert_Prop( B, 5, 20 ), g ); + add_vertex( SPPRC_Example_Graph_Vert_Prop( C, 6, 10 ), g ); + add_vertex( SPPRC_Example_Graph_Vert_Prop( D, 3, 12 ), g ); + add_vertex( SPPRC_Example_Graph_Vert_Prop( E, 0, 100 ), g ); + + add_edge( A, C, SPPRC_Example_Graph_Arc_Prop( 0, 1, 5 ), g ); + add_edge( B, B, SPPRC_Example_Graph_Arc_Prop( 1, 2, 5 ), g ); + add_edge( B, D, SPPRC_Example_Graph_Arc_Prop( 2, 1, 2 ), g ); + add_edge( B, E, SPPRC_Example_Graph_Arc_Prop( 3, 2, 7 ), g ); + add_edge( C, B, SPPRC_Example_Graph_Arc_Prop( 4, 7, 3 ), g ); + add_edge( C, D, SPPRC_Example_Graph_Arc_Prop( 5, 3, 8 ), g ); + add_edge( D, E, SPPRC_Example_Graph_Arc_Prop( 6, 1, 3 ), g ); + add_edge( E, A, SPPRC_Example_Graph_Arc_Prop( 7, 1, 5 ), g ); + add_edge( E, B, SPPRC_Example_Graph_Arc_Prop( 8, 1, 4 ), g ); + + + // the unique shortest path from A to E in the dijkstra-example.cpp is + // A -> C -> D -> E + // its length is 5 + // the following code also yields this result + + // with the above time windows, this path is infeasible + // now, there are two shortest paths that are also feasible with respect to + // the vertex time windows: + // A -> C -> B -> D -> E and + // A -> C -> B -> E + // however, the latter has a longer total travel time and is therefore not + // pareto-optimal, i.e., it is dominated by the former path + // therefore, the code below returns only the former path + + // spp without resource constraints + graph_traits::vertex_descriptor s = A; + graph_traits::vertex_descriptor t = E; + + std::vector + ::edge_descriptor> > + opt_solutions; + std::vector pareto_opt_rcs_no_rc; + + r_c_shortest_paths + ( g, + get( &SPPRC_Example_Graph_Vert_Prop::num, g ), + get( &SPPRC_Example_Graph_Arc_Prop::num, g ), + s, + t, + opt_solutions, + pareto_opt_rcs_no_rc, + spp_no_rc_res_cont( 0 ), + ref_no_res_cont(), + dominance_no_res_cont(), + std::allocator + >(), + default_r_c_shortest_paths_visitor() ); + + std::cout << "SPP without resource constraints:" << std::endl; + std::cout << "Number of optimal solutions: "; + std::cout << static_cast( opt_solutions.size() ) << std::endl; + for( int i = 0; i < static_cast( opt_solutions.size() ); ++i ) + { + std::cout << "The " << i << "th shortest path from A to E is: "; + std::cout << std::endl; + for( int j = static_cast( opt_solutions[i].size() ) - 1; j >= 0; --j ) + std::cout << name[source( opt_solutions[i][j], g )] << std::endl; + std::cout << "E" << std::endl; + std::cout << "Length: " << pareto_opt_rcs_no_rc[i].cost << std::endl; + } + std::cout << std::endl; + + // spptw + std::vector + ::edge_descriptor> > + opt_solutions_spptw; + std::vector pareto_opt_rcs_spptw; + + r_c_shortest_paths + ( g, + get( &SPPRC_Example_Graph_Vert_Prop::num, g ), + get( &SPPRC_Example_Graph_Arc_Prop::num, g ), + s, + t, + opt_solutions_spptw, + pareto_opt_rcs_spptw, + spp_spptw_res_cont( 0, 0 ), + ref_spptw(), + dominance_spptw(), + std::allocator + >(), + default_r_c_shortest_paths_visitor() ); + + std::cout << "SPP with time windows:" << std::endl; + std::cout << "Number of optimal solutions: "; + std::cout << static_cast( opt_solutions.size() ) << std::endl; + for( int i = 0; i < static_cast( opt_solutions.size() ); ++i ) + { + std::cout << "The " << i << "th shortest path from A to E is: "; + std::cout << std::endl; + for( int j = static_cast( opt_solutions_spptw[i].size() ) - 1; + j >= 0; + --j ) + std::cout << name[source( opt_solutions_spptw[i][j], g )] << std::endl; + std::cout << "E" << std::endl; + std::cout << "Length: " << pareto_opt_rcs_spptw[i].cost << std::endl; + std::cout << "Time: " << pareto_opt_rcs_spptw[i].time << std::endl; + } + + // utility function check_r_c_path example + std::cout << std::endl; + bool b_is_a_path_at_all = false; + bool b_feasible = false; + bool b_correctly_extended = false; + spp_spptw_res_cont actual_final_resource_levels( 0, 0 ); + graph_traits::edge_descriptor ed_last_extended_arc; + check_r_c_path( g, + opt_solutions_spptw[0], + spp_spptw_res_cont( 0, 0 ), + true, + pareto_opt_rcs_spptw[0], + actual_final_resource_levels, + ref_spptw(), + b_is_a_path_at_all, + b_feasible, + b_correctly_extended, + ed_last_extended_arc ); + if( !b_is_a_path_at_all ) + std::cout << "Not a path." << std::endl; + if( !b_feasible ) + std::cout << "Not a feasible path." << std::endl; + if( !b_correctly_extended ) + std::cout << "Not correctly extended." << std::endl; + if( b_is_a_path_at_all && b_feasible && b_correctly_extended ) + { + std::cout << "Actual final resource levels:" << std::endl; + std::cout << "Length: " << actual_final_resource_levels.cost << std::endl; + std::cout << "Time: " << actual_final_resource_levels.time << std::endl; + std::cout << "OK." << std::endl; + } + + return 0; +} diff --git a/include/boost/graph/r_c_shortest_paths.hpp b/include/boost/graph/r_c_shortest_paths.hpp new file mode 100644 index 00000000..4e935dcf --- /dev/null +++ b/include/boost/graph/r_c_shortest_paths.hpp @@ -0,0 +1,729 @@ +// r_c_shortest_paths.hpp header file + +// Copyright Michael Drexl 2005, 2006. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GRAPH_R_C_SHORTEST_PATHS_HPP +#define BOOST_GRAPH_R_C_SHORTEST_PATHS_HPP + +#include +#include +#include + +#include + +namespace boost { + +// r_c_shortest_paths_label struct +template +struct r_c_shortest_paths_label +{ + r_c_shortest_paths_label + ( const unsigned long n, + const Resource_Container& rc = Resource_Container(), + const r_c_shortest_paths_label* const pl = 0, + const typename graph_traits::edge_descriptor& ed = + graph_traits::edge_descriptor(), + const typename graph_traits::vertex_descriptor& vd = + graph_traits::vertex_descriptor() ) + : num( n ), + cumulated_resource_consumption( rc ), + p_pred_label( pl ), + pred_edge( ed ), + resident_vertex( vd ), + b_is_dominated( false ), + b_is_processed( false ) + {} + r_c_shortest_paths_label& operator=( const r_c_shortest_paths_label& other ) + { + if( this == &other ) + return *this; + this->~r_c_shortest_paths_label(); + new( this ) r_c_shortest_paths_label( other ); + return *this; + } + const unsigned long num; + Resource_Container cumulated_resource_consumption; + const r_c_shortest_paths_label* const p_pred_label; + const typename graph_traits::edge_descriptor pred_edge; + const typename graph_traits::vertex_descriptor resident_vertex; + bool b_is_dominated; + bool b_is_processed; +}; // r_c_shortest_paths_label + +template +inline bool operator== +( const r_c_shortest_paths_label& l1, + const r_c_shortest_paths_label& l2 ) +{ + return + l1.cumulated_resource_consumption == l2.cumulated_resource_consumption; +} + +template +inline bool operator!= +( const r_c_shortest_paths_label& l1, + const r_c_shortest_paths_label& l2 ) +{ + return + !( l1 == l2 ); +} + +template +inline bool operator< +( const r_c_shortest_paths_label& l1, + const r_c_shortest_paths_label& l2 ) +{ + return + l1.cumulated_resource_consumption < l2.cumulated_resource_consumption; +} + +template +inline bool operator> +( const r_c_shortest_paths_label& l1, + const r_c_shortest_paths_label& l2 ) +{ + return + l2.cumulated_resource_consumption < l1.cumulated_resource_consumption; +} + +template +inline bool operator<= +( const r_c_shortest_paths_label& l1, + const r_c_shortest_paths_label& l2 ) +{ + return + l1 < l2 || l1 == l2; +} + +template +inline bool operator>= +( const r_c_shortest_paths_label& l1, + const r_c_shortest_paths_label& l2 ) +{ + return l2 < l1 || l1 == l2; +} + +namespace detail { + +// ks_smart_pointer class +// from: +// Kuhlins, S.; Schader, M. (1999): +// Die C++-Standardbibliothek +// Springer, Berlin +// p. 333 f. +template +class ks_smart_pointer +{ +public: + ks_smart_pointer( T* ptt = 0 ) : pt( ptt ) {} + ks_smart_pointer( const ks_smart_pointer& other ) : pt( other.pt ) {} + ks_smart_pointer& operator=( const ks_smart_pointer& other ) + { pt = other.pt; return *this; } + ~ks_smart_pointer() {} + T& operator*() const { return *pt; } + T* operator->() const { return pt; } + T* get() const { return pt; } + operator T*() const { return pt; } + friend bool operator==( const ks_smart_pointer& t, + const ks_smart_pointer& u ) + { return *t.pt == *u.pt; } + friend bool operator!=( const ks_smart_pointer& t, + const ks_smart_pointer& u ) + { return *t.pt != *u.pt; } + friend bool operator<( const ks_smart_pointer& t, + const ks_smart_pointer& u ) + { return *t.pt < *u.pt; } + friend bool operator>( const ks_smart_pointer& t, + const ks_smart_pointer& u ) + { return *t.pt > *u.pt; } + friend bool operator<=( const ks_smart_pointer& t, + const ks_smart_pointer& u ) + { return *t.pt <= *u.pt; } + friend bool operator>=( const ks_smart_pointer& t, + const ks_smart_pointer& u ) + { return *t.pt >= *u.pt; } +private: + T* pt; +}; // ks_smart_pointer + + +// r_c_shortest_paths_dispatch function (body/implementation) +template +void r_c_shortest_paths_dispatch +( const Graph& g, + const VertexIndexMap& vertex_index_map, + const EdgeIndexMap& edge_index_map, + typename graph_traits::vertex_descriptor s, + typename graph_traits::vertex_descriptor t, + // each inner vector corresponds to a pareto-optimal path + std::vector + ::edge_descriptor> >& pareto_optimal_solutions, + std::vector + & pareto_optimal_resource_containers, + bool b_all_pareto_optimal_solutions, + // to initialize the first label/resource container + // and to carry the type information + const Resource_Container& rc, + Resource_Extension_Function& ref, + Dominance_Function& dominance, + // to specify the memory management strategy for the labels + Label_Allocator la, + Visitor vis ) +{ + pareto_optimal_resource_containers.clear(); + pareto_optimal_solutions.clear(); + + unsigned long i_label_num = 0; + typedef + typename + Label_Allocator::template rebind + >::other LAlloc; + LAlloc l_alloc; + typedef + ks_smart_pointer + > Splabel; + std::priority_queue, std::greater > + unprocessed_labels; + + bool b_feasible = true; + r_c_shortest_paths_label* first_label = + l_alloc.allocate( 1 ); + l_alloc.construct + ( first_label, + r_c_shortest_paths_label + ( i_label_num++, + rc, + 0, + typename graph_traits:: + edge_descriptor(), + s ) ); + + 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( int i = 0; i < static_cast( 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 + b_vec_vertex_already_checked_for_dominance( num_vertices( g ), false ); + while( unprocessed_labels.size() ) + { + Splabel cur_label = unprocessed_labels.top(); + unprocessed_labels.pop(); + vis.on_label_popped( *cur_label, g ); + // an Splabel object in unprocessed_labels and the respective Splabel + // object in the respective list of vec_vertex_labels share their + // embedded r_c_shortest_paths_label object + // to avoid memory leaks, dominated + // r_c_shortest_paths_label objects are marked and deleted when popped + // from unprocessed_labels, as they can no longer be deleted at the end of + // the function; only the Splabel object in unprocessed_labels still + // references the r_c_shortest_paths_label object + // this is also for efficiency, because the else branch is executed only + // 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 + if( !cur_label->b_is_dominated ) + { + int i_cur_resident_vertex_num = 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 + && vec_last_valid_index_for_dominance[i_cur_resident_vertex_num] + < static_cast( list_labels_cur_vertex.size() ) ) + { + typename std::list::iterator outer_iter = + list_labels_cur_vertex.begin(); + bool b_outer_iter_at_or_beyond_last_valid_pos_for_dominance = false; + while( outer_iter != list_labels_cur_vertex.end() ) + { + Splabel cur_outer_splabel = *outer_iter; + 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] ) + 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] + || b_outer_iter_at_or_beyond_last_valid_pos_for_dominance ) + { + ++inner_iter; + } + else + { + inner_iter = + vec_last_valid_positions_for_dominance + [i_cur_resident_vertex_num]; + ++inner_iter; + } + bool b_outer_iter_erased = false; + while( inner_iter != list_labels_cur_vertex.end() ) + { + Splabel cur_inner_splabel = *inner_iter; + if( dominance( cur_outer_splabel-> + cumulated_resource_consumption, + cur_inner_splabel-> + cumulated_resource_consumption ) ) + { + typename std::list::iterator buf = inner_iter; + ++inner_iter; + list_labels_cur_vertex.erase( buf ); + if( cur_inner_splabel->b_is_processed ) + { + l_alloc.destroy( cur_inner_splabel.get() ); + l_alloc.deallocate( cur_inner_splabel.get(), 1 ); + } + else + cur_inner_splabel->b_is_dominated = true; + continue; + } + else + ++inner_iter; + if( dominance( cur_inner_splabel-> + cumulated_resource_consumption, + cur_outer_splabel-> + cumulated_resource_consumption ) ) + { + typename std::list::iterator buf = outer_iter; + ++outer_iter; + list_labels_cur_vertex.erase( buf ); + b_outer_iter_erased = true; + if( cur_outer_splabel->b_is_processed ) + { + l_alloc.destroy( cur_outer_splabel.get() ); + l_alloc.deallocate( cur_outer_splabel.get(), 1 ); + } + else + cur_outer_splabel->b_is_dominated = true; + break; + } + } + if( !b_outer_iter_erased ) + ++outer_iter; + } + if( static_cast( list_labels_cur_vertex.size() ) > 1 ) + vec_last_valid_positions_for_dominance[i_cur_resident_vertex_num] = + (--(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] = + static_cast( list_labels_cur_vertex.size() ) - 1; + } + } + if( !b_all_pareto_optimal_solutions && cur_label->resident_vertex == t ) + { + // the devil don't sleep + if( cur_label->b_is_dominated ) + { + l_alloc.destroy( cur_label.get() ); + l_alloc.deallocate( cur_label.get(), 1 ); + } + while( unprocessed_labels.size() ) + { + Splabel l = unprocessed_labels.top(); + unprocessed_labels.pop(); + // delete only dominated labels, because nondominated labels are + // deleted at the end of the function + if( l->b_is_dominated ) + { + l_alloc.destroy( l.get() ); + l_alloc.deallocate( l.get(), 1 ); + } + } + break; + } + if( !cur_label->b_is_dominated ) + { + cur_label->b_is_processed = true; + vis.on_label_not_dominated( *cur_label, g ); + typename graph_traits::vertex_descriptor cur_vertex = + cur_label->resident_vertex; + typename graph_traits::out_edge_iterator oei, oei_end; + for( tie( oei, oei_end ) = out_edges( cur_vertex, g ); + oei != oei_end; + ++oei ) + { + b_feasible = true; + r_c_shortest_paths_label* new_label = + l_alloc.allocate( 1 ); + l_alloc.construct( new_label, + r_c_shortest_paths_label + + ( i_label_num++, + cur_label->cumulated_resource_consumption, + cur_label.get(), + *oei, + target( *oei, g ) ) ); + b_feasible = + ref( g, + new_label->cumulated_resource_consumption, + new_label->p_pred_label->cumulated_resource_consumption, + new_label->pred_edge ); + + if( !b_feasible ) + { + vis.on_label_not_feasible( *new_label, g ); + l_alloc.destroy( new_label ); + l_alloc.deallocate( new_label, 1 ); + } + else + { + const r_c_shortest_paths_label& + 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]]. + push_back( new_sp_label ); + unprocessed_labels.push( new_sp_label ); + } + } + } + else + { + vis.on_label_dominated( *cur_label, g ); + l_alloc.destroy( cur_label.get() ); + l_alloc.deallocate( cur_label.get(), 1 ); + } + } + std::list dsplabels = vec_vertex_labels[vertex_index_map[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 + if( dsplabels.size() ) + { + for( ; csi != csi_end; ++csi ) + { + std::vector::edge_descriptor> + cur_pareto_optimal_path; + const r_c_shortest_paths_label* p_cur_label = + (*csi).get(); + 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; + } + pareto_optimal_solutions.push_back( cur_pareto_optimal_path ); + if( !b_all_pareto_optimal_solutions ) + break; + } + } + + int i_size = static_cast( vec_vertex_labels.size() ); + for( int i = 0; i < i_size; ++i ) + { + 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 ) + { + l_alloc.destroy( (*csi).get() ); + l_alloc.deallocate( (*csi).get(), 1 ); + } + } +} // r_c_shortest_paths_dispatch + +} // detail + +// default_r_c_shortest_paths_visitor struct +struct default_r_c_shortest_paths_visitor +{ + template + void on_label_popped( const Label& l, const Graph& g ) {} + template + void on_label_feasible( const Label& l, const Graph& g ) {} + template + void on_label_not_feasible( const Label& l, const Graph& g ) {} + template + void on_label_dominated( const Label& l, const Graph& g ) {} + template + void on_label_not_dominated( const Label& l, const Graph& g ) {} +}; // default_r_c_shortest_paths_visitor + + +// default_r_c_shortest_paths_allocator +typedef + std::allocator default_r_c_shortest_paths_allocator; +// default_r_c_shortest_paths_allocator + + +// r_c_shortest_paths functions (handle/interface) +// first overload: +// - return all pareto-optimal solutions +// - specify Label_Allocator and Visitor arguments +template +void r_c_shortest_paths +( const Graph& g, + const VertexIndexMap& vertex_index_map, + const EdgeIndexMap& edge_index_map, + typename graph_traits::vertex_descriptor s, + typename graph_traits::vertex_descriptor t, + // each inner vector corresponds to a pareto-optimal path + std::vector::edge_descriptor> >& + pareto_optimal_solutions, + std::vector& pareto_optimal_resource_containers, + // to initialize the first label/resource container + // and to carry the type information + const Resource_Container& rc, + const Resource_Extension_Function& ref, + const Dominance_Function& dominance, + // to specify the memory management strategy for the labels + Label_Allocator la, + Visitor vis ) +{ + r_c_shortest_paths_dispatch( g, + vertex_index_map, + edge_index_map, + s, + t, + pareto_optimal_solutions, + pareto_optimal_resource_containers, + true, + rc, + ref, + dominance, + la, + vis ); +} + +// second overload: +// - return only one pareto-optimal solution +// - specify Label_Allocator and Visitor arguments +template +void r_c_shortest_paths +( const Graph& g, + const VertexIndexMap& vertex_index_map, + const EdgeIndexMap& edge_index_map, + typename graph_traits::vertex_descriptor s, + typename graph_traits::vertex_descriptor t, + std::vector::edge_descriptor>& + pareto_optimal_solution, + Resource_Container& pareto_optimal_resource_container, + // to initialize the first label/resource container + // and to carry the type information + const Resource_Container& rc, + const Resource_Extension_Function& ref, + const Dominance_Function& dominance, + // to specify the memory management strategy for the labels + Label_Allocator la, + Visitor vis ) +{ + // each inner vector corresponds to a pareto-optimal path + std::vector::edge_descriptor> > + pareto_optimal_solutions; + std::vector pareto_optimal_resource_containers; + r_c_shortest_paths_dispatch( g, + vertex_index_map, + edge_index_map, + s, + t, + pareto_optimal_solutions, + pareto_optimal_resource_containers, + false, + rc, + ref, + dominance, + la, + vis ); + pareto_optimal_solution = pareto_optimal_solutions[0]; + pareto_optimal_resource_container = pareto_optimal_resource_containers[0]; +} + +// third overload: +// - return all pareto-optimal solutions +// - use default Label_Allocator and Visitor +template +void r_c_shortest_paths +( const Graph& g, + const VertexIndexMap& vertex_index_map, + const EdgeIndexMap& edge_index_map, + typename graph_traits::vertex_descriptor s, + typename graph_traits::vertex_descriptor t, + // each inner vector corresponds to a pareto-optimal path + std::vector::edge_descriptor> >& + pareto_optimal_solutions, + std::vector& pareto_optimal_resource_containers, + // to initialize the first label/resource container + // and to carry the type information + const Resource_Container& rc, + const Resource_Extension_Function& ref, + const Dominance_Function& dominance ) +{ + r_c_shortest_paths_dispatch( g, + vertex_index_map, + edge_index_map, + s, + t, + pareto_optimal_solutions, + pareto_optimal_resource_containers, + true, + rc, + ref, + dominance, + default_r_c_shortest_paths_allocator(), + default_r_c_shortest_paths_visitor() ); +} + +// fourth overload: +// - return only one pareto-optimal solution +// - use default Label_Allocator and Visitor +template +void r_c_shortest_paths +( const Graph& g, + const VertexIndexMap& vertex_index_map, + const EdgeIndexMap& edge_index_map, + typename graph_traits::vertex_descriptor s, + typename graph_traits::vertex_descriptor t, + std::vector::edge_descriptor>& + pareto_optimal_solution, + Resource_Container& pareto_optimal_resource_container, + // to initialize the first label/resource container + // and to carry the type information + const Resource_Container& rc, + const Resource_Extension_Function& ref, + const Dominance_Function& dominance ) +{ + // each inner vector corresponds to a pareto-optimal path + std::vector::edge_descriptor> > + pareto_optimal_solutions; + std::vector pareto_optimal_resource_containers; + r_c_shortest_paths_dispatch( g, + vertex_index_map, + edge_index_map, + s, + t, + pareto_optimal_solutions, + pareto_optimal_resource_containers, + false, + rc, + ref, + 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]; +} +// r_c_shortest_paths + + +// check_r_c_path function +template +void check_r_c_path( const Graph& g, + const std::vector + ::edge_descriptor>& ed_vec_path, + const Resource_Container& initial_resource_levels, + // if true, computed accumulated final resource levels must + // be equal to desired_final_resource_levels + // if false, computed accumulated final resource levels must + // be less than or equal to desired_final_resource_levels + bool b_result_must_be_equal_to_desired_final_resource_levels, + const Resource_Container& desired_final_resource_levels, + Resource_Container& actual_final_resource_levels, + const Resource_Extension_Function& ref, + bool& b_is_a_path_at_all, + bool& b_feasible, + bool& b_correctly_extended, + typename graph_traits::edge_descriptor& + ed_last_extended_arc ) +{ + int i_size_ed_vec_path = static_cast( ed_vec_path.size() ); + std::vector::edge_descriptor> buf_path; + if( i_size_ed_vec_path == 0 ) + b_feasible = true; + else + { + if( i_size_ed_vec_path == 1 + || 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 ) + { + if( target( buf_path[i], g ) != source( buf_path[i + 1], g ) ) + { + b_is_a_path_at_all = false; + b_feasible = false; + b_correctly_extended = false; + return; + } + } + } + b_is_a_path_at_all = true; + b_feasible = true; + 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 ) + { + ed_last_extended_arc = buf_path[i]; + b_feasible = ref( g, + actual_final_resource_levels, + current_resource_levels, + buf_path[i] ); + current_resource_levels = actual_final_resource_levels; + if( !b_feasible ) + return; + } + if( b_result_must_be_equal_to_desired_final_resource_levels ) + b_correctly_extended = + actual_final_resource_levels == desired_final_resource_levels ? + true : false; + else + { + if( actual_final_resource_levels < desired_final_resource_levels + || actual_final_resource_levels == desired_final_resource_levels ) + b_correctly_extended = true; + } +} // check_path + +} // namespace + +#endif // BOOST_GRAPH_R_C_SHORTEST_PATHS_HPP diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 61332ff5..0c179d7b 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -133,6 +133,8 @@ test-suite graph_test : ../../system/build : $(PLANAR_INPUT_FILES) ] + [ run r_c_shortest_paths_test.cpp ] + $(optional_tests) ; diff --git a/test/r_c_shortest_paths_test.cpp b/test/r_c_shortest_paths_test.cpp new file mode 100755 index 00000000..8459eb0a --- /dev/null +++ b/test/r_c_shortest_paths_test.cpp @@ -0,0 +1,641 @@ +// Copyright Michael Drexl 2005, 2006. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://boost.org/LICENSE_1_0.txt) + +#include + +#ifdef BOOST_MSVC +# pragma warning(disable: 4267) +#endif + +#include +//#include + +#include +#include +#include + +using namespace boost; + +struct SPPRC_Example_Graph_Vert_Prop +{ + SPPRC_Example_Graph_Vert_Prop( int n = 0, int e = 0, int l = 0 ) + : num( n ), eat( e ), lat( l ) {} + int num; + // earliest arrival time + int eat; + // latest arrival time + int lat; +}; + +struct SPPRC_Example_Graph_Arc_Prop +{ + SPPRC_Example_Graph_Arc_Prop( int n = 0, int c = 0, int t = 0 ) + : num( n ), cost( c ), time( t ) {} + int num; + // traversal cost + int cost; + // traversal time + int time; +}; + +typedef adjacency_list + SPPRC_Example_Graph; + +// data structures for spp without resource constraints: +// ResourceContainer model +struct spp_no_rc_res_cont +{ + spp_no_rc_res_cont( int c = 0 ) : cost( c ) {}; + spp_no_rc_res_cont& operator=( const spp_no_rc_res_cont& other ) + { + if( this == &other ) + return *this; + this->~spp_no_rc_res_cont(); + new( this ) spp_no_rc_res_cont( other ); + return *this; + } + int cost; +}; + +bool operator==( const spp_no_rc_res_cont& res_cont_1, + const spp_no_rc_res_cont& res_cont_2 ) +{ + return ( res_cont_1.cost == res_cont_2.cost ); +} + +bool operator<( const spp_no_rc_res_cont& res_cont_1, + const spp_no_rc_res_cont& res_cont_2 ) +{ + return ( res_cont_1.cost < res_cont_2.cost ); +} + +// ResourceExtensionFunction model +class ref_no_res_cont +{ +public: + inline bool operator()( const SPPRC_Example_Graph& g, + spp_no_rc_res_cont& new_cont, + const spp_no_rc_res_cont& old_cont, + graph_traits + ::edge_descriptor ed ) const + { + new_cont.cost = old_cont.cost + g[ed].cost; + return true; + } +}; + +// DominanceFunction model +class dominance_no_res_cont +{ +public: + inline bool operator()( const spp_no_rc_res_cont& res_cont_1, + const spp_no_rc_res_cont& res_cont_2 ) const + { + // must be "<=" here!!! + // must NOT be "<"!!! + return res_cont_1.cost <= res_cont_2.cost; + // this is not a contradiction to the documentation + // the documentation says: + // "A label $l_1$ dominates a label $l_2$ if and only if both are resident + // at the same vertex, and if, for each resource, the resource consumption + // of $l_1$ is less than or equal to the resource consumption of $l_2$, + // and if there is at least one resource where $l_1$ has a lower resource + // consumption than $l_2$." + // one can think of a new label with a resource consumption equal to that + // of an old label as being dominated by that old label, because the new + // one will have a higher number and is created at a later point in time, + // so one can implicitly use the number or the creation time as a resource + // for tie-breaking + } +}; +// end data structures for spp without resource constraints: + +// data structures for shortest path problem with time windows (spptw) +// ResourceContainer model +struct spp_spptw_res_cont +{ + spp_spptw_res_cont( int c = 0, int t = 0 ) : cost( c ), time( t ) {} + spp_spptw_res_cont& operator=( const spp_spptw_res_cont& other ) + { + if( this == &other ) + return *this; + this->~spp_spptw_res_cont(); + new( this ) spp_spptw_res_cont( other ); + return *this; + } + int cost; + int time; +}; + +bool operator==( const spp_spptw_res_cont& res_cont_1, + const spp_spptw_res_cont& res_cont_2 ) +{ + return ( res_cont_1.cost == res_cont_2.cost + && res_cont_1.time == res_cont_2.time ); +} + +bool operator<( const spp_spptw_res_cont& res_cont_1, + const spp_spptw_res_cont& res_cont_2 ) +{ + if( res_cont_1.cost > res_cont_2.cost ) + return false; + if( res_cont_1.cost == res_cont_2.cost ) + return res_cont_1.time < res_cont_2.time; + return true; +} + +// ResourceExtensionFunction model +class ref_spptw +{ +public: + inline bool operator()( const SPPRC_Example_Graph& g, + spp_spptw_res_cont& new_cont, + const spp_spptw_res_cont& old_cont, + graph_traits + ::edge_descriptor ed ) const + { + const SPPRC_Example_Graph_Arc_Prop& arc_prop = + get( edge_bundle, g )[ed]; + const SPPRC_Example_Graph_Vert_Prop& vert_prop = + get( vertex_bundle, g )[target( ed, g )]; + new_cont.cost = old_cont.cost + arc_prop.cost; + int& i_time = new_cont.time; + i_time = old_cont.time + arc_prop.time; + i_time < vert_prop.eat ? i_time = vert_prop.eat : 0; + return i_time <= vert_prop.lat ? true : false; + } +}; + +// DominanceFunction model +class dominance_spptw +{ +public: + inline bool operator()( const spp_spptw_res_cont& res_cont_1, + const spp_spptw_res_cont& res_cont_2 ) const + { + // must be "<=" here!!! + // must NOT be "<"!!! + return res_cont_1.cost <= res_cont_2.cost + && res_cont_1.time <= res_cont_2.time; + // this is not a contradiction to the documentation + // the documentation says: + // "A label $l_1$ dominates a label $l_2$ if and only if both are resident + // at the same vertex, and if, for each resource, the resource consumption + // of $l_1$ is less than or equal to the resource consumption of $l_2$, + // and if there is at least one resource where $l_1$ has a lower resource + // consumption than $l_2$." + // one can think of a new label with a resource consumption equal to that + // of an old label as being dominated by that old label, because the new + // one will have a higher number and is created at a later point in time, + // so one can implicitly use the number or the creation time as a resource + // for tie-breaking + } +}; +// end data structures for shortest path problem with time windows (spptw) + +int test_main(int argc, char* argv[]) +{ + SPPRC_Example_Graph g; + add_vertex( SPPRC_Example_Graph_Vert_Prop( 0, 0, 1000000000 ), g ); + add_vertex( SPPRC_Example_Graph_Vert_Prop( 1, 56, 142 ), g ); + add_vertex( SPPRC_Example_Graph_Vert_Prop( 2, 0, 1000000000 ), g ); + add_vertex( SPPRC_Example_Graph_Vert_Prop( 3, 89, 178 ), g ); + add_vertex( SPPRC_Example_Graph_Vert_Prop( 4, 0, 1000000000 ), g ); + add_vertex( SPPRC_Example_Graph_Vert_Prop( 5, 49, 76 ), g ); + add_vertex( SPPRC_Example_Graph_Vert_Prop( 6, 0, 1000000000 ), g ); + add_vertex( SPPRC_Example_Graph_Vert_Prop( 7, 98, 160 ), g ); + add_vertex( SPPRC_Example_Graph_Vert_Prop( 8, 0, 1000000000 ), g ); + add_vertex( SPPRC_Example_Graph_Vert_Prop( 9, 90, 158 ), g ); + add_edge( 0, 7, SPPRC_Example_Graph_Arc_Prop( 6, 33, 2 ), g ); + add_edge( 0, 6, SPPRC_Example_Graph_Arc_Prop( 5, 31, 6 ), g ); + add_edge( 0, 4, SPPRC_Example_Graph_Arc_Prop( 3, 14, 4 ), g ); + add_edge( 0, 1, SPPRC_Example_Graph_Arc_Prop( 0, 43, 8 ), g ); + add_edge( 0, 4, SPPRC_Example_Graph_Arc_Prop( 4, 28, 10 ), g ); + add_edge( 0, 3, SPPRC_Example_Graph_Arc_Prop( 1, 31, 10 ), g ); + add_edge( 0, 3, SPPRC_Example_Graph_Arc_Prop( 2, 1, 7 ), g ); + add_edge( 0, 9, SPPRC_Example_Graph_Arc_Prop( 7, 25, 9 ), g ); + add_edge( 1, 0, SPPRC_Example_Graph_Arc_Prop( 8, 37, 4 ), g ); + add_edge( 1, 6, SPPRC_Example_Graph_Arc_Prop( 9, 7, 3 ), g ); + add_edge( 2, 6, SPPRC_Example_Graph_Arc_Prop( 12, 6, 7 ), g ); + add_edge( 2, 3, SPPRC_Example_Graph_Arc_Prop( 10, 13, 7 ), g ); + add_edge( 2, 3, SPPRC_Example_Graph_Arc_Prop( 11, 49, 9 ), g ); + add_edge( 2, 8, SPPRC_Example_Graph_Arc_Prop( 13, 47, 5 ), g ); + add_edge( 3, 4, SPPRC_Example_Graph_Arc_Prop( 17, 5, 10 ), g ); + add_edge( 3, 1, SPPRC_Example_Graph_Arc_Prop( 15, 47, 1 ), g ); + add_edge( 3, 2, SPPRC_Example_Graph_Arc_Prop( 16, 26, 9 ), g ); + add_edge( 3, 9, SPPRC_Example_Graph_Arc_Prop( 21, 24, 10 ), g ); + add_edge( 3, 7, SPPRC_Example_Graph_Arc_Prop( 20, 50, 10 ), g ); + add_edge( 3, 0, SPPRC_Example_Graph_Arc_Prop( 14, 41, 4 ), g ); + add_edge( 3, 6, SPPRC_Example_Graph_Arc_Prop( 19, 6, 1 ), g ); + add_edge( 3, 4, SPPRC_Example_Graph_Arc_Prop( 18, 8, 1 ), g ); + add_edge( 4, 5, SPPRC_Example_Graph_Arc_Prop( 26, 38, 4 ), g ); + add_edge( 4, 9, SPPRC_Example_Graph_Arc_Prop( 27, 32, 10 ), g ); + add_edge( 4, 3, SPPRC_Example_Graph_Arc_Prop( 24, 40, 3 ), g ); + add_edge( 4, 0, SPPRC_Example_Graph_Arc_Prop( 22, 7, 3 ), g ); + add_edge( 4, 3, SPPRC_Example_Graph_Arc_Prop( 25, 28, 9 ), g ); + add_edge( 4, 2, SPPRC_Example_Graph_Arc_Prop( 23, 39, 6 ), g ); + add_edge( 5, 8, SPPRC_Example_Graph_Arc_Prop( 32, 6, 2 ), g ); + add_edge( 5, 2, SPPRC_Example_Graph_Arc_Prop( 30, 26, 10 ), g ); + add_edge( 5, 0, SPPRC_Example_Graph_Arc_Prop( 28, 38, 9 ), g ); + add_edge( 5, 2, SPPRC_Example_Graph_Arc_Prop( 31, 48, 10 ), g ); + add_edge( 5, 9, SPPRC_Example_Graph_Arc_Prop( 33, 49, 2 ), g ); + add_edge( 5, 1, SPPRC_Example_Graph_Arc_Prop( 29, 22, 7 ), g ); + add_edge( 6, 1, SPPRC_Example_Graph_Arc_Prop( 34, 15, 7 ), g ); + add_edge( 6, 7, SPPRC_Example_Graph_Arc_Prop( 35, 20, 3 ), g ); + add_edge( 7, 9, SPPRC_Example_Graph_Arc_Prop( 40, 1, 3 ), g ); + add_edge( 7, 0, SPPRC_Example_Graph_Arc_Prop( 36, 23, 5 ), g ); + add_edge( 7, 6, SPPRC_Example_Graph_Arc_Prop( 38, 36, 2 ), g ); + add_edge( 7, 6, SPPRC_Example_Graph_Arc_Prop( 39, 18, 10 ), g ); + add_edge( 7, 2, SPPRC_Example_Graph_Arc_Prop( 37, 2, 1 ), g ); + add_edge( 8, 5, SPPRC_Example_Graph_Arc_Prop( 46, 36, 5 ), g ); + add_edge( 8, 1, SPPRC_Example_Graph_Arc_Prop( 42, 13, 10 ), g ); + add_edge( 8, 0, SPPRC_Example_Graph_Arc_Prop( 41, 40, 5 ), g ); + add_edge( 8, 1, SPPRC_Example_Graph_Arc_Prop( 43, 32, 8 ), g ); + add_edge( 8, 6, SPPRC_Example_Graph_Arc_Prop( 47, 25, 1 ), g ); + add_edge( 8, 2, SPPRC_Example_Graph_Arc_Prop( 44, 44, 3 ), g ); + add_edge( 8, 3, SPPRC_Example_Graph_Arc_Prop( 45, 11, 9 ), g ); + add_edge( 9, 0, SPPRC_Example_Graph_Arc_Prop( 48, 41, 5 ), g ); + add_edge( 9, 1, SPPRC_Example_Graph_Arc_Prop( 49, 44, 7 ), g ); + + // spp without resource constraints + + std::vector + ::edge_descriptor> > + opt_solutions; + std::vector pareto_opt_rcs_no_rc; + std::vector i_vec_opt_solutions_spp_no_rc; + //std::cout << "r_c_shortest_paths:" << std::endl; + for( int s = 0; s < 10; ++s ) + { + for( int t = 0; t < 10; ++t ) + { + r_c_shortest_paths + ( g, + get( &SPPRC_Example_Graph_Vert_Prop::num, g ), + get( &SPPRC_Example_Graph_Arc_Prop::num, g ), + s, + t, + opt_solutions, + pareto_opt_rcs_no_rc, + spp_no_rc_res_cont( 0 ), + ref_no_res_cont(), + dominance_no_res_cont(), + std::allocator + >(), + default_r_c_shortest_paths_visitor() ); + i_vec_opt_solutions_spp_no_rc.push_back( pareto_opt_rcs_no_rc[0].cost ); + //std::cout << "From " << s << " to " << t << ": "; + //std::cout << pareto_opt_rcs_no_rc[0].cost << std::endl; + } + } + + //std::vector::vertex_descriptor> + // p( num_vertices( g ) ); + //std::vector d( num_vertices( g ) ); + //std::vector i_vec_dijkstra_distances; + //std::cout << "Dijkstra:" << std::endl; + //for( int s = 0; s < 10; ++s ) + //{ + // dijkstra_shortest_paths( g, + // s, + // &p[0], + // &d[0], + // get( &SPPRC_Example_Graph_Arc_Prop::cost, g ), + // get( &SPPRC_Example_Graph_Vert_Prop::num, g ), + // std::less(), + // closed_plus(), + // (std::numeric_limits::max)(), + // 0, + // default_dijkstra_visitor() ); + // for( int t = 0; t < 10; ++t ) + // { + // i_vec_dijkstra_distances.push_back( d[t] ); + // std::cout << "From " << s << " to " << t << ": " << d[t] << std::endl; + // } + //} + + std::vector i_vec_correct_solutions; + i_vec_correct_solutions.push_back( 0 ); + i_vec_correct_solutions.push_back( 22 ); + i_vec_correct_solutions.push_back( 27 ); + i_vec_correct_solutions.push_back( 1 ); + i_vec_correct_solutions.push_back( 6 ); + i_vec_correct_solutions.push_back( 44 ); + i_vec_correct_solutions.push_back( 7 ); + i_vec_correct_solutions.push_back( 27 ); + i_vec_correct_solutions.push_back( 50 ); + i_vec_correct_solutions.push_back( 25 ); + i_vec_correct_solutions.push_back( 37 ); + i_vec_correct_solutions.push_back( 0 ); + i_vec_correct_solutions.push_back( 29 ); + i_vec_correct_solutions.push_back( 38 ); + i_vec_correct_solutions.push_back( 43 ); + i_vec_correct_solutions.push_back( 81 ); + i_vec_correct_solutions.push_back( 7 ); + i_vec_correct_solutions.push_back( 27 ); + i_vec_correct_solutions.push_back( 76 ); + i_vec_correct_solutions.push_back( 28 ); + i_vec_correct_solutions.push_back( 25 ); + i_vec_correct_solutions.push_back( 21 ); + i_vec_correct_solutions.push_back( 0 ); + i_vec_correct_solutions.push_back( 13 ); + i_vec_correct_solutions.push_back( 18 ); + i_vec_correct_solutions.push_back( 56 ); + i_vec_correct_solutions.push_back( 6 ); + i_vec_correct_solutions.push_back( 26 ); + i_vec_correct_solutions.push_back( 47 ); + i_vec_correct_solutions.push_back( 27 ); + i_vec_correct_solutions.push_back( 12 ); + i_vec_correct_solutions.push_back( 21 ); + i_vec_correct_solutions.push_back( 26 ); + i_vec_correct_solutions.push_back( 0 ); + i_vec_correct_solutions.push_back( 5 ); + i_vec_correct_solutions.push_back( 43 ); + i_vec_correct_solutions.push_back( 6 ); + i_vec_correct_solutions.push_back( 26 ); + i_vec_correct_solutions.push_back( 49 ); + i_vec_correct_solutions.push_back( 24 ); + i_vec_correct_solutions.push_back( 7 ); + i_vec_correct_solutions.push_back( 29 ); + i_vec_correct_solutions.push_back( 34 ); + i_vec_correct_solutions.push_back( 8 ); + i_vec_correct_solutions.push_back( 0 ); + i_vec_correct_solutions.push_back( 38 ); + i_vec_correct_solutions.push_back( 14 ); + i_vec_correct_solutions.push_back( 34 ); + i_vec_correct_solutions.push_back( 44 ); + i_vec_correct_solutions.push_back( 32 ); + i_vec_correct_solutions.push_back( 29 ); + i_vec_correct_solutions.push_back( 19 ); + i_vec_correct_solutions.push_back( 26 ); + i_vec_correct_solutions.push_back( 17 ); + i_vec_correct_solutions.push_back( 22 ); + i_vec_correct_solutions.push_back( 0 ); + i_vec_correct_solutions.push_back( 23 ); + i_vec_correct_solutions.push_back( 43 ); + i_vec_correct_solutions.push_back( 6 ); + i_vec_correct_solutions.push_back( 41 ); + i_vec_correct_solutions.push_back( 43 ); + i_vec_correct_solutions.push_back( 15 ); + i_vec_correct_solutions.push_back( 22 ); + i_vec_correct_solutions.push_back( 35 ); + i_vec_correct_solutions.push_back( 40 ); + i_vec_correct_solutions.push_back( 78 ); + i_vec_correct_solutions.push_back( 0 ); + i_vec_correct_solutions.push_back( 20 ); + i_vec_correct_solutions.push_back( 69 ); + i_vec_correct_solutions.push_back( 21 ); + i_vec_correct_solutions.push_back( 23 ); + i_vec_correct_solutions.push_back( 23 ); + i_vec_correct_solutions.push_back( 2 ); + i_vec_correct_solutions.push_back( 15 ); + i_vec_correct_solutions.push_back( 20 ); + i_vec_correct_solutions.push_back( 58 ); + i_vec_correct_solutions.push_back( 8 ); + i_vec_correct_solutions.push_back( 0 ); + i_vec_correct_solutions.push_back( 49 ); + i_vec_correct_solutions.push_back( 1 ); + i_vec_correct_solutions.push_back( 23 ); + i_vec_correct_solutions.push_back( 13 ); + i_vec_correct_solutions.push_back( 37 ); + i_vec_correct_solutions.push_back( 11 ); + i_vec_correct_solutions.push_back( 16 ); + i_vec_correct_solutions.push_back( 36 ); + i_vec_correct_solutions.push_back( 17 ); + i_vec_correct_solutions.push_back( 37 ); + i_vec_correct_solutions.push_back( 0 ); + i_vec_correct_solutions.push_back( 35 ); + i_vec_correct_solutions.push_back( 41 ); + i_vec_correct_solutions.push_back( 44 ); + i_vec_correct_solutions.push_back( 68 ); + i_vec_correct_solutions.push_back( 42 ); + i_vec_correct_solutions.push_back( 47 ); + i_vec_correct_solutions.push_back( 85 ); + i_vec_correct_solutions.push_back( 48 ); + i_vec_correct_solutions.push_back( 68 ); + i_vec_correct_solutions.push_back( 91 ); + i_vec_correct_solutions.push_back( 0 ); + BOOST_CHECK(i_vec_opt_solutions_spp_no_rc.size() == i_vec_correct_solutions.size() ); + for( int i = 0; i < static_cast( i_vec_correct_solutions.size() ); ++i ) + BOOST_CHECK( i_vec_opt_solutions_spp_no_rc[i] == i_vec_correct_solutions[i] ); + + // spptw + std::vector + ::edge_descriptor> > + opt_solutions_spptw; + std::vector pareto_opt_rcs_spptw; + std::vector + ::edge_descriptor> > > > + vec_vec_vec_vec_opt_solutions_spptw( 10 ); + + for( int s = 0; s < 10; ++s ) + { + for( int t = 0; t < 10; ++t ) + { + r_c_shortest_paths + ( g, + get( &SPPRC_Example_Graph_Vert_Prop::num, g ), + get( &SPPRC_Example_Graph_Arc_Prop::num, g ), + s, + t, + opt_solutions_spptw, + pareto_opt_rcs_spptw, + // be careful, do not simply take 0 as initial value for time + spp_spptw_res_cont( 0, g[s].eat ), + ref_spptw(), + dominance_spptw(), + std::allocator + >(), + default_r_c_shortest_paths_visitor() ); + vec_vec_vec_vec_opt_solutions_spptw[s].push_back( opt_solutions_spptw ); + if( opt_solutions_spptw.size() ) + { + bool b_is_a_path_at_all = false; + bool b_feasible = false; + bool b_correctly_extended = false; + spp_spptw_res_cont actual_final_resource_levels( 0, 0 ); + graph_traits::edge_descriptor ed_last_extended_arc; + check_r_c_path( g, + opt_solutions_spptw[0], + spp_spptw_res_cont( 0, g[s].eat ), + true, + pareto_opt_rcs_spptw[0], + actual_final_resource_levels, + ref_spptw(), + b_is_a_path_at_all, + b_feasible, + b_correctly_extended, + ed_last_extended_arc ); + BOOST_CHECK(b_is_a_path_at_all && b_feasible && b_correctly_extended); + b_is_a_path_at_all = false; + b_feasible = false; + b_correctly_extended = false; + spp_spptw_res_cont actual_final_resource_levels2( 0, 0 ); + graph_traits::edge_descriptor ed_last_extended_arc2; + check_r_c_path( g, + opt_solutions_spptw[0], + spp_spptw_res_cont( 0, g[s].eat ), + false, + pareto_opt_rcs_spptw[0], + actual_final_resource_levels2, + ref_spptw(), + b_is_a_path_at_all, + b_feasible, + b_correctly_extended, + ed_last_extended_arc2 ); + BOOST_CHECK(b_is_a_path_at_all && b_feasible && b_correctly_extended); + } + } + } + + std::vector i_vec_correct_num_solutions_spptw; + i_vec_correct_num_solutions_spptw.push_back( 1 ); + i_vec_correct_num_solutions_spptw.push_back( 2 ); + i_vec_correct_num_solutions_spptw.push_back( 3 ); + i_vec_correct_num_solutions_spptw.push_back( 1 ); + i_vec_correct_num_solutions_spptw.push_back( 3 ); + i_vec_correct_num_solutions_spptw.push_back( 1 ); + i_vec_correct_num_solutions_spptw.push_back( 2 ); + i_vec_correct_num_solutions_spptw.push_back( 1 ); + i_vec_correct_num_solutions_spptw.push_back( 2 ); + i_vec_correct_num_solutions_spptw.push_back( 1 ); + i_vec_correct_num_solutions_spptw.push_back( 1 ); + i_vec_correct_num_solutions_spptw.push_back( 1 ); + i_vec_correct_num_solutions_spptw.push_back( 4 ); + i_vec_correct_num_solutions_spptw.push_back( 1 ); + i_vec_correct_num_solutions_spptw.push_back( 3 ); + i_vec_correct_num_solutions_spptw.push_back( 1 ); + i_vec_correct_num_solutions_spptw.push_back( 1 ); + i_vec_correct_num_solutions_spptw.push_back( 1 ); + i_vec_correct_num_solutions_spptw.push_back( 2 ); + i_vec_correct_num_solutions_spptw.push_back( 2 ); + i_vec_correct_num_solutions_spptw.push_back( 4 ); + i_vec_correct_num_solutions_spptw.push_back( 1 ); + i_vec_correct_num_solutions_spptw.push_back( 1 ); + i_vec_correct_num_solutions_spptw.push_back( 1 ); + i_vec_correct_num_solutions_spptw.push_back( 4 ); + i_vec_correct_num_solutions_spptw.push_back( 1 ); + i_vec_correct_num_solutions_spptw.push_back( 2 ); + i_vec_correct_num_solutions_spptw.push_back( 1 ); + i_vec_correct_num_solutions_spptw.push_back( 1 ); + i_vec_correct_num_solutions_spptw.push_back( 3 ); + i_vec_correct_num_solutions_spptw.push_back( 2 ); + i_vec_correct_num_solutions_spptw.push_back( 2 ); + i_vec_correct_num_solutions_spptw.push_back( 2 ); + i_vec_correct_num_solutions_spptw.push_back( 1 ); + i_vec_correct_num_solutions_spptw.push_back( 2 ); + i_vec_correct_num_solutions_spptw.push_back( 0 ); + i_vec_correct_num_solutions_spptw.push_back( 1 ); + i_vec_correct_num_solutions_spptw.push_back( 1 ); + i_vec_correct_num_solutions_spptw.push_back( 2 ); + i_vec_correct_num_solutions_spptw.push_back( 1 ); + i_vec_correct_num_solutions_spptw.push_back( 1 ); + i_vec_correct_num_solutions_spptw.push_back( 2 ); + i_vec_correct_num_solutions_spptw.push_back( 2 ); + i_vec_correct_num_solutions_spptw.push_back( 1 ); + i_vec_correct_num_solutions_spptw.push_back( 1 ); + i_vec_correct_num_solutions_spptw.push_back( 1 ); + i_vec_correct_num_solutions_spptw.push_back( 2 ); + i_vec_correct_num_solutions_spptw.push_back( 1 ); + i_vec_correct_num_solutions_spptw.push_back( 2 ); + i_vec_correct_num_solutions_spptw.push_back( 1 ); + i_vec_correct_num_solutions_spptw.push_back( 4 ); + i_vec_correct_num_solutions_spptw.push_back( 2 ); + i_vec_correct_num_solutions_spptw.push_back( 2 ); + i_vec_correct_num_solutions_spptw.push_back( 1 ); + i_vec_correct_num_solutions_spptw.push_back( 4 ); + i_vec_correct_num_solutions_spptw.push_back( 1 ); + i_vec_correct_num_solutions_spptw.push_back( 4 ); + i_vec_correct_num_solutions_spptw.push_back( 1 ); + i_vec_correct_num_solutions_spptw.push_back( 1 ); + i_vec_correct_num_solutions_spptw.push_back( 2 ); + i_vec_correct_num_solutions_spptw.push_back( 2 ); + i_vec_correct_num_solutions_spptw.push_back( 1 ); + i_vec_correct_num_solutions_spptw.push_back( 4 ); + i_vec_correct_num_solutions_spptw.push_back( 2 ); + i_vec_correct_num_solutions_spptw.push_back( 5 ); + i_vec_correct_num_solutions_spptw.push_back( 1 ); + i_vec_correct_num_solutions_spptw.push_back( 1 ); + i_vec_correct_num_solutions_spptw.push_back( 1 ); + i_vec_correct_num_solutions_spptw.push_back( 2 ); + i_vec_correct_num_solutions_spptw.push_back( 2 ); + i_vec_correct_num_solutions_spptw.push_back( 1 ); + i_vec_correct_num_solutions_spptw.push_back( 3 ); + i_vec_correct_num_solutions_spptw.push_back( 1 ); + i_vec_correct_num_solutions_spptw.push_back( 1 ); + i_vec_correct_num_solutions_spptw.push_back( 2 ); + i_vec_correct_num_solutions_spptw.push_back( 0 ); + i_vec_correct_num_solutions_spptw.push_back( 2 ); + i_vec_correct_num_solutions_spptw.push_back( 1 ); + i_vec_correct_num_solutions_spptw.push_back( 1 ); + i_vec_correct_num_solutions_spptw.push_back( 1 ); + i_vec_correct_num_solutions_spptw.push_back( 3 ); + i_vec_correct_num_solutions_spptw.push_back( 1 ); + i_vec_correct_num_solutions_spptw.push_back( 2 ); + i_vec_correct_num_solutions_spptw.push_back( 1 ); + i_vec_correct_num_solutions_spptw.push_back( 3 ); + i_vec_correct_num_solutions_spptw.push_back( 1 ); + i_vec_correct_num_solutions_spptw.push_back( 3 ); + i_vec_correct_num_solutions_spptw.push_back( 1 ); + i_vec_correct_num_solutions_spptw.push_back( 1 ); + i_vec_correct_num_solutions_spptw.push_back( 2 ); + i_vec_correct_num_solutions_spptw.push_back( 1 ); + i_vec_correct_num_solutions_spptw.push_back( 1 ); + i_vec_correct_num_solutions_spptw.push_back( 4 ); + i_vec_correct_num_solutions_spptw.push_back( 1 ); + i_vec_correct_num_solutions_spptw.push_back( 3 ); + i_vec_correct_num_solutions_spptw.push_back( 0 ); + i_vec_correct_num_solutions_spptw.push_back( 2 ); + i_vec_correct_num_solutions_spptw.push_back( 3 ); + i_vec_correct_num_solutions_spptw.push_back( 4 ); + i_vec_correct_num_solutions_spptw.push_back( 1 ); + for( int s = 0; s < 10; ++s ) + for( int t = 0; t < 10; ++t ) + BOOST_CHECK( static_cast + ( vec_vec_vec_vec_opt_solutions_spptw[s][t].size() ) == + i_vec_correct_num_solutions_spptw[10 * s + t] ); + + // one pareto-optimal solution + SPPRC_Example_Graph g2; + add_vertex( SPPRC_Example_Graph_Vert_Prop( 0, 0, 1000000000 ), g2 ); + add_vertex( SPPRC_Example_Graph_Vert_Prop( 1, 0, 1000000000 ), g2 ); + add_vertex( SPPRC_Example_Graph_Vert_Prop( 2, 0, 1000000000 ), g2 ); + add_vertex( SPPRC_Example_Graph_Vert_Prop( 3, 0, 1000000000 ), g2 ); + add_edge( 0, 1, SPPRC_Example_Graph_Arc_Prop( 0, 1, 1 ), g2 ); + add_edge( 0, 2, SPPRC_Example_Graph_Arc_Prop( 1, 2, 1 ), g2 ); + add_edge( 1, 3, SPPRC_Example_Graph_Arc_Prop( 2, 3, 1 ), g2 ); + add_edge( 2, 3, SPPRC_Example_Graph_Arc_Prop( 3, 1, 1 ), g2 ); + std::vector::edge_descriptor> opt_solution; + spp_spptw_res_cont pareto_opt_rc; + r_c_shortest_paths( g2, + get( &SPPRC_Example_Graph_Vert_Prop::num, g2 ), + get( &SPPRC_Example_Graph_Arc_Prop::num, g2 ), + 0, + 3, + opt_solution, + pareto_opt_rc, + spp_spptw_res_cont( 0, 0 ), + ref_spptw(), + dominance_spptw(), + std::allocator + >(), + default_r_c_shortest_paths_visitor() ); + + BOOST_CHECK(pareto_opt_rc.cost == 3); + + return 0; +} From ccf09ceddfd3d6feff094d2f3eb8892322b3c8ef Mon Sep 17 00:00:00 2001 From: Douglas Gregor Date: Tue, 29 Apr 2008 18:18:01 +0000 Subject: [PATCH 008/224] Remove names of unused variables. Fixes #1832 and fixes #1865 [SVN r44889] --- include/boost/graph/dijkstra_shortest_paths.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/boost/graph/dijkstra_shortest_paths.hpp b/include/boost/graph/dijkstra_shortest_paths.hpp index ef6b824c..243b17f7 100644 --- a/include/boost/graph/dijkstra_shortest_paths.hpp +++ b/include/boost/graph/dijkstra_shortest_paths.hpp @@ -109,7 +109,7 @@ namespace boost { } template - void initialize_vertex(Vertex u, Graph& g) { } + void initialize_vertex(Vertex /*u*/, Graph& /*g*/) { } template void non_tree_edge(Edge, Graph&) { } template From b98298ab981e3af1abd0800260d0f47dc7c24724 Mon Sep 17 00:00:00 2001 From: Douglas Gregor Date: Tue, 29 Apr 2008 18:34:28 +0000 Subject: [PATCH 009/224] Correct erroneous call to is_reachable from is_connected. Fixes #870 [SVN r44891] --- include/boost/graph/graph_utility.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/boost/graph/graph_utility.hpp b/include/boost/graph/graph_utility.hpp index a5791561..018442b9 100644 --- a/include/boost/graph/graph_utility.hpp +++ b/include/boost/graph/graph_utility.hpp @@ -385,7 +385,7 @@ namespace boost { if (*ui != *vi) { for (tie(ci, ci_end) = vertices(g); ci != ci_end; ++ci) put(color, *ci, Color::white()); - if (! is_reachable(*ui, *vi, color)) + if (! is_reachable(*ui, *vi, g, color)) return false; } return true; From c6c6be7ae05b3a893cdd02f623ed769fa750745b Mon Sep 17 00:00:00 2001 From: Daniel James Date: Sun, 11 May 2008 13:49:20 +0000 Subject: [PATCH 010/224] Quote href values - our tools don't support unquoted values. [SVN r45283] --- doc/BFSVisitor.html | 2 +- doc/BellmanFordVisitor.html | 2 +- doc/ColorValue.html | 2 +- doc/DFSVisitor.html | 2 +- doc/DijkstraVisitor.html | 2 +- doc/EventVisitor.html | 2 +- doc/EventVisitorList.html | 2 +- doc/IncidenceGraph.html | 2 +- doc/IteratorConstructibleGraph.html | 2 +- doc/Monoid.html | 2 +- doc/acknowledgements.html | 2 +- doc/adjacency_list.html | 2 +- doc/adjacency_list_traits.html | 2 +- doc/bellman_visitor.html | 2 +- doc/betweenness_centrality.html | 2 +- doc/bfs_visitor.html | 2 +- doc/bgl_named_params.html | 2 +- doc/circle_layout.html | 2 +- doc/compressed_sparse_row.html | 8 ++++---- doc/constructing_algorithms.html | 2 +- doc/depth_first_search.html | 2 +- doc/dfs_visitor.html | 2 +- doc/dijkstra_visitor.html | 2 +- doc/distance_recorder.html | 2 +- doc/edge_list.html | 2 +- doc/erdos_renyi_generator.html | 2 +- doc/filtered_graph.html | 2 +- doc/graph_coloring.html | 2 +- doc/graph_traits.html | 2 +- doc/gursoy_atun_layout.html | 2 +- doc/history.html | 2 +- doc/incident.html | 2 +- doc/incremental_components.html | 2 +- doc/index.html | 2 +- doc/known_problems.html | 2 +- doc/leda_conversion.html | 2 +- doc/null_visitor.html | 2 +- doc/opposite.html | 2 +- doc/plod_generator.html | 2 +- doc/predecessor_recorder.html | 2 +- doc/property_map.html | 2 +- doc/property_writer.html | 2 +- doc/publications.html | 2 +- doc/python.html | 2 +- doc/sequential_vertex_coloring.html | 2 +- doc/small_world_generator.html | 2 +- doc/sorted_erdos_renyi_gen.html | 2 +- doc/stanford_graph.html | 2 +- doc/table_of_contents.html | 2 +- doc/time_stamper.html | 2 +- doc/trouble_shooting.html | 2 +- doc/undirected_dfs.html | 2 +- doc/visitor_concepts.html | 2 +- 53 files changed, 56 insertions(+), 56 deletions(-) diff --git a/doc/BFSVisitor.html b/doc/BFSVisitor.html index 326d3654..2d6fc3d7 100644 --- a/doc/BFSVisitor.html +++ b/doc/BFSVisitor.html @@ -211,7 +211,7 @@ class count_tree_edges_bfs_visitor(bgl.Graph.BFSVisitor): Indiana University (jsiek@osl.iu.edu)
          Lie-Quan Lee, Indiana University (llee@cs.indiana.edu)
          -Andrew Lumsdaine, +Andrew Lumsdaine, Indiana University (lums@osl.iu.edu)
    diff --git a/doc/BellmanFordVisitor.html b/doc/BellmanFordVisitor.html index 40b2b425..c49992b9 100644 --- a/doc/BellmanFordVisitor.html +++ b/doc/BellmanFordVisitor.html @@ -175,7 +175,7 @@ class count_tree_edges_bellman_ford_visitor(bgl.Graph.BellmanFordVisitor): Indiana University (
    jsiek@osl.iu.edu)
    Lie-Quan Lee, Indiana University (llee@cs.indiana.edu)
    -Andrew Lumsdaine, +Andrew Lumsdaine, Indiana University (lums@osl.iu.edu)
    diff --git a/doc/ColorValue.html b/doc/ColorValue.html index 090d039e..4e3111b3 100644 --- a/doc/ColorValue.html +++ b/doc/ColorValue.html @@ -99,7 +99,7 @@ href="http://www.sgi.com/tech/stl/DefaultConstructible.html">DefaultConstructibl Indiana University (jsiek@osl.iu.edu)
    Lie-Quan Lee, Indiana University (llee@cs.indiana.edu)
    -Andrew Lumsdaine, +Andrew Lumsdaine, Indiana University (lums@osl.iu.edu)
    diff --git a/doc/DFSVisitor.html b/doc/DFSVisitor.html index 1242f520..99784844 100644 --- a/doc/DFSVisitor.html +++ b/doc/DFSVisitor.html @@ -203,7 +203,7 @@ class count_tree_edges_dfs_visitor(bgl.Graph.DFSVisitor): Indiana University (jsiek@osl.iu.edu)
    Lie-Quan Lee, Indiana University (llee@cs.indiana.edu)
    -Andrew Lumsdaine, +Andrew Lumsdaine, Indiana University (lums@osl.iu.edu)
    diff --git a/doc/DijkstraVisitor.html b/doc/DijkstraVisitor.html index 4b889b89..c504cb71 100644 --- a/doc/DijkstraVisitor.html +++ b/doc/DijkstraVisitor.html @@ -213,7 +213,7 @@ class count_tree_edges_dijkstra_visitor(bgl.Graph.DijkstraVisitor): Indiana University (jsiek@osl.iu.edu)
    Lie-Quan Lee, Indiana University (llee@cs.indiana.edu)
    -Andrew Lumsdaine, +Andrew Lumsdaine, Indiana University (lums@osl.iu.edu)
    diff --git a/doc/EventVisitor.html b/doc/EventVisitor.html index efb0c70c..10cf6407 100644 --- a/doc/EventVisitor.html +++ b/doc/EventVisitor.html @@ -152,7 +152,7 @@ either a vertex or edge descriptor of the graph. Indiana University (jsiek@osl.iu.edu)
    Lie-Quan Lee, Indiana University (llee@cs.indiana.edu)
    -Andrew Lumsdaine, +Andrew Lumsdaine, Indiana University (lums@osl.iu.edu)
    diff --git a/doc/EventVisitorList.html b/doc/EventVisitorList.html index 3cb03bd6..070d391f 100644 --- a/doc/EventVisitorList.html +++ b/doc/EventVisitorList.html @@ -118,7 +118,7 @@ std::make_pair(visitor1, Indiana University (jsiek@osl.iu.edu)
    Lie-Quan Lee, Indiana University (llee@cs.indiana.edu)
    -Andrew Lumsdaine, +Andrew Lumsdaine, Indiana University (lums@osl.iu.edu)
    diff --git a/doc/IncidenceGraph.html b/doc/IncidenceGraph.html index a1ab72c8..069b9371 100644 --- a/doc/IncidenceGraph.html +++ b/doc/IncidenceGraph.html @@ -193,7 +193,7 @@ Therefore, the extra requirement is added that the out-edge connecting Indiana University (jsiek@osl.iu.edu)
    Lie-Quan Lee, Indiana University (llee@cs.indiana.edu)
    -Andrew Lumsdaine, +Andrew Lumsdaine, Indiana University (lums@osl.iu.edu)
    diff --git a/doc/IteratorConstructibleGraph.html b/doc/IteratorConstructibleGraph.html index 55982585..901452eb 100644 --- a/doc/IteratorConstructibleGraph.html +++ b/doc/IteratorConstructibleGraph.html @@ -152,7 +152,7 @@ constructor lacking the graph size information. Indiana University (jsiek@osl.iu.edu)
    Lie-Quan Lee, Indiana University (llee@cs.indiana.edu)
    -Andrew Lumsdaine, +Andrew Lumsdaine, Indiana University (lums@osl.iu.edu)
    diff --git a/doc/Monoid.html b/doc/Monoid.html index ba2366fb..c0898b70 100644 --- a/doc/Monoid.html +++ b/doc/Monoid.html @@ -113,7 +113,7 @@ Return type: bool Indiana University (jsiek@osl.iu.edu)
    Lie-Quan Lee, Indiana University (llee@cs.indiana.edu)
    -Andrew Lumsdaine, +Andrew Lumsdaine, Indiana University (lums@osl.iu.edu)
    diff --git a/doc/acknowledgements.html b/doc/acknowledgements.html index 7c827689..16f3af7e 100644 --- a/doc/acknowledgements.html +++ b/doc/acknowledgements.html @@ -67,7 +67,7 @@ Science of the U.S. Department of Energy. Indiana University (jsiek@osl.iu.edu)
    Lie-Quan Lee, Indiana University (llee@cs.indiana.edu)
    -Andrew Lumsdaine, +Andrew Lumsdaine, Indiana University (lums@osl.iu.edu)
    diff --git a/doc/adjacency_list.html b/doc/adjacency_list.html index ef626e33..16de125c 100644 --- a/doc/adjacency_list.html +++ b/doc/adjacency_list.html @@ -1104,7 +1104,7 @@ Include boost/graph/ad Indiana University (jsiek@osl.iu.edu)
    Lie-Quan Lee, Indiana University (llee@cs.indiana.edu)
    -Andrew Lumsdaine, +Andrew Lumsdaine, Indiana University (lums@osl.iu.edu)
    diff --git a/doc/adjacency_list_traits.html b/doc/adjacency_list_traits.html index 6b38c3e0..14f60063 100644 --- a/doc/adjacency_list_traits.html +++ b/doc/adjacency_list_traits.html @@ -149,7 +149,7 @@ parallel edges (disallow_parallel_edge_tag). Indiana University (jsiek@osl.iu.edu)
    Lie-Quan Lee, Indiana University (llee@cs.indiana.edu)
    -Andrew Lumsdaine, +Andrew Lumsdaine, Indiana University (lums@osl.iu.edu)
    diff --git a/doc/bellman_visitor.html b/doc/bellman_visitor.html index 1259cd78..a5dfe9bf 100644 --- a/doc/bellman_visitor.html +++ b/doc/bellman_visitor.html @@ -102,7 +102,7 @@ and property_writer. Indiana University (jsiek@osl.iu.edu)
    Lie-Quan Lee, Indiana University (llee@cs.indiana.edu)
    -Andrew Lumsdaine, +Andrew Lumsdaine, Indiana University (lums@osl.iu.edu)
    diff --git a/doc/betweenness_centrality.html b/doc/betweenness_centrality.html index 47731524..cc3741e0 100644 --- a/doc/betweenness_centrality.html +++ b/doc/betweenness_centrality.html @@ -297,7 +297,7 @@ is O(VE).
    Copyright © 2004 Douglas Gregor, Indiana University (dgregor@cs.indiana.edu)
    -Andrew Lumsdaine, +Andrew Lumsdaine, Indiana University (lums@osl.iu.edu)
    diff --git a/doc/bfs_visitor.html b/doc/bfs_visitor.html index 9bf31938..d38f9a1a 100644 --- a/doc/bfs_visitor.html +++ b/doc/bfs_visitor.html @@ -119,7 +119,7 @@ and property_writer. Indiana University (jsiek@osl.iu.edu)
    Lie-Quan Lee, Indiana University (llee@cs.indiana.edu)
    -Andrew Lumsdaine, +Andrew Lumsdaine, Indiana University (lums@osl.iu.edu)
    diff --git a/doc/bgl_named_params.html b/doc/bgl_named_params.html index 2e9635b5..282e0c82 100644 --- a/doc/bgl_named_params.html +++ b/doc/bgl_named_params.html @@ -87,7 +87,7 @@ like boost::weight_map that create an instance of Indiana University (jsiek@osl.iu.edu)
    Lie-Quan Lee, Indiana University (llee@cs.indiana.edu)
    -Andrew Lumsdaine, +Andrew Lumsdaine, Indiana University (lums@osl.iu.edu)
    diff --git a/doc/circle_layout.html b/doc/circle_layout.html index 109d84c1..eceffa91 100644 --- a/doc/circle_layout.html +++ b/doc/circle_layout.html @@ -45,7 +45,7 @@ IN: Radius radius
    Copyright © 2004 Douglas Gregor, Indiana University (dgregor -at- cs.indiana.edu)
    -Andrew Lumsdaine, +Andrew Lumsdaine, Indiana University (lums -at- osl.iu.edu)
    diff --git a/doc/compressed_sparse_row.html b/doc/compressed_sparse_row.html index 9eedf0b3..1ed2639a 100644 --- a/doc/compressed_sparse_row.html +++ b/doc/compressed_sparse_row.html @@ -204,13 +204,13 @@ void set_property(const compressed_sparse_row_graph& // Incremental construction functions template<typename Graph> -vertex_descriptor add_vertex(compressed_sparse_row_graph& g); +vertex_descriptor add_vertex(compressed_sparse_row_graph& g); template<typename Graph> -vertex_descriptor add_vertices(vertices_size_type count, compressed_sparse_row_graph& g); +vertex_descriptor add_vertices(vertices_size_type count, compressed_sparse_row_graph& g); template<typename Graph> -edge_descriptor add_vertices(vertex_descriptor src, vertex_descriptor tgt, compressed_sparse_row_graph& g); +edge_descriptor add_vertices(vertex_descriptor src, vertex_descriptor tgt, compressed_sparse_row_graph& g); } // end namespace boost @@ -713,7 +713,7 @@ BGL_FORALL_EDGES(e, g, WebGraph)
    Copyright © 2005 Doug Gregor, Indiana University ()
    Jeremiah Willcock, Indiana University ()
    - Andrew Lumsdaine, + Andrew Lumsdaine, Indiana University ()
    diff --git a/doc/constructing_algorithms.html b/doc/constructing_algorithms.html index 14c33674..968df19c 100644 --- a/doc/constructing_algorithms.html +++ b/doc/constructing_algorithms.html @@ -174,7 +174,7 @@ namespace boost { Indiana University (
    jsiek@osl.iu.edu)
    Lie-Quan Lee, Indiana University (llee@cs.indiana.edu)
    -Andrew Lumsdaine, +Andrew Lumsdaine, Indiana University (lums@osl.iu.edu)
    diff --git a/doc/depth_first_search.html b/doc/depth_first_search.html index 838420b6..51d4d0fc 100644 --- a/doc/depth_first_search.html +++ b/doc/depth_first_search.html @@ -305,7 +305,7 @@ The example in Indiana University (jsiek@osl.iu.edu)
    Lie-Quan Lee, Indiana University (llee@cs.indiana.edu)
    -Andrew Lumsdaine, +Andrew Lumsdaine, Indiana University (lums@osl.iu.edu)
    diff --git a/doc/dfs_visitor.html b/doc/dfs_visitor.html index 035ff59d..9c87ce34 100644 --- a/doc/dfs_visitor.html +++ b/doc/dfs_visitor.html @@ -102,7 +102,7 @@ and property_writer. Indiana University (jsiek@osl.iu.edu)
    Lie-Quan Lee, Indiana University (llee@cs.indiana.edu)
    -Andrew Lumsdaine, +Andrew Lumsdaine, Indiana University (lums@osl.iu.edu)

    diff --git a/doc/dijkstra_visitor.html b/doc/dijkstra_visitor.html index c238053e..e6d3e146 100644 --- a/doc/dijkstra_visitor.html +++ b/doc/dijkstra_visitor.html @@ -116,7 +116,7 @@ and property_writer. Indiana University (jsiek@osl.iu.edu)
    Lie-Quan Lee, Indiana University (llee@cs.indiana.edu)
    -Andrew Lumsdaine, +Andrew Lumsdaine, Indiana University (lums@osl.iu.edu)
    diff --git a/doc/distance_recorder.html b/doc/distance_recorder.html index f4fe2baf..deaf0b4e 100644 --- a/doc/distance_recorder.html +++ b/doc/distance_recorder.html @@ -167,7 +167,7 @@ and property_writer. Indiana University (jsiek@osl.iu.edu)
    Lie-Quan Lee, Indiana University (llee@cs.indiana.edu)
    -Andrew Lumsdaine, +Andrew Lumsdaine, Indiana University (lums@osl.iu.edu)
    diff --git a/doc/edge_list.html b/doc/edge_list.html index d00e12ba..c1e0f202 100644 --- a/doc/edge_list.html +++ b/doc/edge_list.html @@ -212,7 +212,7 @@ Returns the target vertex of edge e. Indiana University (jsiek@osl.iu.edu)
    Lie-Quan Lee, Indiana University (llee@cs.indiana.edu)
    -Andrew Lumsdaine, +Andrew Lumsdaine, Indiana University (lums@osl.iu.edu)
    diff --git a/doc/erdos_renyi_generator.html b/doc/erdos_renyi_generator.html index 4531437f..6c17bc92 100644 --- a/doc/erdos_renyi_generator.html +++ b/doc/erdos_renyi_generator.html @@ -144,7 +144,7 @@ int main()
    Copyright © 2005 Doug Gregor, Indiana University ()
    - Andrew Lumsdaine, + Andrew Lumsdaine, Indiana University ()
    diff --git a/doc/filtered_graph.html b/doc/filtered_graph.html index 106ea617..296171f7 100644 --- a/doc/filtered_graph.html +++ b/doc/filtered_graph.html @@ -526,7 +526,7 @@ num_edges(g))) which is assumed in many of the algorithms. Indiana University (jsiek@osl.iu.edu)
    Lie-Quan Lee, Indiana University (llee@cs.indiana.edu)
    -Andrew Lumsdaine, +Andrew Lumsdaine, Indiana University (lums@osl.iu.edu)
    diff --git a/doc/graph_coloring.html b/doc/graph_coloring.html index 22ac4471..26d52ecf 100644 --- a/doc/graph_coloring.html +++ b/doc/graph_coloring.html @@ -182,7 +182,7 @@ namespace boost { Indiana University (jsiek@osl.iu.edu)
    Lie-Quan Lee, Indiana University (llee@cs.indiana.edu)
    -Andrew Lumsdaine, +Andrew Lumsdaine, Indiana University (lums@osl.iu.edu)
    diff --git a/doc/graph_traits.html b/doc/graph_traits.html index a5dc4ee6..e0916b0b 100644 --- a/doc/graph_traits.html +++ b/doc/graph_traits.html @@ -243,7 +243,7 @@ of vertices in the graph. Indiana University (
    jsiek@osl.iu.edu)
    Lie-Quan Lee, Indiana University (llee@cs.indiana.edu)
    -Andrew Lumsdaine, +Andrew Lumsdaine, Indiana University (lums@osl.iu.edu)
    diff --git a/doc/gursoy_atun_layout.html b/doc/gursoy_atun_layout.html index 1d8fc0c2..e90fa196 100644 --- a/doc/gursoy_atun_layout.html +++ b/doc/gursoy_atun_layout.html @@ -454,7 +454,7 @@ class heart_topology
    Copyright © 2004 Jeremiah Willcock, Indiana University ()
    Doug Gregor, Indiana University ()
    - Andrew Lumsdaine, + Andrew Lumsdaine, Indiana University ()
    diff --git a/doc/history.html b/doc/history.html index 3f3b3794..0b7bd2d3 100644 --- a/doc/history.html +++ b/doc/history.html @@ -199,7 +199,7 @@ September 27, 2000. Indiana University (jsiek@osl.iu.edu)
    Lie-Quan Lee, Indiana University (llee@cs.indiana.edu)
    -Andrew Lumsdaine, +Andrew Lumsdaine, Indiana University (lums@osl.iu.edu)
    diff --git a/doc/incident.html b/doc/incident.html index 68cf6c72..421da5f4 100644 --- a/doc/incident.html +++ b/doc/incident.html @@ -70,7 +70,7 @@ is the target. This function is equivalent to the expression Indiana University (jsiek@osl.iu.edu)
    Lie-Quan Lee, Indiana University (llee@cs.indiana.edu)
    -Andrew Lumsdaine, +Andrew Lumsdaine, Indiana University (lums@osl.iu.edu)
    diff --git a/doc/incremental_components.html b/doc/incremental_components.html index 7aed1a69..321b61d3 100644 --- a/doc/incremental_components.html +++ b/doc/incremental_components.html @@ -412,7 +412,7 @@ Returns the number of components in the graph. Indiana University (jsiek@osl.iu.edu)
    Lie-Quan Lee, Indiana University (llee@cs.indiana.edu)
    -Andrew Lumsdaine, +Andrew Lumsdaine, Indiana University (lums@osl.iu.edu)
    diff --git a/doc/index.html b/doc/index.html index eae700d9..aefb551e 100644 --- a/doc/index.html +++ b/doc/index.html @@ -293,7 +293,7 @@ iterator and implements an Edge List Graph. Indiana University (jsiek@osl.iu.edu)
    Lie-Quan Lee, Indiana University (llee@cs.indiana.edu)
    -Andrew Lumsdaine, +Andrew Lumsdaine, Indiana University (lums@osl.iu.edu)
    diff --git a/doc/known_problems.html b/doc/known_problems.html index ae5e2fff..13561330 100644 --- a/doc/known_problems.html +++ b/doc/known_problems.html @@ -51,7 +51,7 @@ Indiana University (jsiek@osl.iu.edu)
    Lie-Quan Lee, Indiana University (llee@cs.indiana.edu)
    -Andrew Lumsdaine, +Andrew Lumsdaine, Indiana University (lums@osl.iu.edu)
    diff --git a/doc/leda_conversion.html b/doc/leda_conversion.html index 8844760d..65c1d133 100644 --- a/doc/leda_conversion.html +++ b/doc/leda_conversion.html @@ -254,7 +254,7 @@ href="../test/graph.cpp">test/graph.cpp. Indiana University (jsiek@osl.iu.edu)
    Lie-Quan Lee, Indiana University (llee@cs.indiana.edu)
    -Andrew Lumsdaine, +Andrew Lumsdaine, Indiana University (lums@osl.iu.edu)
    diff --git a/doc/null_visitor.html b/doc/null_visitor.html index e6842032..0e2dd9f2 100644 --- a/doc/null_visitor.html +++ b/doc/null_visitor.html @@ -85,7 +85,7 @@ This does nothing. Indiana University (jsiek@osl.iu.edu)
    Lie-Quan Lee, Indiana University (llee@cs.indiana.edu)
    -Andrew Lumsdaine, +Andrew Lumsdaine, Indiana University (lums@osl.iu.edu)
    diff --git a/doc/opposite.html b/doc/opposite.html index 252c47f3..ce73d030 100644 --- a/doc/opposite.html +++ b/doc/opposite.html @@ -70,7 +70,7 @@ assert(u == opposite(e, v, g)); Indiana University (jsiek@osl.iu.edu)
    Lie-Quan Lee, Indiana University (llee@cs.indiana.edu)
    -Andrew Lumsdaine, +Andrew Lumsdaine, Indiana University (lums@osl.iu.edu)
    diff --git a/doc/plod_generator.html b/doc/plod_generator.html index 8e78ef3e..98d66427 100644 --- a/doc/plod_generator.html +++ b/doc/plod_generator.html @@ -131,7 +131,7 @@ int main()
    Copyright © 2005 Doug Gregor, Indiana University ()
    - Andrew Lumsdaine, + Andrew Lumsdaine, Indiana University ()
    diff --git a/doc/predecessor_recorder.html b/doc/predecessor_recorder.html index 6f933b4f..d11620a8 100644 --- a/doc/predecessor_recorder.html +++ b/doc/predecessor_recorder.html @@ -177,7 +177,7 @@ and property_writer. Indiana University (jsiek@osl.iu.edu)
    Lie-Quan Lee, Indiana University (llee@cs.indiana.edu)
    -Andrew Lumsdaine, +Andrew Lumsdaine, Indiana University (lums@osl.iu.edu) diff --git a/doc/property_map.html b/doc/property_map.html index b39c4ed3..8fa975b7 100644 --- a/doc/property_map.html +++ b/doc/property_map.html @@ -77,7 +77,7 @@ href="../../property_map/property_map.html">property map. Indiana University (jsiek@osl.iu.edu)
    Lie-Quan Lee, Indiana University (llee@cs.indiana.edu)
    -Andrew Lumsdaine, +Andrew Lumsdaine, Indiana University (lums@osl.iu.edu) diff --git a/doc/property_writer.html b/doc/property_writer.html index c4d4155a..862221ec 100644 --- a/doc/property_writer.html +++ b/doc/property_writer.html @@ -188,7 +188,7 @@ and time_stamper. Indiana University (jsiek@osl.iu.edu)
    Lie-Quan Lee, Indiana University (llee@cs.indiana.edu)
    -Andrew Lumsdaine, +Andrew Lumsdaine, Indiana University (lums@osl.iu.edu) diff --git a/doc/publications.html b/doc/publications.html index fc919bcb..e597f349 100644 --- a/doc/publications.html +++ b/doc/publications.html @@ -37,7 +37,7 @@ Indiana University (jsiek@osl.iu.edu)
    Lie-Quan Lee, Indiana University (llee@cs.indiana.edu)
    -Andrew Lumsdaine, +Andrew Lumsdaine, Indiana University (lums@osl.iu.edu) diff --git a/doc/python.html b/doc/python.html index 52ef6fcb..f9a2de54 100644 --- a/doc/python.html +++ b/doc/python.html @@ -44,7 +44,7 @@ Copyright © 2005 Doug Gregor, Indiana University ()
    - Andrew Lumsdaine, + Andrew Lumsdaine, Indiana University () diff --git a/doc/sequential_vertex_coloring.html b/doc/sequential_vertex_coloring.html index 504c8f39..9588c590 100644 --- a/doc/sequential_vertex_coloring.html +++ b/doc/sequential_vertex_coloring.html @@ -107,7 +107,7 @@ in the graph, and k is the number of colors used.
    Copyright © 1997-2004 -Andrew Lumsdaine, +Andrew Lumsdaine, Indiana University (lums@osl.iu.edu)
    Douglas Gregor, Indiana University (dgregor -at- cs.indiana.edu)) diff --git a/doc/small_world_generator.html b/doc/small_world_generator.html index 2f44c06a..aebd31ac 100644 --- a/doc/small_world_generator.html +++ b/doc/small_world_generator.html @@ -118,7 +118,7 @@ int main()
    Copyright © 2005 Doug Gregor, Indiana University ()
    - Andrew Lumsdaine, + Andrew Lumsdaine, Indiana University ()
    diff --git a/doc/sorted_erdos_renyi_gen.html b/doc/sorted_erdos_renyi_gen.html index e03cbcf6..16f7e2f7 100644 --- a/doc/sorted_erdos_renyi_gen.html +++ b/doc/sorted_erdos_renyi_gen.html @@ -125,7 +125,7 @@ int main() Jeremiah Willcock, Indiana University ()
    Doug Gregor, Indiana University ()
    - Andrew Lumsdaine, + Andrew Lumsdaine, Indiana University () diff --git a/doc/stanford_graph.html b/doc/stanford_graph.html index f4aa4bee..773f81e3 100644 --- a/doc/stanford_graph.html +++ b/doc/stanford_graph.html @@ -449,7 +449,7 @@ HREF="mailto:jsiek@osl.iu.edu">jsiek@osl.iu.edu)
    Lie-Quan Lee, Indiana University (llee@cs.indiana.edu)
    -Andrew Lumsdaine, +Andrew Lumsdaine, Indiana University (lums@osl.iu.edu) diff --git a/doc/table_of_contents.html b/doc/table_of_contents.html index 4c045f61..c7c86a61 100644 --- a/doc/table_of_contents.html +++ b/doc/table_of_contents.html @@ -287,7 +287,7 @@ Indiana University (jsiek@osl.iu.edu)
    Lie-Quan Lee, Indiana University (llee@cs.indiana.edu)
    -Andrew Lumsdaine, +Andrew Lumsdaine, Indiana University (lums@osl.iu.edu) diff --git a/doc/time_stamper.html b/doc/time_stamper.html index 08efa10d..6fcebe4c 100644 --- a/doc/time_stamper.html +++ b/doc/time_stamper.html @@ -187,7 +187,7 @@ and property_writer. Indiana University (jsiek@osl.iu.edu)
    Lie-Quan Lee, Indiana University (llee@cs.indiana.edu)
    -Andrew Lumsdaine, +Andrew Lumsdaine, Indiana University (lums@osl.iu.edu) diff --git a/doc/trouble_shooting.html b/doc/trouble_shooting.html index c14e8b67..21c657ff 100644 --- a/doc/trouble_shooting.html +++ b/doc/trouble_shooting.html @@ -119,7 +119,7 @@ for (std::size_t j = 0; j < n_edges; ++j) Indiana University (jsiek@osl.iu.edu)
    Lie-Quan Lee, Indiana University (llee@cs.indiana.edu)
    -Andrew Lumsdaine, +Andrew Lumsdaine, Indiana University (lums@osl.iu.edu) diff --git a/doc/undirected_dfs.html b/doc/undirected_dfs.html index 53bd726b..4c500716 100644 --- a/doc/undirected_dfs.html +++ b/doc/undirected_dfs.html @@ -327,7 +327,7 @@ An example is in Indiana University (jsiek@osl.iu.edu)
    Lie-Quan Lee, Indiana University (llee@cs.indiana.edu)
    -Andrew Lumsdaine, +Andrew Lumsdaine, Indiana University (lums@osl.iu.edu) diff --git a/doc/visitor_concepts.html b/doc/visitor_concepts.html index da86e1dc..e49a32bc 100644 --- a/doc/visitor_concepts.html +++ b/doc/visitor_concepts.html @@ -52,7 +52,7 @@ the following visitor concepts: Indiana University (jsiek@osl.iu.edu)
    Lie-Quan Lee, Indiana University (llee@cs.indiana.edu)
    -Andrew Lumsdaine, +Andrew Lumsdaine, Indiana University (lums@osl.iu.edu) From ae53d6cbbc919aff99801f09eed62d94670a0176 Mon Sep 17 00:00:00 2001 From: Douglas Gregor Date: Sun, 6 Jul 2008 18:55:34 +0000 Subject: [PATCH 011/224] Fix missing IncidenceGraph requirement in topoogical_sort. Fixes #1986 [SVN r47138] --- doc/topological_sort.html | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/doc/topological_sort.html b/doc/topological_sort.html index eae0400f..e3863ab9 100644 --- a/doc/topological_sort.html +++ b/doc/topological_sort.html @@ -45,7 +45,8 @@ href="./depth_first_search.html">depth_first_search(). IN: VertexListGraph& g
    A directed acylic graph (DAG). The graph type must - be a model of Vertex List Graph. + be a model of Vertex List Graph + and Incidence Graph. If the graph is not a DAG then a not_a_dag exception will be thrown and the user should discard the contents of result range.
    From 3644e4d51a3ecdf7c5bc72a2e1bac535833a49f9 Mon Sep 17 00:00:00 2001 From: Ronald Garcia Date: Tue, 8 Jul 2008 17:24:20 +0000 Subject: [PATCH 012/224] Initial Revision. Based on read_graphviz.cpp. [SVN r47240] --- example/graph-thingie.cpp | 102 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 102 insertions(+) create mode 100644 example/graph-thingie.cpp diff --git a/example/graph-thingie.cpp b/example/graph-thingie.cpp new file mode 100644 index 00000000..eac181a4 --- /dev/null +++ b/example/graph-thingie.cpp @@ -0,0 +1,102 @@ +// Copyright 2008 Trustees of Indiana University + +// 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) + +// An example of using read_graphviz to load a GraphViz Dot textual +// graph into a BGL adjacency_list graph that has custom properties. + +// Author: Ronald Garcia + + + +#include +#include +#include +#include +#include + +using namespace boost; +using namespace std; + + +// +// Create a custom graph properties +// (see the documentation for adjacency list) +struct graph_identifier_t { typedef graph_property_tag kind; }; +struct vertex_label_t { typedef vertex_property_tag kind; }; + +int main() { + + // Vertex properties + typedef property < vertex_name_t, string, + property < vertex_label_t, string, + property < vertex_root_t, int > > > vertex_p; + // Edge properties + typedef property < edge_name_t, string > edge_p; + // Graph properties + typedef property < graph_name_t, string, + property < graph_identifier_t, string > > graph_p; + // adjacency_list-based type + typedef adjacency_list < vecS, vecS, directedS, + vertex_p, edge_p, graph_p > graph_t; + + // Construct an empty graph and prepare the dynamic_property_maps. + graph_t graph(0); + dynamic_properties dp; + + property_map::type vname = + get(vertex_name, graph); + dp.property("node_id",vname); + + property_map::type vlabel = + get(vertex_label_t(), graph); + dp.property("label",vlabel); + + property_map::type root = + get(vertex_root, graph); + dp.property("root",root); + + property_map::type elabel = + get(edge_name, graph); + dp.property("label",elabel); + + // Use ref_property_map to turn a graph property into a property map + ref_property_map + gname(get_property(graph,graph_name)); + dp.property("name",gname); + + // Use ref_property_map to turn a graph property into a property map + ref_property_map + gid(get_property(graph,graph_identifier_t())); + dp.property("identifier",gid); + // Sample graph as an istream; + +const char* dot = +"digraph \ +{ \ + graph [name=\"GRAPH\", identifier=\"CX2A1Z\"] \ + \ + a [label=\"NODE_A\", root=\"1\"] \ + b [label=\"NODE_B\", root=\"0\"] \ + \ + a -> b [label=\"EDGE_1\"] \ + b -> c [label=\"EDGE_2\"] \ +}"; + + + istringstream gvgraph(dot); + + bool status = read_graphviz(gvgraph,graph,dp,"node_id"); + + cout << "graph " << get("name",dp,&graph) << + " (" << get("identifier",dp,&graph) << ")\n\n"; + + BOOST_FOREACH( graph_t::vertex_descriptor v, vertices(graph) ) { + cout << "vertex " << get("node_id",dp,v) << + " (" << get("label",dp,v) << ")\n"; + } + + return 0; +} From f9dcab79b25b8a2f520e109540699b8e8f7093d4 Mon Sep 17 00:00:00 2001 From: Douglas Gregor Date: Wed, 9 Jul 2008 14:59:46 +0000 Subject: [PATCH 013/224] Support BOOST_NO_EXCEPTIONS in Boost.Graph, from Brian Barrett [SVN r47269] --- include/boost/graph/detail/read_graphviz_spirit.hpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/include/boost/graph/detail/read_graphviz_spirit.hpp b/include/boost/graph/detail/read_graphviz_spirit.hpp index 0c483349..16224c23 100644 --- a/include/boost/graph/detail/read_graphviz_spirit.hpp +++ b/include/boost/graph/detail/read_graphviz_spirit.hpp @@ -53,6 +53,7 @@ #include #include #include +#include namespace phoenix { // Workaround: std::map::operator[] uses a different return type than all @@ -292,12 +293,12 @@ struct dot_grammar : public boost::spirit::grammar { void check_undirected() { if(self.graph_.is_directed()) - throw boost::undirected_graph_error(); + boost::throw_exception(boost::undirected_graph_error()); } void check_directed() { if(!self.graph_.is_directed()) - throw boost::directed_graph_error(); + boost::throw_exception(boost::directed_graph_error()); } void memoize_node() { From 6d2a97d97ca199b3bb4bde2affbf61da9b1d9e53 Mon Sep 17 00:00:00 2001 From: Douglas Gregor Date: Wed, 23 Jul 2008 13:58:30 +0000 Subject: [PATCH 014/224] Fix Cuthill-McKee documentation typos. Fixes #2131 [SVN r47709] --- doc/cuthill_mckee_ordering.html | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/doc/cuthill_mckee_ordering.html b/doc/cuthill_mckee_ordering.html index aa176270..f5d7c110 100644 --- a/doc/cuthill_mckee_ordering.html +++ b/doc/cuthill_mckee_ordering.html @@ -44,24 +44,24 @@ class ColorMap, class DegreeMap> OutputIterator cuthill_mckee_ordering(const IncidenceGraph& g, - typename graph_traits<Graph>::vertex_descriptor s, + typename graph_traits<IncidenceGraph>::vertex_descriptor s, OutputIterator inverse_permutation, ColorMap color, DegreeMap degree) (2) template <class VertexListGraph, class OutputIterator> OutputIterator - cuthill_mckee_ordering(const VertexIndexMap& G, OutputIterator inverse_permutation); + cuthill_mckee_ordering(const VertexListGraph& g, OutputIterator inverse_permutation); template <class VertexListGraph, class OutputIterator, class VertexIndexMap> OutputIterator - cuthill_mckee_ordering(const VertexIndexMap& G, OutputIterator inverse_permutation, + cuthill_mckee_ordering(const VertexListGraph& g, OutputIterator inverse_permutation, VertexIndexMap index_map); template <class VertexListGraph, class OutputIterator, class ColorMap, class DegreeMap> OutputIterator - cuthill_mckee_ordering(const VertexListGraph& G, OutputIterator inverse_permutation, + cuthill_mckee_ordering(const VertexListGraph& g, OutputIterator inverse_permutation, ColorMap color, DegreeMap degree) (3) @@ -70,7 +70,7 @@ OutputIterator cuthill_mckee_ordering(const IncidenceGraph& g, std::deque< typename - graph_traits<Graph>::vertex_descriptor > vertex_queue, + graph_traits<IncidenceGraph>::vertex_descriptor > vertex_queue, OutputIterator inverse_permutation, ColorMap color, DegreeMap degree) @@ -172,7 +172,7 @@ For version 2:
  • VertexListGraph& g  (IN)
    An undirected graph. The graph's type must be a model of VertexListGraph.
    + href="./VertexListGraph.html">VertexListGraph and IncidenceGraph.
    Python: The parameter is named graph.
  • From 7e088fd0ecf5dad1638f20b0bccafdb6ef10703f Mon Sep 17 00:00:00 2001 From: Douglas Gregor Date: Wed, 23 Jul 2008 15:24:17 +0000 Subject: [PATCH 015/224] Link against shared expat. [SVN r47720] --- build/Jamfile.v2 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/Jamfile.v2 b/build/Jamfile.v2 index d684515b..863b56b6 100644 --- a/build/Jamfile.v2 +++ b/build/Jamfile.v2 @@ -26,7 +26,7 @@ if [ modules.peek : EXPAT_INCLUDE ] && [ modules.peek : EXPAT_LIBPATH ] optional_sources += graphml.cpp ; optional_reqs += $(EXPAT_INCLUDE) $(EXPAT_LIBPATH) - expat + expat ; } else From b39dd265099f5adc5060459c60e771ea66bd58a2 Mon Sep 17 00:00:00 2001 From: Douglas Gregor Date: Fri, 1 Aug 2008 14:20:59 +0000 Subject: [PATCH 016/224] Make reverse_graph work with non-class graph types [SVN r47930] --- include/boost/graph/reverse_graph.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/boost/graph/reverse_graph.hpp b/include/boost/graph/reverse_graph.hpp index 314584fa..ef7f3a7e 100644 --- a/include/boost/graph/reverse_graph.hpp +++ b/include/boost/graph/reverse_graph.hpp @@ -76,9 +76,9 @@ class reverse_graph { typedef typename Traits::edges_size_type edges_size_type; // More typedefs used by detail::edge_property_map, vertex_property_map - typedef typename BidirectionalGraph::edge_property_type + typedef typename boost::edge_property_type::type edge_property_type; - typedef typename BidirectionalGraph::vertex_property_type + typedef typename boost::vertex_property_type::type vertex_property_type; typedef reverse_graph_tag graph_tag; From d73b792b6cb31c58961d58dcec6520e1f8a6c0d2 Mon Sep 17 00:00:00 2001 From: Douglas Gregor Date: Thu, 4 Sep 2008 19:49:49 +0000 Subject: [PATCH 017/224] Make graphml_test.cpp accept the name of its input file on the command line, Jamfile.v2 provide the input file (both thanks to Dave A), and make the input XML well-formed. Fixes #2267. [SVN r48583] --- test/Jamfile.v2 | 2 +- test/graphml_test.cpp | 2 +- test/graphml_test.xml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 0c179d7b..8a625e42 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -17,7 +17,7 @@ path-constant CYCLE_RATIO_INPUT_FILE : ./cycle_ratio_s382.90.dot ; if [ modules.peek : EXPAT_INCLUDE ] && [ modules.peek : EXPAT_LIBPATH ] { - optional_tests += [ run graphml_test.cpp ../build//boost_graph ] ; + optional_tests += [ run graphml_test.cpp ../build//boost_graph : : "graphml_test.xml" ] ; } test-suite graph_test : diff --git a/test/graphml_test.cpp b/test/graphml_test.cpp index 10742896..44fde10e 100644 --- a/test/graphml_test.cpp +++ b/test/graphml_test.cpp @@ -43,7 +43,7 @@ int main(int argc, char** argv) dp.property("foo",get(vertex_color_t(),g)); dp.property("weight",get(edge_weight_t(),g)); - ifstream ifile("graphml_test.xml"); + ifstream ifile(argv[1]); read_graphml(ifile, g, dp); ifile.close(); diff --git a/test/graphml_test.xml b/test/graphml_test.xml index 63d9899e..25d56b47 100644 --- a/test/graphml_test.xml +++ b/test/graphml_test.xml @@ -19,7 +19,7 @@ 0 - + 0.8 From 424e529abafdee9c7c0c9cf668d1139cc62329fc Mon Sep 17 00:00:00 2001 From: Douglas Gregor Date: Fri, 5 Sep 2008 13:59:12 +0000 Subject: [PATCH 018/224] Fix handling of infinite weights in Floyd-Warshall algorithm. Fixes #1700 [SVN r48611] --- include/boost/graph/floyd_warshall_shortest.hpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/include/boost/graph/floyd_warshall_shortest.hpp b/include/boost/graph/floyd_warshall_shortest.hpp index 69c3e7ed..6204ca0e 100644 --- a/include/boost/graph/floyd_warshall_shortest.hpp +++ b/include/boost/graph/floyd_warshall_shortest.hpp @@ -59,15 +59,15 @@ namespace boost for (tie(k, lastk) = vertices(g); k != lastk; k++) for (tie(i, lasti) = vertices(g); i != lasti; i++) - for (tie(j, lastj) = vertices(g); j != lastj; j++) - { - d[*i][*j] = - detail::min_with_compare(d[*i][*j], - combine(d[*i][*k], d[*k][*j]), - compare); - } + if(d[*i][*k] != inf) + for (tie(j, lastj) = vertices(g); j != lastj; j++) + if(d[*k][*j] != inf) + d[*i][*j] = + detail::min_with_compare(d[*i][*j], + combine(d[*i][*k], d[*k][*j]), + compare); + - for (tie(i, lasti) = vertices(g); i != lasti; i++) if (compare(d[*i][*i], zero)) return false; From 3a894a9a5f9b42d744055dd9da243d40fb50ba57 Mon Sep 17 00:00:00 2001 From: Andrew Sutton Date: Mon, 29 Sep 2008 12:27:03 +0000 Subject: [PATCH 019/224] Removed define and usage of MAXINT, replaced with numeric_limits max. This was discussed on the boost list, but there's no ticket filed. [SVN r48999] --- include/boost/graph/sloan_ordering.hpp | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) mode change 100755 => 100644 include/boost/graph/sloan_ordering.hpp diff --git a/include/boost/graph/sloan_ordering.hpp b/include/boost/graph/sloan_ordering.hpp old mode 100755 new mode 100644 index b0855e5a..3a257b8d --- a/include/boost/graph/sloan_ordering.hpp +++ b/include/boost/graph/sloan_ordering.hpp @@ -14,19 +14,18 @@ #define WEIGHT1 1 //default weight for the distance in the Sloan algorithm #define WEIGHT2 2 //default weight for the degree in the Sloan algorithm -#define MAXINT 2147483647 //Maximum value for a 32bit integer #include #include #include +#include +#include #include #include #include #include #include #include -#include -#include #include #include #include @@ -195,9 +194,9 @@ namespace boost { //end 3 & 4 - //step 5 - //Initializing w - w_e = MAXINT; + // step 5 + // Initializing w + w_e = std::numeric_limits::max(); //end 5 From e9d6adeab1b91acd68fc27d9f1749438f921e411 Mon Sep 17 00:00:00 2001 From: Andrew Sutton Date: Mon, 29 Sep 2008 12:42:26 +0000 Subject: [PATCH 020/224] Resolving ticket #2209. [SVN r49000] --- include/boost/graph/topological_sort.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/boost/graph/topological_sort.hpp b/include/boost/graph/topological_sort.hpp index 2ed7e18e..dc8d9eb7 100644 --- a/include/boost/graph/topological_sort.hpp +++ b/include/boost/graph/topological_sort.hpp @@ -37,7 +37,7 @@ namespace boost { : m_iter(_iter) { } template - void back_edge(const Edge& u, Graph&) { throw not_a_dag(); } + void back_edge(const Edge&, Graph&) { throw not_a_dag(); } template void finish_vertex(const Vertex& u, Graph&) { *m_iter++ = u; } From 19dd79f771f72b553b40736211b848028805dea6 Mon Sep 17 00:00:00 2001 From: Vladimir Prus Date: Mon, 29 Sep 2008 15:38:37 +0000 Subject: [PATCH 021/224] Don't emit warnings about GraphML support if not actually building Boost.Graph. [SVN r49008] --- build/Jamfile.v2 | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/build/Jamfile.v2 b/build/Jamfile.v2 index 863b56b6..7e8da510 100644 --- a/build/Jamfile.v2 +++ b/build/Jamfile.v2 @@ -23,23 +23,30 @@ if [ modules.peek : EXPAT_INCLUDE ] && [ modules.peek : EXPAT_LIBPATH ] ECHO "Expat library directory: $(EXPAT_LIBPATH)" ; } - optional_sources += graphml.cpp ; - optional_reqs += $(EXPAT_INCLUDE) - $(EXPAT_LIBPATH) - expat - ; + alias graphml + : graphml.cpp + : # requirements + : # default built + : # usage requirements + $(EXPAT_INCLUDE) + $(EXPAT_LIBPATH) + expat + ; } else { - ECHO "warning: Graph library does not contain optional GraphML reader." ; - ECHO "note: to enable GraphML support, set EXPAT_INCLUDE and EXPAT_LIBPATH to the" ; - ECHO "note: directories containing the Expat headers and libraries, respectively." ; + message graphml + : "warning: Graph library does not contain optional GraphML reader." + : "note: to enable GraphML support, set EXPAT_INCLUDE and EXPAT_LIBPATH to the" + : "note: directories containing the Expat headers and libraries, respectively." + ; } +explicit graphml ; lib boost_graph : read_graphviz_spirit.cpp - $(optional_sources) + graphml : BOOST_GRAPH_NO_LIB=1 shared:BOOST_GRAPH_DYN_LINK=1 @@ -48,8 +55,6 @@ lib boost_graph # Without these flags, MSVC 7.1 and 8.0 crash msvc-7.1:-GR- msvc-8.0:-GR- - # Requirements for any "optional" sources - $(optional_reqs) ; boost-install boost_graph ; \ No newline at end of file From 7218c1ba66ab5f50c1e5d16b1225bf8c8d26a598 Mon Sep 17 00:00:00 2001 From: Aaron Windsor Date: Sat, 4 Oct 2008 22:49:18 +0000 Subject: [PATCH 022/224] Fix for a bug in BGL's is_straight_line_drawing - adding necessary additional comparisons during the planar sweep to detect intersections. [SVN r49132] --- .../boost/graph/is_straight_line_drawing.hpp | 28 ++- test/Jamfile.v2 | 2 + test/is_straight_line_draw_test.cpp | 161 ++++++++++++++++++ 3 files changed, 187 insertions(+), 4 deletions(-) create mode 100644 test/is_straight_line_draw_test.cpp diff --git a/include/boost/graph/is_straight_line_drawing.hpp b/include/boost/graph/is_straight_line_drawing.hpp index f533bce2..eb9bf688 100644 --- a/include/boost/graph/is_straight_line_drawing.hpp +++ b/include/boost/graph/is_straight_line_drawing.hpp @@ -164,7 +164,7 @@ namespace boost edge_t e(get<0>(*itr)); vertex_t source_v(source(e,g)); vertex_t target_v(target(e,g)); - if (drawing[source_v].x > drawing[target_v].x) + if (drawing[source_v].y > drawing[target_v].y) std::swap(source_v, target_v); active_map_key_t key(get(drawing, source_v).y, @@ -187,12 +187,32 @@ namespace boost before = prior(a_itr); after = next(a_itr); - if (after != active_edges.end() || before != active_edges.end()) + if (before != active_edges.end()) { - edge_t f = after != active_edges.end() ? - after->second : before->second; + edge_t f = before->second; + vertex_t e_source(source(e,g)); + vertex_t e_target(target(e,g)); + vertex_t f_source(source(f,g)); + vertex_t f_target(target(f,g)); + if (intersects(drawing[e_source].x, + drawing[e_source].y, + drawing[e_target].x, + drawing[e_target].y, + drawing[f_source].x, + drawing[f_source].y, + drawing[f_target].x, + drawing[f_target].y + ) + ) + return false; + } + + if (after != active_edges.end()) + { + + edge_t f = after->second; vertex_t e_source(source(e,g)); vertex_t e_target(target(e,g)); vertex_t f_source(source(f,g)); diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 8a625e42..f8b20d91 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -135,6 +135,8 @@ test-suite graph_test : [ run r_c_shortest_paths_test.cpp ] + [ run is_straight_line_draw_test.cpp ] + $(optional_tests) ; diff --git a/test/is_straight_line_draw_test.cpp b/test/is_straight_line_draw_test.cpp new file mode 100644 index 00000000..03cc56ac --- /dev/null +++ b/test/is_straight_line_draw_test.cpp @@ -0,0 +1,161 @@ +//======================================================================= +// Copyright 2008 Aaron Windsor +// +// 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 + +using namespace boost; + +struct coord_t +{ + std::size_t x; + std::size_t y; +}; + + +int test_main(int argc, char* argv []) +{ + typedef adjacency_list< vecS, vecS, undirectedS, + property + > graph_t; + + typedef std::vector< coord_t > drawing_storage_t; + + typedef boost::iterator_property_map + < drawing_storage_t::iterator, + property_map::type + > drawing_t; + + graph_t g(4); + add_edge(0,1,g); + add_edge(2,3,g); + + drawing_storage_t drawing_storage(num_vertices(g)); + drawing_t drawing(drawing_storage.begin(), get(vertex_index,g)); + + // two perpendicular lines that intersect at (1,1) + drawing[0].x = 1; drawing[0].y = 0; + drawing[1].x = 1; drawing[1].y = 2; + drawing[2].x = 0; drawing[2].y = 1; + drawing[3].x = 2; drawing[3].y = 1; + + BOOST_REQUIRE(!is_straight_line_drawing(g,drawing)); + + // two parallel horizontal lines + drawing[0].x = 0; drawing[0].y = 0; + drawing[1].x = 2; drawing[1].y = 0; + + BOOST_REQUIRE(is_straight_line_drawing(g,drawing)); + + // two parallel vertical lines + drawing[0].x = 0; drawing[0].y = 0; + drawing[1].x = 0; drawing[1].y = 2; + drawing[2].x = 1; drawing[2].y = 0; + drawing[3].x = 1; drawing[3].y = 2; + + BOOST_REQUIRE(is_straight_line_drawing(g,drawing)); + + // two lines that intersect at (1,1) + drawing[0].x = 0; drawing[0].y = 0; + drawing[1].x = 2; drawing[1].y = 2; + drawing[2].x = 0; drawing[2].y = 2; + drawing[3].x = 2; drawing[3].y = 0; + + BOOST_REQUIRE(!is_straight_line_drawing(g,drawing)); + + // K_4 arranged in a diamond pattern, so that edges intersect + g = graph_t(4); + add_edge(0,1,g); + add_edge(0,2,g); + add_edge(0,3,g); + add_edge(1,2,g); + add_edge(1,3,g); + add_edge(2,3,g); + + drawing_storage = drawing_storage_t(num_vertices(g)); + drawing = drawing_t(drawing_storage.begin(), get(vertex_index,g)); + + drawing[0].x = 1; drawing[0].y = 2; + drawing[1].x = 2; drawing[1].y = 1; + drawing[2].x = 1; drawing[2].y = 0; + drawing[3].x = 0; drawing[3].y = 1; + + BOOST_REQUIRE(!is_straight_line_drawing(g, drawing)); + + // K_4 arranged so that no edges intersect + drawing[0].x = 0; drawing[0].y = 0; + drawing[1].x = 1; drawing[1].y = 1; + drawing[2].x = 1; drawing[2].y = 2; + drawing[3].x = 2; drawing[3].y = 0; + + BOOST_REQUIRE(is_straight_line_drawing(g, drawing)); + + // a slightly more complicated example - edges (0,1) and (4,5) + // intersect + g = graph_t(8); + add_edge(0,1,g); + add_edge(2,3,g); + add_edge(4,5,g); + add_edge(6,7,g); + + drawing_storage = drawing_storage_t(num_vertices(g)); + drawing = drawing_t(drawing_storage.begin(), get(vertex_index,g)); + + drawing[0].x = 1; drawing[0].y = 1; + drawing[1].x = 5; drawing[1].y = 4; + drawing[2].x = 2; drawing[2].y = 5; + drawing[3].x = 4; drawing[3].y = 4; + drawing[4].x = 3; drawing[4].y = 4; + drawing[5].x = 3; drawing[5].y = 2; + drawing[6].x = 4; drawing[6].y = 2; + drawing[7].x = 1; drawing[7].y = 1; + + BOOST_REQUIRE(!is_straight_line_drawing(g, drawing)); + + // form a graph consisting of a bunch of parallel vertical edges, + // then place an edge at various positions to intersect edges + g = graph_t(22); + for(int i = 0; i < 11; ++i) + add_edge(2*i,2*i+1,g); + + drawing_storage = drawing_storage_t(num_vertices(g)); + drawing = drawing_t(drawing_storage.begin(), get(vertex_index,g)); + + for(int i = 0; i < 10; ++i) + { + drawing[2*i].x = i; drawing[2*i].y = 0; + drawing[2*i+1].x = i; drawing[2*i+1].y = 10; + } + + // put the final edge as a horizontal edge intersecting one other edge + drawing[20].x = 5; drawing[20].y = 5; + drawing[21].x = 7; drawing[21].y = 5; + + BOOST_REQUIRE(!is_straight_line_drawing(g, drawing)); + + // make the final edge a diagonal intersecting multiple edges + drawing[20].x = 2; drawing[20].y = 4; + drawing[21].x = 9; drawing[21].y = 7; + + BOOST_REQUIRE(!is_straight_line_drawing(g, drawing)); + + // reverse the slope + drawing[20].x = 2; drawing[20].y = 7; + drawing[21].x = 9; drawing[21].y = 4; + + BOOST_REQUIRE(!is_straight_line_drawing(g, drawing)); + + return 0; +} + From 9b902b614d669693fef290a5af8b7c91959aecef Mon Sep 17 00:00:00 2001 From: Douglas Gregor Date: Wed, 8 Oct 2008 12:38:44 +0000 Subject: [PATCH 023/224] Fix reverse_graph adaptor to work with user-defined graph types [SVN r49176] --- include/boost/graph/reverse_graph.hpp | 35 ++++++++++++++------------- 1 file changed, 18 insertions(+), 17 deletions(-) diff --git a/include/boost/graph/reverse_graph.hpp b/include/boost/graph/reverse_graph.hpp index ef7f3a7e..8fbd6364 100644 --- a/include/boost/graph/reverse_graph.hpp +++ b/include/boost/graph/reverse_graph.hpp @@ -146,16 +146,16 @@ edges(const reverse_graph& g) } template -inline std::pair -out_edges(const typename BidirectionalGraph::vertex_descriptor u, +inline std::pair::in_edge_iterator, + typename graph_traits::in_edge_iterator> +out_edges(const typename graph_traits::vertex_descriptor u, const reverse_graph& g) { return in_edges(u, g.m_g); } template -inline typename BidirectionalGraph::vertices_size_type +inline typename graph_traits::vertices_size_type num_vertices(const reverse_graph& g) { return num_vertices(g.m_g); @@ -169,26 +169,27 @@ num_edges(const reverse_graph& g) } template -inline typename BidirectionalGraph::degree_size_type -out_degree(const typename BidirectionalGraph::vertex_descriptor u, +inline typename graph_traits::degree_size_type +out_degree(const typename graph_traits::vertex_descriptor u, const reverse_graph& g) { return in_degree(u, g.m_g); } template -inline std::pair -edge(const typename BidirectionalGraph::vertex_descriptor u, - const typename BidirectionalGraph::vertex_descriptor v, +inline std::pair::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); } template -inline std::pair -in_edges(const typename BidirectionalGraph::vertex_descriptor u, +inline std::pair::out_edge_iterator, + typename graph_traits::out_edge_iterator> +in_edges(const typename graph_traits::vertex_descriptor u, const reverse_graph& g) { return out_edges(u, g.m_g); @@ -197,20 +198,20 @@ in_edges(const typename BidirectionalGraph::vertex_descriptor u, template inline std::pair::adjacency_iterator, typename reverse_graph::adjacency_iterator> -adjacent_vertices(const typename BidirectionalGraph::vertex_descriptor u, +adjacent_vertices(typename graph_traits::vertex_descriptor u, const reverse_graph& g) { typedef reverse_graph Graph; - typename Graph::out_edge_iterator first, last; + typename graph_traits::out_edge_iterator first, last; tie(first, last) = out_edges(u, g); - typedef typename Graph::adjacency_iterator adjacency_iterator; + typedef typename graph_traits::adjacency_iterator adjacency_iterator; return std::make_pair(adjacency_iterator(first, const_cast(&g)), adjacency_iterator(last, const_cast(&g))); } template -inline typename BidirectionalGraph::degree_size_type -in_degree(const typename BidirectionalGraph::vertex_descriptor u, +inline typename graph_traits::degree_size_type +in_degree(const typename graph_traits::vertex_descriptor u, const reverse_graph& g) { return out_degree(u, g.m_g); From f7585c91af8adad14df0f5a5f97cf23b817c7a07 Mon Sep 17 00:00:00 2001 From: Douglas Gregor Date: Wed, 8 Oct 2008 14:51:11 +0000 Subject: [PATCH 024/224] Add support for named vertices in adjacency_list [SVN r49178] --- build/Jamfile.v2 | 25 +- include/boost/graph/adjacency_list.hpp | 16 +- include/boost/graph/detail/adjacency_list.hpp | 15 + include/boost/graph/named_graph.hpp | 541 ++++++++++++++++++ test/Jamfile.v2 | 2 + test/named_vertices_test.cpp | 91 +++ 6 files changed, 688 insertions(+), 2 deletions(-) create mode 100644 include/boost/graph/named_graph.hpp create mode 100644 test/named_vertices_test.cpp diff --git a/build/Jamfile.v2 b/build/Jamfile.v2 index 7e8da510..e3272262 100644 --- a/build/Jamfile.v2 +++ b/build/Jamfile.v2 @@ -57,4 +57,27 @@ lib boost_graph msvc-8.0:-GR- ; -boost-install boost_graph ; \ No newline at end of file +boost-install boost_graph ; + +############################################################ +# Distributed-memory parallel graph library (Parallel BGL) # +############################################################ +use-project /boost/mpi : ../../mpi/build ; +import mpi ; +if [ mpi.configured ] +{ + lib boost_graph_mpi + : distributed/tag_allocator.cpp + distributed/mpi_process_group.cpp + : # Requirements + ../../mpi/build//boost_mpi + /mpi//mpi [ mpi.extra-requirements ] + ../../serialization/build//boost_serialization + : # Default build + shared + : # Usage requirements + ../../mpi/build//boost_mpi + /mpi//mpi [ mpi.extra-requirements ] + ../../serialization/build//boost_serialization + ; +} \ No newline at end of file diff --git a/include/boost/graph/adjacency_list.hpp b/include/boost/graph/adjacency_list.hpp index a60916a2..9f019f74 100644 --- a/include/boost/graph/adjacency_list.hpp +++ b/include/boost/graph/adjacency_list.hpp @@ -44,6 +44,7 @@ #include #include #include +#include namespace boost { @@ -333,7 +334,14 @@ namespace boost { #else VertexProperty, EdgeProperty, #endif - GraphProperty, EdgeListS>::type + GraphProperty, EdgeListS>::type, + // Support for named vertices + public graph::maybe_named_graph< + adjacency_list, + typename adjacency_list_traits::vertex_descriptor, + VertexProperty> { #if !defined(BOOST_GRAPH_NO_BUNDLED_PROPERTIES) typedef typename detail::retag_property_listclearing_graph(); + Base::clear(); + } + #ifndef BOOST_GRAPH_NO_BUNDLED_PROPERTIES // Directly access a vertex or edge bundle vertex_bundled& operator[](vertex_descriptor v) diff --git a/include/boost/graph/detail/adjacency_list.hpp b/include/boost/graph/detail/adjacency_list.hpp index 0839dc0f..43a27bde 100644 --- a/include/boost/graph/detail/adjacency_list.hpp +++ b/include/boost/graph/detail/adjacency_list.hpp @@ -1902,6 +1902,7 @@ namespace boost { bool inserted; boost::tie(pos,inserted) = boost::graph_detail::push(g.m_vertices, v); v->m_position = pos; + g.added_vertex(v); return v; } // O(1) @@ -1910,13 +1911,19 @@ namespace boost { add_vertex(const typename Config::vertex_property_type& p, adj_list_impl& g_) { + typedef typename Config::vertex_descriptor vertex_descriptor; Derived& g = static_cast(g_); + if (optional v + = g.vertex_by_property(get_property_value(p, vertex_bundle))) + return *v; + typedef typename Config::stored_vertex stored_vertex; stored_vertex* v = new stored_vertex(p); typename Config::StoredVertexList::iterator pos; bool inserted; boost::tie(pos,inserted) = boost::graph_detail::push(g.m_vertices, v); v->m_position = pos; + g.added_vertex(v); return v; } // O(1) @@ -1926,6 +1933,7 @@ namespace boost { { typedef typename Config::stored_vertex stored_vertex; Derived& g = static_cast(g_); + g.removing_vertex(u); stored_vertex* su = (stored_vertex*)u; g.m_vertices.erase(su->m_position); delete su; @@ -2171,6 +2179,7 @@ namespace boost { add_vertex(vec_adj_list_impl& g_) { Graph& g = static_cast(g_); g.m_vertices.resize(g.m_vertices.size() + 1); + g.added_vertex(g.m_vertices.size() - 1); return g.m_vertices.size() - 1; } @@ -2178,9 +2187,14 @@ namespace boost { inline typename Config::vertex_descriptor add_vertex(const typename Config::vertex_property_type& p, vec_adj_list_impl& g_) { + typedef typename Config::vertex_descriptor vertex_descriptor; Graph& g = static_cast(g_); + if (optional v + = g.vertex_by_property(get_property_value(p, vertex_bundle))) + return *v; typedef typename Config::stored_vertex stored_vertex; g.m_vertices.push_back(stored_vertex(p)); + g.added_vertex(g.m_vertices.size() - 1); return g.m_vertices.size() - 1; } @@ -2219,6 +2233,7 @@ namespace boost { { typedef typename Config::directed_category Cat; Graph& g = static_cast(g_); + g.removing_vertex(v); 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 new file mode 100644 index 00000000..efadd4e1 --- /dev/null +++ b/include/boost/graph/named_graph.hpp @@ -0,0 +1,541 @@ +// Copyright (C) 2007 Douglas Gregor + +// 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) + +// Provides support for named vertices in graphs, allowing one to more +// easily associate unique external names (URLs, city names, employee +// ID numbers, etc.) with the vertices of a graph. +#ifndef BOOST_GRAPH_NAMED_GRAPH_HPP +#define BOOST_GRAPH_NAMED_GRAPH_HPP + +#include +#include +#include +#include +#include +#include +#include + +namespace boost { namespace graph { + +/******************************************************************* + * User-customized traits * + *******************************************************************/ + +/** + * @brief Trait used to extract the internal vertex name from a vertex + * property. + * + * To enable the use of internal vertex names in a graph type, + * specialize the @c internal_vertex_name trait for your graph + * property (e.g., @c a City class, which stores information about the + * vertices in a road map). + */ +template +struct internal_vertex_name +{ + /** + * The @c type field provides a function object that extracts a key + * from the @c VertexProperty. The function object type must have a + * nested @c result_type that provides the type of the key. For + * more information, see the @c KeyExtractor concept in the + * Boost.MultiIndex documentation: @c type must either be @c void + * (if @c VertexProperty does not have an internal vertex name) or + * a model of @c KeyExtractor. + */ + typedef void type; +}; + +#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION +/** + * Extract the internal vertex name from a @c property structure by + * looking at its base. + */ +template +struct internal_vertex_name > + : internal_vertex_name { }; +#endif + +/** + * Construct an instance of @c VertexProperty directly from its + * name. This function object should be used within the @c + * internal_vertex_constructor trait. + */ +template +struct vertex_from_name +{ +private: + typedef typename internal_vertex_name::type extract_name_type; + + typedef typename remove_cv< + typename remove_reference< + typename extract_name_type::result_type>::type>::type + vertex_name_type; + +public: + typedef vertex_name_type argument_type; + typedef VertexProperty result_type; + + VertexProperty operator()(const vertex_name_type& name) + { + return VertexProperty(name); + } +}; + +/** + * Throw an exception whenever one tries to construct a @c + * VertexProperty instance from its name. + */ +template +struct cannot_add_vertex +{ +private: + typedef typename internal_vertex_name::type extract_name_type; + + typedef typename remove_cv< + typename remove_reference< + typename extract_name_type::result_type>::type>::type + vertex_name_type; + +public: + typedef vertex_name_type argument_type; + typedef VertexProperty result_type; + + VertexProperty operator()(const vertex_name_type& name) + { + boost::throw_exception(std::runtime_error("add_vertex: " + "unable to create a vertex from its name")); + } +}; + +/** + * @brief Trait used to construct an instance of a @c VertexProperty, + * which is a class type that stores the properties associated with a + * vertex in a graph, from just the name of that vertex property. This + * operation is used when an operation is required to map from a + * vertex name to a vertex descriptor (e.g., to add an edge outgoing + * from that vertex), but no vertex by the name exists. The function + * object provided by this trait will be used to add new vertices + * based only on their names. Since this cannot be done for arbitrary + * types, the default behavior is to throw an exception when this + * routine is called, which requires that all named vertices be added + * before adding any edges by name. + */ +template +struct internal_vertex_constructor +{ + /** + * The @c type field provides a function object that constructs a + * new instance of @c VertexProperty from the name of the vertex (as + * determined by @c internal_vertex_name). The function object shall + * accept a vertex name and return a @c VertexProperty. Predefined + * options include: + * + * @c vertex_from_name: construct an instance of + * @c VertexProperty directly from the name. + * + * @c cannot_add_vertex: the default value, which + * throws an @c std::runtime_error if one attempts to add a vertex + * given just the name. + */ + 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. + */ +template +struct internal_vertex_constructor > + : internal_vertex_constructor { }; +#endif + +/******************************************************************* + * Named graph-specific metafunctions * + *******************************************************************/ +namespace detail { + /** + * INTERNAL ONLY + * + * 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 ONLY + * + * 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 * + *******************************************************************/ + +/** + * named_graph is a mixin that provides names for the vertices of a + * graph, including a mapping from names to vertices. Graph types that + * may or may not be have vertex names (depending on the properties + * supplied by the user) should use maybe_named_graph. + * + * Template parameters: + * + * Graph: the graph type that derives from named_graph + * + * Vertex: the type of a vertex descriptor in Graph. Note: we cannot + * use graph_traits here, because the Graph is not yet defined. + * + * VertexProperty: the type stored with each vertex in the Graph. + */ +template +class named_graph +{ +public: + /// The type of the function object that extracts names from vertex + /// properties. + 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 + bundled_vertex_property_type; + + /// The type of the function object that generates vertex properties + /// from names, for the implicit addition of vertices. + typedef typename internal_vertex_constructor::type + vertex_constructor_type; + + /// The type used to name vertices in the graph + typedef typename remove_cv< + typename remove_reference< + typename extract_name_type::result_type>::type>::type + vertex_name_type; + + /// The type of vertex descriptors in the graph + typedef Vertex vertex_descriptor; + +private: + /// Key extractor for use with the multi_index_container + struct extract_name_from_vertex + { + typedef vertex_name_type result_type; + + extract_name_from_vertex(Graph& graph, const extract_name_type& extract) + : graph(graph), extract(extract) { } + + const result_type& operator()(Vertex vertex) const + { + return extract(graph[vertex]); + } + + Graph& graph; + extract_name_type extract; + }; + +public: + /// The type that maps names to vertices + typedef multi_index::multi_index_container< + Vertex, + multi_index::indexed_by< + multi_index::hashed_unique, + extract_name_from_vertex> > + > named_vertices_type; + + /// The set of vertices, indexed by name + typedef typename named_vertices_type::template index::type + vertices_by_name_type; + + /// Construct an instance of the named graph mixin, using the given + /// function object to extract a name from the bundled property + /// associated with a vertex. + named_graph(const extract_name_type& extract = extract_name_type(), + const vertex_constructor_type& vertex_constructor + = vertex_constructor_type()); + + /// Notify the named_graph that we have added the given vertex. The + /// name of the vertex will be added to the mapping. + void added_vertex(Vertex vertex); + + /// 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); + + /// Notify the named_graph that we are clearing the graph. + /// This will clear out all of the name->vertex mappings + void clearing_graph(); + + /// Retrieve the derived instance + Graph& derived() { return static_cast(*this); } + const Graph& derived() const { return static_cast(*this); } + + /// Extract the name from a vertex property instance + typename extract_name_type::result_type + extract_name(const bundled_vertex_property_type& property); + + /// Search for a vertex that has the given property (based on its + /// name) + optional + vertex_by_property(const bundled_vertex_property_type& property); + + /// Mapping from names to vertices + named_vertices_type named_vertices; + + /// Constructs a vertex from the name of that vertex + vertex_constructor_type vertex_constructor; +}; + +/// Helper macro containing the template parameters of named_graph +#define BGL_NAMED_GRAPH_PARAMS \ + typename Graph, typename Vertex, typename VertexProperty +/// Helper macro containing the named_graph<...> instantiation +#define BGL_NAMED_GRAPH \ + named_graph + +template +BGL_NAMED_GRAPH::named_graph(const extract_name_type& extract, + const vertex_constructor_type& vertex_constructor) + : named_vertices( + typename named_vertices_type::ctor_args_list( + boost::make_tuple( + boost::make_tuple( + 0, // initial number of buckets + extract_name_from_vertex(derived(), extract), + boost::hash(), + std::equal_to())))), + vertex_constructor(vertex_constructor) +{ +} + +template +inline void BGL_NAMED_GRAPH::added_vertex(Vertex vertex) +{ + named_vertices.insert(vertex); +} + +template +inline void BGL_NAMED_GRAPH::removing_vertex(Vertex vertex) +{ + named_vertices.erase(vertex); +} + +template +inline void BGL_NAMED_GRAPH::clearing_graph() +{ + named_vertices.clear(); +} + +template +typename BGL_NAMED_GRAPH::extract_name_type::result_type +BGL_NAMED_GRAPH::extract_name(const bundled_vertex_property_type& property) +{ + return named_vertices.key_extractor().extract(property); +} + +template +optional +BGL_NAMED_GRAPH:: +vertex_by_property(const bundled_vertex_property_type& property) +{ + return find_vertex(extract_name(property), *this); +} + +/// Retrieve the vertex associated with the given name +template +optional +find_vertex(typename BGL_NAMED_GRAPH::vertex_name_type const& name, + const BGL_NAMED_GRAPH& g) +{ + typedef typename BGL_NAMED_GRAPH::vertices_by_name_type + vertices_by_name_type; + + // Retrieve the set of vertices indexed by name + vertices_by_name_type const& vertices_by_name + = g.named_vertices.template get(); + + /// Look for a vertex with the given name + typename vertices_by_name_type::const_iterator iter + = vertices_by_name.find(name); + + if (iter == vertices_by_name.end()) + return optional(); // vertex not found + else + return *iter; +} + +/// Retrieve the vertex associated with the given name, or add a new +/// vertex with that name if no such vertex is available. +template +Vertex +add_vertex(typename BGL_NAMED_GRAPH::vertex_name_type const& name, + BGL_NAMED_GRAPH& g) +{ + if (optional vertex = find_vertex(name, g)) + /// We found the vertex, so return it + return *vertex; + else + /// There is no vertex with the given name, so create one + return add_vertex(g.vertex_constructor(name), g.derived()); +} + +/// Add an edge using vertex names to refer to the vertices +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, + BGL_NAMED_GRAPH& g) +{ + return add_edge(add_vertex(u_name, g.derived()), + add_vertex(v_name, g.derived()), + g.derived()); +} + +/// Add an edge using vertex descriptors or names to refer to the vertices +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, + BGL_NAMED_GRAPH& g) +{ + return add_edge(u, + add_vertex(v_name, g.derived()), + g.derived()); +} + +/// Add an edge using vertex descriptors or names to refer to the vertices +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, + BGL_NAMED_GRAPH& g) +{ + return add_edge(add_vertex(u_name, g.derived()), + v, + g.derived()); +} + +#undef BGL_NAMED_GRAPH +#undef BGL_NAMED_GRAPH_PARAMS + +/******************************************************************* + * 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 + * graphs. + */ +template::type> +struct maybe_named_graph : public named_graph +{ +}; + +/** + * A graph mixin that can provide a mapping from names to vertices, + * and use that mapping to simplify creation and manipulation of + * graphs. This partial specialization turns off this functionality + * when the @c VertexProperty does not have an internal vertex name. + */ +template +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. + void removing_vertex(Vertex) { } + + /// 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<> + optional + vertex_by_property(const bundled_vertex_property_type&) + { + 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. + void removing_vertex(Vertex) { } + + /// 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 + +#endif // BOOST_GRAPH_NAMED_GRAPH_HPP diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index f8b20d91..956fa7ed 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -123,6 +123,8 @@ test-suite graph_test : [ run make_maximal_planar_test.cpp ] + [ run named_vertices_test.cpp ] + [ run all_planar_input_files_test.cpp ../../filesystem/build ../../system/build diff --git a/test/named_vertices_test.cpp b/test/named_vertices_test.cpp new file mode 100644 index 00000000..b9cc9cdb --- /dev/null +++ b/test/named_vertices_test.cpp @@ -0,0 +1,91 @@ +// Copyright (C) 2007-2008 The Trustees of Indiana University. + +// 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) + +// Test support for named vertices in adjacency_list. +#include +#include +#include +#include +#include +#include +#include + +#ifdef BOOST_NO_EXCEPTIONS +void +boost::throw_exception(std::exception const& ex) +{ + std::cout << ex.what() << std::endl; + abort(); +} +#endif + +using namespace boost; + +/// City structure to be attached to each vertex +struct City { + City() {} + + City(const std::string& name, int population = -1) + : name(name), population(population) { } + + std::string name; + int population; +}; + +namespace boost { namespace graph { + +/// Use the City name as a key for indexing cities in a graph +template<> +struct internal_vertex_name +{ + typedef multi_index::member type; +}; + +/// Allow the graph to build cities given only their names (filling in +/// the defaults for fields). +template<> +struct internal_vertex_constructor +{ + typedef vertex_from_name type; +}; + +} } // end namespace boost::graph + +/// Our road map, where each of the vertices are cities +typedef adjacency_list RoadMap; +typedef graph_traits::vertex_descriptor Vertex; + +int test_main(int argc, char* argv[]) +{ + RoadMap map; + + /// Create vertices for Bloomington, Indianapolis, Chicago + Vertex bloomington = add_vertex(City("Bloomington", 69291), map); + Vertex indianapolis = add_vertex(City("Indianapolis", 791926), map); + Vertex chicago = add_vertex(City("Chicago", 9500000), map); + + BOOST_CHECK(add_vertex(City("Bloomington", 69291), map) == bloomington); + + BGL_FORALL_VERTICES(city, map, RoadMap) + std::cout << map[city].name << ", population " << map[city].population + << std::endl; + + BOOST_CHECK(*find_vertex("Bloomington", map) == bloomington); + BOOST_CHECK(*find_vertex("Indianapolis", map) == indianapolis); + BOOST_CHECK(*find_vertex("Chicago", map) == chicago); + + add_edge(bloomington, "Indianapolis", map); + add_edge("Indianapolis", chicago, map); + add_edge("Indianapolis", "Cincinnatti", map); + + BGL_FORALL_EDGES(road, map, RoadMap) + std::cout << map[source(road, map)].name << " -> " + << map[target(road, map)].name << std::endl; + + BOOST_CHECK(map[*find_vertex("Cincinnatti", map)].population == -1); + + return 0; +} From 33640c6bf30ff6f9e0314b488adf19c4192d5ee9 Mon Sep 17 00:00:00 2001 From: Douglas Gregor Date: Wed, 8 Oct 2008 15:05:33 +0000 Subject: [PATCH 025/224] Minor fixes for named graph changes [SVN r49179] --- include/boost/graph/named_graph.hpp | 2 ++ include/boost/pending/property.hpp | 6 ++++++ 2 files changed, 8 insertions(+) diff --git a/include/boost/graph/named_graph.hpp b/include/boost/graph/named_graph.hpp index efadd4e1..d9e800c5 100644 --- a/include/boost/graph/named_graph.hpp +++ b/include/boost/graph/named_graph.hpp @@ -17,6 +17,8 @@ #include #include #include +#include +#include // for std::runtime_error namespace boost { namespace graph { diff --git a/include/boost/pending/property.hpp b/include/boost/pending/property.hpp index f4d2cb91..e7e9e8f4 100644 --- a/include/boost/pending/property.hpp +++ b/include/boost/pending/property.hpp @@ -75,6 +75,12 @@ namespace boost { #endif }; + template + inline detail::error_property_not_found + get_property_value(const no_property& p, Tag2) { + return detail::error_property_not_found(); + } + template inline typename property_value, Tag2>::type& get_property_value(property& p, Tag2 tag2) { From b7a5fe292b0060970b1a12dc4d8cbd3297aad9f6 Mon Sep 17 00:00:00 2001 From: Douglas Gregor Date: Fri, 10 Oct 2008 13:24:44 +0000 Subject: [PATCH 026/224] Remove accidental commit [SVN r49248] --- build/Jamfile.v2 | 25 +------------------------ 1 file changed, 1 insertion(+), 24 deletions(-) diff --git a/build/Jamfile.v2 b/build/Jamfile.v2 index e3272262..7e8da510 100644 --- a/build/Jamfile.v2 +++ b/build/Jamfile.v2 @@ -57,27 +57,4 @@ lib boost_graph msvc-8.0:-GR- ; -boost-install boost_graph ; - -############################################################ -# Distributed-memory parallel graph library (Parallel BGL) # -############################################################ -use-project /boost/mpi : ../../mpi/build ; -import mpi ; -if [ mpi.configured ] -{ - lib boost_graph_mpi - : distributed/tag_allocator.cpp - distributed/mpi_process_group.cpp - : # Requirements - ../../mpi/build//boost_mpi - /mpi//mpi [ mpi.extra-requirements ] - ../../serialization/build//boost_serialization - : # Default build - shared - : # Usage requirements - ../../mpi/build//boost_mpi - /mpi//mpi [ mpi.extra-requirements ] - ../../serialization/build//boost_serialization - ; -} \ No newline at end of file +boost-install boost_graph ; \ No newline at end of file From b267aee59caf3c1ca039691a5b6a5053bca897fe Mon Sep 17 00:00:00 2001 From: John Maddock Date: Fri, 10 Oct 2008 16:10:00 +0000 Subject: [PATCH 027/224] Change includes of to . Previously if Boost.TR1 was in the include path then including pulls in all the new TR1 math functions, which in turn also requires linking to an external library. With auto-linking support this requires that library to have been built and be present in the library search path, even if the actual library under use is header only. Fixes #2392. [SVN r49254] --- include/boost/graph/circle_layout.hpp | 2 +- include/boost/graph/erdos_renyi_generator.hpp | 2 +- include/boost/graph/fruchterman_reingold.hpp | 2 +- include/boost/graph/gursoy_atun_layout.hpp | 2 +- include/boost/graph/kamada_kawai_spring_layout.hpp | 2 +- include/boost/graph/plod_generator.hpp | 2 +- include/boost/graph/wavefront.hpp | 2 +- include/boost/pending/fibonacci_heap.hpp | 2 +- 8 files changed, 8 insertions(+), 8 deletions(-) mode change 100755 => 100644 include/boost/graph/wavefront.hpp diff --git a/include/boost/graph/circle_layout.hpp b/include/boost/graph/circle_layout.hpp index b63f8165..26387d14 100644 --- a/include/boost/graph/circle_layout.hpp +++ b/include/boost/graph/circle_layout.hpp @@ -8,7 +8,7 @@ // Andrew Lumsdaine #ifndef BOOST_GRAPH_CIRCLE_LAYOUT_HPP #define BOOST_GRAPH_CIRCLE_LAYOUT_HPP -#include +#include #include #include diff --git a/include/boost/graph/erdos_renyi_generator.hpp b/include/boost/graph/erdos_renyi_generator.hpp index 188a3f18..605b0e17 100644 --- a/include/boost/graph/erdos_renyi_generator.hpp +++ b/include/boost/graph/erdos_renyi_generator.hpp @@ -19,7 +19,7 @@ #include #include #include -#include +#include namespace boost { diff --git a/include/boost/graph/fruchterman_reingold.hpp b/include/boost/graph/fruchterman_reingold.hpp index a93d2665..f5ea6af7 100644 --- a/include/boost/graph/fruchterman_reingold.hpp +++ b/include/boost/graph/fruchterman_reingold.hpp @@ -9,7 +9,7 @@ #ifndef BOOST_GRAPH_FRUCHTERMAN_REINGOLD_FORCE_DIRECTED_LAYOUT_HPP #define BOOST_GRAPH_FRUCHTERMAN_REINGOLD_FORCE_DIRECTED_LAYOUT_HPP -#include +#include #include #include #include diff --git a/include/boost/graph/gursoy_atun_layout.hpp b/include/boost/graph/gursoy_atun_layout.hpp index 3b6ccc5e..7cc1f973 100644 --- a/include/boost/graph/gursoy_atun_layout.hpp +++ b/include/boost/graph/gursoy_atun_layout.hpp @@ -15,7 +15,7 @@ // in EuroPar 2000, p. 234 of LNCS 1900 // http://springerlink.metapress.com/link.asp?id=pcu07ew5rhexp9yt -#include +#include #include #include #include diff --git a/include/boost/graph/kamada_kawai_spring_layout.hpp b/include/boost/graph/kamada_kawai_spring_layout.hpp index b210d490..00dbcb76 100644 --- a/include/boost/graph/kamada_kawai_spring_layout.hpp +++ b/include/boost/graph/kamada_kawai_spring_layout.hpp @@ -16,7 +16,7 @@ #include #include #include -#include +#include namespace boost { namespace detail { namespace graph { diff --git a/include/boost/graph/plod_generator.hpp b/include/boost/graph/plod_generator.hpp index a7800d04..9a63ec8f 100644 --- a/include/boost/graph/plod_generator.hpp +++ b/include/boost/graph/plod_generator.hpp @@ -16,7 +16,7 @@ #include #include #include -#include +#include namespace boost { diff --git a/include/boost/graph/wavefront.hpp b/include/boost/graph/wavefront.hpp old mode 100755 new mode 100644 index c5118406..00cf3524 --- a/include/boost/graph/wavefront.hpp +++ b/include/boost/graph/wavefront.hpp @@ -16,7 +16,7 @@ #include #include #include -#include +#include #include #include // for std::min and std::max diff --git a/include/boost/pending/fibonacci_heap.hpp b/include/boost/pending/fibonacci_heap.hpp index 76f28a8a..dfaae4a4 100644 --- a/include/boost/pending/fibonacci_heap.hpp +++ b/include/boost/pending/fibonacci_heap.hpp @@ -8,7 +8,7 @@ #if defined(__sgi) && !defined(__GNUC__) # include #else -# include +# include #endif #include #include From 71f20dd7b61ba5cf5e05fc8a8bd7f2991478a828 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=BCrgen=20Hunold?= Date: Fri, 10 Oct 2008 19:38:48 +0000 Subject: [PATCH 028/224] Add missing BOOST_GRAPH_DECL macro. [SVN r49256] --- 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 be7a804e..4197abd3 100644 --- a/include/boost/graph/graphml.hpp +++ b/include/boost/graph/graphml.hpp @@ -187,7 +187,7 @@ protected: template char* mutate_graph_impl::m_type_names[] = {"boolean", "int", "long", "float", "double", "string"}; -void +void BOOST_GRAPH_DECL read_graphml(std::istream& in, mutate_graph& g); template From ebde55caabf73acdca7a584df4dbd512e866b8ac Mon Sep 17 00:00:00 2001 From: Aaron Windsor Date: Thu, 16 Oct 2008 12:02:37 +0000 Subject: [PATCH 029/224] Patch from David Gleich to fix underflow and overflow that can happen when computing vertex positions in chroback_payne_straight_line_drawing [SVN r49358] --- include/boost/graph/chrobak_payne_drawing.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/boost/graph/chrobak_payne_drawing.hpp b/include/boost/graph/chrobak_payne_drawing.hpp index 6fb7b56d..e8a9104b 100644 --- a/include/boost/graph/chrobak_payne_drawing.hpp +++ b/include/boost/graph/chrobak_payne_drawing.hpp @@ -193,8 +193,8 @@ namespace boost delta_p_q += delta_x[temp]; } - delta_x[v] = (y[rightmost] - y[leftmost] + delta_p_q)/2; - y[v] = (y[rightmost] + y[leftmost] + delta_p_q)/2; + delta_x[v] = ((y[rightmost] + delta_p_q) - y[leftmost])/2; + y[v] = y[leftmost] + delta_x[v]; delta_x[rightmost] = delta_p_q - delta_x[v]; bool leftmost_and_rightmost_adjacent = right[leftmost] == rightmost; From 7db8d06fbffa9863c925bb2b571886da293cbd1d Mon Sep 17 00:00:00 2001 From: "Michael A. Jackson" Date: Sat, 1 Nov 2008 13:15:41 +0000 Subject: [PATCH 030/224] Continuing merge of CMake build system files into trunk with the encouragement of Doug Gregor [SVN r49510] --- CMakeLists.txt | 24 ++++++++++++++++++ module.cmake | 3 +++ src/CMakeLists.txt | 26 +++++++++++++++++++ test/CMakeLists.txt | 61 +++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 114 insertions(+) create mode 100644 CMakeLists.txt create mode 100644 module.cmake create mode 100644 src/CMakeLists.txt create mode 100644 test/CMakeLists.txt diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 00000000..139abdfc --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,24 @@ +#---------------------------------------------------------------------------- +# This file was automatically generated from the original CMakeLists.txt file +# Add a variable to hold the headers for the library +set (lib_headers + graph +) + +# Add a library target to the build system +boost_library_project( + graph + SRCDIRS src + TESTDIRS test + HEADERS ${lib_headers} + # DOCDIRS + DESCRIPTION "The BGL graph interface and graph components are generic, in the same sense as the the Standard Template Library (STL)." + MODULARIZED + AUTHORS "Jeremy Siek " + "Lie-Quan Lee" + "Andrew Lumsdaine" + "Douglas Gregor " + # MAINTAINERS +) + + diff --git a/module.cmake b/module.cmake new file mode 100644 index 00000000..b7015a64 --- /dev/null +++ b/module.cmake @@ -0,0 +1,3 @@ +boost_module(graph DEPENDS property_map tuple multi_index any) + +# any is there because of the dependency on boost/dynamic_property_map.hpp diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt new file mode 100644 index 00000000..786b8173 --- /dev/null +++ b/src/CMakeLists.txt @@ -0,0 +1,26 @@ +add_definitions(-DBOOST_GRAPH_NO_LIB=1) + +if (MSVC) + # Without these flags, MSVC 7.1 and 8.0 crash + add_definitions(-GR-) +endif (MSVC) + +set(BOOST_GRAPH_OPTIONAL_SOURCES "") +set(BOOST_GRAPH_OPTIONAL_LIBRARIES "") + +# Try to find the Expat library +include(FindEXPAT) +if (EXPAT_FOUND) + # We have Expat, so build the GraphML parser - TODO: Boost 1.34.x only +# set(BOOST_GRAPH_OPTIONAL_SOURCES +# ${BOOST_GRAPH_OPTIONAL_SOURCES} "graphml.cpp") + include_directories(${EXPAT_INCLUDE_DIRS}) + list(APPEND BOOST_GRAPH_OPTIONAL_LIBRARIES ${EXPAT_LIBRARIES}) +endif (EXPAT_FOUND) + +boost_add_library( + boost_graph + read_graphviz_spirit.cpp ${BOOST_GRAPH_OPTIONAL_SOURCES} + LINK_LIBS ${BOOST_GRAPH_OPTIONAL_LIBRARIES} + SHARED_COMPILE_FLAGS "-DBOOST_GRAPH_DYN_LINK=1" + ) diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt new file mode 100644 index 00000000..163a2931 --- /dev/null +++ b/test/CMakeLists.txt @@ -0,0 +1,61 @@ +boost_test_run(transitive_closure_test) +boost_test_compile(adj_list_cc) +boost_test_run(adj_list_edge_list_set) +boost_test_compile(adj_matrix_cc) +boost_test_run(bfs) +boost_test_compile(bfs_cc) +boost_test_run(bellman-test) +boost_test_run(betweenness_centrality_test DEPENDS boost_graph-shared) +boost_test_run(csr_graph_test) +boost_test_run(dag_longest_paths) +boost_test_run(dfs) +boost_test_compile(dfs_cc) +boost_test_compile(dijkstra_cc) +boost_test_run(dijkstra_heap_performance ARGS 10000 DEPENDS boost_graph-shared) +boost_test_run(dominator_tree_test) +boost_test_run(relaxed_heap_test ARGS 5000 15000) +boost_test_compile(edge_list_cc) +boost_test_compile(filtered_graph_cc) +boost_test_run(graph) +boost_test_compile(graph_concepts) +boost_test_run(graphviz_test + DEPENDS boost_test_exec_monitor boost_graph-static) +boost_test_run(gursoy_atun_layout_test) +boost_test_run(layout_test) +boost_test_run(serialize DEPENDS boost_serialization) +boost_test_compile(reverse_graph_cc) +boost_test_run(sequential_vertex_coloring) +boost_test_run(subgraph) +boost_test_run(isomorphism) +boost_test_run(adjacency_matrix_test) +boost_test_compile(vector_graph_cc) +boost_test_compile(copy) +boost_test_compile(property_iter) +boost_test_run(bundled_properties) +boost_test_run(floyd_warshall_test) +boost_test_run(astar_search_test) +boost_test_run(biconnected_components_test) +boost_test_run(cuthill_mckee_ordering) +boost_test_run(king_ordering) +boost_test_run(matching_test) +# boost_test_run(max_flow_test) +# boost_test_run(kolmogorov_max_flow_test) TODO: Boost 1.34.x only + +# GraphML Tests - not for Boost 1.34.x +#include(FindEXPAT) +#if (EXPAT_FOUND) +# include_directories(${EXPAT_INCLUDE_DIRS}) +# boost_test_run(graphml_test LIBRARIES boost_graph) +#endif (EXPAT_FOUND) + +# Stanford GraphBase Tests +if ($ENV{SDB}) + include_directories("$ENV{SDB}") + boost_test_compile(stanford_graph_cc) +endif ($ENV{SDB}) + +# LEDA tests +if ($ENV{LEDA}) + include_directories("$ENV{LEDA}/incl") + boost_test_compile(leda_graph_cc) +endif ($ENV{LEDA}) From 10d71f23654a60f32eb494836660ce6f65b2f05d Mon Sep 17 00:00:00 2001 From: Andrew Sutton Date: Mon, 3 Nov 2008 15:03:13 +0000 Subject: [PATCH 031/224] Added a compiler check to adjacency_list.hpp that checks for GCC >= 4.3 and defines BOOST_NO_HASH. Closes #2444. [SVN r49554] --- include/boost/graph/adjacency_list.hpp | 58 ++++++++++++++------------ 1 file changed, 32 insertions(+), 26 deletions(-) diff --git a/include/boost/graph/adjacency_list.hpp b/include/boost/graph/adjacency_list.hpp index 9f019f74..e75ed169 100644 --- a/include/boost/graph/adjacency_list.hpp +++ b/include/boost/graph/adjacency_list.hpp @@ -17,6 +17,12 @@ #include #include +// Thef 4.3 series deprecates hash_set and hash_map. +// TODO: Migrate this to Boost.Config. +#if __GNUC__ >= 4 && __GNUC_MINOR__ >= 3 +# define BOOST_NO_HASH +#endif + #if !defined BOOST_NO_HASH # ifdef BOOST_HASH_SET_HEADER # include BOOST_HASH_SET_HEADER @@ -60,7 +66,7 @@ namespace boost { #if !defined BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION #if !defined BOOST_NO_SLIST - struct slistS {}; + struct slistS {}; #endif struct vecS { }; @@ -132,35 +138,35 @@ namespace boost { struct bind_ { typedef std::vector type; }; }; - struct listS { + struct listS { template struct bind_ { typedef std::list type; }; }; - struct setS { + struct setS { template struct bind_ { typedef std::set > type; }; }; - struct multisetS { + struct multisetS { template struct bind_ { typedef std::multiset > type; }; }; #if !defined BOOST_NO_HASH - struct hash_setS { + struct hash_setS { template struct bind_ { typedef BOOST_STD_EXTENSION_NAMESPACE::hash_set > type; }; }; #endif - struct mapS { + struct mapS { template struct bind_ { typedef std::set > type; }; }; #if !defined BOOST_NO_HASH - struct hash_mapS { + struct hash_mapS { template struct bind_ { typedef BOOST_STD_EXTENSION_NAMESPACE::hash_set > type; }; }; @@ -199,54 +205,54 @@ namespace boost { struct parallel_edge_traits { }; template <> - struct parallel_edge_traits { + struct parallel_edge_traits { typedef allow_parallel_edge_tag type; }; template <> - struct parallel_edge_traits { + struct parallel_edge_traits { typedef allow_parallel_edge_tag type; }; #if !defined BOOST_NO_SLIST template <> - struct parallel_edge_traits { + struct parallel_edge_traits { typedef allow_parallel_edge_tag type; }; #endif template <> - struct parallel_edge_traits { + struct parallel_edge_traits { typedef disallow_parallel_edge_tag type; }; template <> - struct parallel_edge_traits { + struct parallel_edge_traits { typedef allow_parallel_edge_tag type; }; #if !defined BOOST_NO_HASH template <> struct parallel_edge_traits { - typedef disallow_parallel_edge_tag type; + typedef disallow_parallel_edge_tag type; }; #endif // mapS is obsolete, replaced with setS template <> - struct parallel_edge_traits { + struct parallel_edge_traits { typedef disallow_parallel_edge_tag type; }; #if !defined BOOST_NO_HASH template <> struct parallel_edge_traits { - typedef disallow_parallel_edge_tag type; + typedef disallow_parallel_edge_tag type; }; #endif namespace detail { - template struct is_random_access { + template struct is_random_access { enum { value = false}; typedef mpl::false_ type; }; template <> - struct is_random_access { - enum { value = true }; + struct is_random_access { + enum { value = true }; typedef mpl::true_ type; }; @@ -296,7 +302,7 @@ namespace boost { typedef typename container_gen::type EdgeContainer; typedef typename DirectedS::is_bidir_t BidirectionalT; typedef typename DirectedS::is_directed_t DirectedT; - typedef typename mpl::and_::type >::type on_edge_storage; public: typedef typename mpl::if_, - VertexListS, OutEdgeListS, DirectedS, + VertexListS, OutEdgeListS, DirectedS, #if !defined(BOOST_GRAPH_NO_BUNDLED_PROPERTIES) typename detail::retag_property_list::type, @@ -379,7 +385,7 @@ namespace boost { private: typedef adjacency_list self; typedef typename detail::adj_list_gen< - self, VertexListS, OutEdgeListS, DirectedS, + self, VertexListS, OutEdgeListS, DirectedS, vertex_property_type, edge_property_type, GraphProperty, EdgeListS >::type Base; @@ -397,7 +403,7 @@ namespace boost { typedef GraphProperty graph_property_type; - inline adjacency_list(const GraphProperty& p = GraphProperty()) + inline adjacency_list(const GraphProperty& p = GraphProperty()) : m_property(p) { } inline adjacency_list(const adjacency_list& x) @@ -413,7 +419,7 @@ namespace boost { } // Required by Mutable Graph - inline adjacency_list(vertices_size_type num_vertices, + inline adjacency_list(vertices_size_type num_vertices, const GraphProperty& p = GraphProperty()) : Base(num_vertices), m_property(p) { } @@ -529,12 +535,12 @@ namespace boost { get(T Bundle::* p, adjacency_list& g) { - typedef typename property_map, T Bundle::*>::type result_type; return result_type(&g, p); } - + template inline @@ -543,7 +549,7 @@ namespace boost { get(T Bundle::* p, adjacency_list const & g) { - typedef typename property_map, T Bundle::*>::const_type result_type; return result_type(&g, p); From 2fbbd52a0e3eed1ead3dcbae5266cd02d54ea4b0 Mon Sep 17 00:00:00 2001 From: Andrew Sutton Date: Mon, 3 Nov 2008 15:21:06 +0000 Subject: [PATCH 032/224] Fixed a compiler warning that complained about parentheses in a do loop. [SVN r49557] --- include/boost/graph/fruchterman_reingold.hpp | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/include/boost/graph/fruchterman_reingold.hpp b/include/boost/graph/fruchterman_reingold.hpp index f5ea6af7..10a4807b 100644 --- a/include/boost/graph/fruchterman_reingold.hpp +++ b/include/boost/graph/fruchterman_reingold.hpp @@ -137,11 +137,11 @@ struct grid_force_pairs std::size_t adj_end_column = column == columns - 1? column : column + 1; for (std::size_t other_row = adj_start_row; other_row <= adj_end_row; ++other_row) - for (std::size_t other_column = adj_start_column; + for (std::size_t other_column = adj_start_column; other_column <= adj_end_column; ++other_column) if (other_row != row || other_column != column) { // Repulse vertices in this bucket - bucket_t& other_bucket + bucket_t& other_bucket = buckets[other_row * columns + other_column]; for (v = other_bucket.begin(); v != other_bucket.end(); ++v) apply_force(*u, *v); @@ -301,20 +301,20 @@ fruchterman_reingold_force_directed_layout BOOST_USING_STD_MAX(); Dim disp_size = sqrt(displacement[*v].x * displacement[*v].x + displacement[*v].y * displacement[*v].y); - position[*v].x += displacement[*v].x / disp_size + position[*v].x += displacement[*v].x / disp_size * min BOOST_PREVENT_MACRO_SUBSTITUTION (disp_size, temp); - position[*v].y += displacement[*v].y / disp_size + position[*v].y += displacement[*v].y / disp_size * min BOOST_PREVENT_MACRO_SUBSTITUTION (disp_size, temp); - position[*v].x = min BOOST_PREVENT_MACRO_SUBSTITUTION - (width / 2, - max BOOST_PREVENT_MACRO_SUBSTITUTION(-width / 2, + position[*v].x = min BOOST_PREVENT_MACRO_SUBSTITUTION + (width / 2, + max BOOST_PREVENT_MACRO_SUBSTITUTION(-width / 2, position[*v].x)); position[*v].y = min BOOST_PREVENT_MACRO_SUBSTITUTION - (height / 2, - max BOOST_PREVENT_MACRO_SUBSTITUTION(-height / 2, + (height / 2, + max BOOST_PREVENT_MACRO_SUBSTITUTION(-height / 2, position[*v].y)); } - } while (temp = cool()); + } while ((temp = cool())); } namespace detail { From 8bde5765abaa53936e7023cf9dd628026901ae90 Mon Sep 17 00:00:00 2001 From: Andrew Sutton Date: Mon, 3 Nov 2008 15:22:52 +0000 Subject: [PATCH 033/224] Fixed warnings about conversion from c-str literals to char*. [SVN r49558] --- include/boost/graph/graphml.hpp | 98 ++++++++++++++++----------------- 1 file changed, 49 insertions(+), 49 deletions(-) diff --git a/include/boost/graph/graphml.hpp b/include/boost/graph/graphml.hpp index 4197abd3..531dee32 100644 --- a/include/boost/graph/graphml.hpp +++ b/include/boost/graph/graphml.hpp @@ -25,15 +25,15 @@ #include #include -namespace boost +namespace boost { ///////////////////////////////////////////////////////////////////////////// // Graph reader exceptions ///////////////////////////////////////////////////////////////////////////// -struct parse_error: public graph_exception +struct parse_error: public graph_exception { - parse_error(const std::string& error) {statement = "parse error: " + error;} + parse_error(const std::string& error) {statement = "parse error: " + error;} virtual ~parse_error() throw() {} virtual const char* what() const throw() {return statement.c_str();} std::string statement; @@ -48,14 +48,14 @@ public: virtual boost::any do_add_vertex() = 0; virtual std::pair do_add_edge(boost::any source, boost::any target) = 0; - - virtual void + + virtual void set_graph_property(const std::string& name, const std::string& value, const std::string& value_type) = 0; - virtual void + virtual void set_vertex_property(const std::string& name, boost::any vertex, const std::string& value, const std::string& value_type) = 0; - - virtual void + + virtual void set_edge_property(const std::string& name, boost::any edge, const std::string& value, const std::string& value_type) = 0; }; @@ -87,27 +87,27 @@ class mutate_graph_impl : public mutate_graph return std::make_pair(any(retval.first), retval.second); } - virtual void + virtual void set_graph_property(const std::string& name, const std::string& value, const std::string& value_type) { bool type_found = false; try { mpl::for_each(put_property - (name, m_dp, m_g, value, value_type, m_type_names, type_found)); + (name, m_dp, m_g, value, value_type, m_type_names, type_found)); } catch (bad_lexical_cast) { - throw parse_error("invalid value \"" + value + "\" for key " + + throw parse_error("invalid value \"" + value + "\" for key " + name + " of type " + value_type); } if (!type_found) - throw parse_error("unrecognized type \"" + value_type + + throw parse_error("unrecognized type \"" + value_type + "\" for key " + name); - + } - - virtual void + + virtual void set_vertex_property(const std::string& name, any vertex, const std::string& value, const std::string& value_type) { bool type_found = false; @@ -115,20 +115,20 @@ class mutate_graph_impl : public mutate_graph { mpl::for_each(put_property (name, m_dp, any_cast(vertex), - value, value_type, m_type_names, type_found)); + value, value_type, m_type_names, type_found)); } catch (bad_lexical_cast) { - throw parse_error("invalid value \"" + value + "\" for key " + + throw parse_error("invalid value \"" + value + "\" for key " + name + " of type " + value_type); } if (!type_found) - throw parse_error("unrecognized type \"" + value_type + + throw parse_error("unrecognized type \"" + value_type + "\" for key " + name); - + } - - virtual void + + virtual void set_edge_property(const std::string& name, any edge, const std::string& value, const std::string& value_type) { bool type_found = false; @@ -136,15 +136,15 @@ class mutate_graph_impl : public mutate_graph { mpl::for_each(put_property (name, m_dp, any_cast(edge), - value, value_type, m_type_names, type_found)); + value, value_type, m_type_names, type_found)); } catch (bad_lexical_cast) { - throw parse_error("invalid value \"" + value + "\" for key " + + throw parse_error("invalid value \"" + value + "\" for key " + name + " of type " + value_type); } if (!type_found) - throw parse_error("unrecognized type \"" + value_type + + throw parse_error("unrecognized type \"" + value_type + "\" for key " + name); } @@ -152,11 +152,11 @@ class mutate_graph_impl : public mutate_graph class put_property { public: - put_property(const std::string& name, dynamic_properties& dp, const Key& key, - const std::string& value, const std::string& value_type, - char** type_names, bool& type_found) - : m_name(name), m_dp(dp), m_key(key), m_value(value), - m_value_type(value_type), m_type_names(type_names), + put_property(const std::string& name, dynamic_properties& dp, const Key& key, + const std::string& value, const std::string& value_type, + const char** type_names, bool& type_found) + : m_name(name), m_dp(dp), m_key(key), m_value(value), + m_value_type(value_type), m_type_names(type_names), m_type_found(type_found) {} template void operator()(Value) @@ -173,19 +173,19 @@ class mutate_graph_impl : public mutate_graph const Key& m_key; const std::string& m_value; const std::string& m_value_type; - char** m_type_names; + const char** m_type_names; bool& m_type_found; - }; - + }; + protected: MutableGraph& m_g; dynamic_properties& m_dp; typedef mpl::vector value_types; - static char* m_type_names[]; + static const char* m_type_names[]; }; template -char* mutate_graph_impl::m_type_names[] = {"boolean", "int", "long", "float", "double", "string"}; +const char* mutate_graph_impl::m_type_names[] = {"boolean", "int", "long", "float", "double", "string"}; void BOOST_GRAPH_DECL read_graphml(std::istream& in, mutate_graph& g); @@ -193,7 +193,7 @@ read_graphml(std::istream& in, mutate_graph& g); template void read_graphml(std::istream& in, MutableGraph& g, dynamic_properties& dp) -{ +{ mutate_graph_impl mg(g,dp); read_graphml(in, mg); } @@ -202,7 +202,7 @@ template class get_type_name { public: - get_type_name(const std::type_info& type, char** type_names, std::string& type_name) + get_type_name(const std::type_info& type, const char** type_names, std::string& type_name) : m_type(type), m_type_names(type_names), m_type_name(type_name) {} template void operator()(Type) @@ -212,7 +212,7 @@ public: } private: const std::type_info &m_type; - char** m_type_names; + const char** m_type_names; std::string &m_type_name; }; @@ -226,22 +226,22 @@ write_graphml(std::ostream& out, const Graph& g, VertexIndexMap vertex_index, typedef typename graph_traits::edge_descriptor edge_descriptor; typedef typename graph_traits::vertex_descriptor vertex_descriptor; - BOOST_STATIC_CONSTANT(bool, - graph_is_directed = + BOOST_STATIC_CONSTANT(bool, + graph_is_directed = (is_convertible::value)); out << "\n" << "\n"; typedef mpl::vector value_types; - char* type_names[] = {"boolean", "int", "int", "int", "int", "long", "long", "long", "long", "float", "double", "double", "string"}; + const char* type_names[] = {"boolean", "int", "int", "int", "int", "long", "long", "long", "long", "float", "double", "double", "string"}; std::map graph_key_ids; std::map vertex_key_ids; std::map edge_key_ids; int key_count = 0; // Output keys - for (dynamic_properties::const_iterator i = dp.begin(); i != dp.end(); ++i) + 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)) @@ -254,14 +254,14 @@ write_graphml(std::ostream& out, const Graph& g, VertexIndexMap vertex_index, continue; 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")) << "\"" << " attr.name=\"" << i->first << "\"" << " attr.type=\"" << type_name << "\"" << " />\n"; } - out << " \n"; @@ -269,13 +269,13 @@ 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)) { out << " first] << "\">" << i->second->get_string(g) << "\n"; } } - + typedef typename graph_traits::vertex_iterator vertex_iterator; vertex_iterator v, v_end; for (tie(v, v_end) = vertices(g); v != v_end; ++v) @@ -284,7 +284,7 @@ write_graphml(std::ostream& out, const Graph& g, VertexIndexMap vertex_index, // Output data for (dynamic_properties::const_iterator i = dp.begin(); i != dp.end(); ++i) { - if (i->second->key() == typeid(vertex_descriptor)) + if (i->second->key() == typeid(vertex_descriptor)) { out << " first] << "\">" << i->second->get_string(*v) << "\n"; @@ -296,7 +296,7 @@ write_graphml(std::ostream& out, const Graph& g, VertexIndexMap vertex_index, typedef typename graph_traits::edge_iterator edge_iterator; edge_iterator e, e_end; typename graph_traits::edges_size_type edge_count = 0; - for (tie(e, e_end) = edges(g); e != e_end; ++e) + for (tie(e, e_end) = edges(g); e != e_end; ++e) { out << " second->key() == typeid(edge_descriptor)) + if (i->second->key() == typeid(edge_descriptor)) { out << " first] << "\">" << i->second->get_string(*e) << "\n"; @@ -321,7 +321,7 @@ write_graphml(std::ostream& out, const Graph& g, VertexIndexMap vertex_index, template void -write_graphml(std::ostream& out, const Graph& g, const dynamic_properties& dp, +write_graphml(std::ostream& out, const Graph& g, const dynamic_properties& dp, bool ordered_vertices=false) { write_graphml(out, g, get(vertex_index, g), dp, ordered_vertices); From 1562d2b1abd0aa5f465b18fa8e4bae2e2fb4d492 Mon Sep 17 00:00:00 2001 From: Andrew Sutton Date: Mon, 3 Nov 2008 15:35:58 +0000 Subject: [PATCH 034/224] Added metric_tsp_approx by Matt Egahazy. Import includes the algorithm, documentation and tests. Integrated the test into the unit tests, and the documentation into the TOC under a new subsection named Paths and Tours. Also added a new bad_graph exception in exception.hpp. [SVN r49561] --- doc/TSPTourVisitor.html | 99 +++++++ doc/metric_tsp_approx.html | 204 ++++++++++++++ doc/table_of_contents.html | 108 ++++---- doc/tsp_tour_len_visitor.html | 123 +++++++++ doc/tsp_tour_visitor.html | 96 +++++++ include/boost/graph/exception.hpp | 51 ++-- include/boost/graph/metric_tsp_approx.hpp | 313 +++++++++++++++++++++ test/Jamfile.v2 | 60 ++-- test/metric_tsp_approx.cpp | 319 ++++++++++++++++++++++ test/metric_tsp_approx.txt | 8 + 10 files changed, 1270 insertions(+), 111 deletions(-) create mode 100644 doc/TSPTourVisitor.html create mode 100644 doc/metric_tsp_approx.html create mode 100644 doc/tsp_tour_len_visitor.html create mode 100644 doc/tsp_tour_visitor.html create mode 100644 include/boost/graph/metric_tsp_approx.hpp create mode 100644 test/metric_tsp_approx.cpp create mode 100644 test/metric_tsp_approx.txt diff --git a/doc/TSPTourVisitor.html b/doc/TSPTourVisitor.html new file mode 100644 index 00000000..bf6ca0e2 --- /dev/null +++ b/doc/TSPTourVisitor.html @@ -0,0 +1,99 @@ + + + +Boost Graph Library: TSP Tour Visitor + +C++ Boost + +
    + +

    TSP Tour Visitor concept

    + +This concept defines the visitor interface for
    metric_tsp_approx() +and related algorithms. The user can create a class that matches this +interface, and then pass objects of the class into +metric_tsp_approx() to augment the actions taken during +the search. + +

    Refinement of

    + +none + +

    Notation

    + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    VA type that is a model of Dijkstra Visitor.
    visAn object of type V.
    GA type that is a model of Graph.
    gAn object of type G.
    vAn object of type boost::graph_traits<G>::vertex_descriptor.
    + +

    Associated Types

    + +none + +

    + +

    Valid Expressions

    + + + + + + + + + + + + + +
    NameExpressionReturn TypeDescription
    Visit Vertexvis.visit_vertex(v, g)void +This is invoked on each vertex of the graph when it is visited as part of the TSP tour. +
    + +

    Models

    + + + +
    +
    + + +
    Copyright © 2008 +Matyas Egyhazy
    + + + diff --git a/doc/metric_tsp_approx.html b/doc/metric_tsp_approx.html new file mode 100644 index 00000000..49bc713c --- /dev/null +++ b/doc/metric_tsp_approx.html @@ -0,0 +1,204 @@ + + + +Boost Graph Library: Metric Traveling Salesperson Approximation + +C++ Boost + +
    + + + +

    +metric_tsp_approx +

    + +

    +

    +template <typename VertexListGraph,
    +          typename WeightMap,
    +          typename VertexIndexMap,
    +          typename TSPVertexVisitor>
    +void metric_tsp_approx_from_vertex(
    +        const VertexListGraph& g,
    +        typename graph_traits<VertexListGraph>::vertex_descriptor start,
    +        WeightMap weightmap,
    +        VertexIndexMap indexmap,
    +        TSPVertexVisitor vis)
    +
    +// Overloads
    +template<typename VertexListGraph, typename OutputIterator>
    +void metric_tsp_approx_tour(VertexListGraph& g, OutputIterator o)
    +
    +template<typename VertexListGraph, typename WeightMap, typename OutputIterator>
    +void metric_tsp_approx_tour(VertexListGraph& g, WeightMap w,
    +    OutputIterator o)
    +
    +template<typename VertexListGraph, typename OutputIterator>
    +void metric_tsp_approx_tour_from_vertex(VertexListGraph& g,
    +    typename graph_traits<VertexListGraph>::vertex_descriptor start,
    +    OutputIterator o)
    +
    +template<typename VertexListGraph, typename WeightMap,
    +    typename OutputIterator>
    +void metric_tsp_approx_tour_from_vertex(VertexListGraph& g,
    +    typename graph_traits<VertexListGraph>::vertex_descriptor start,
    +    WeightMap w, OutputIterator o)
    +
    +// visitor versions
    +template<typename VertexListGraph, typename TSPVertexVisitor>
    +void metric_tsp_approx(VertexListGraph& g, TSPVertexVisitor vis)
    +
    +template<typename VertexListGraph, typename Weightmap,
    +    typename VertexIndexMap, typename TSPVertexVisitor>
    +void metric_tsp_approx(VertexListGraph& g, Weightmap w,
    +    TSPVertexVisitor vis)
    +
    +template<typename VertexListGraph, typename WeightMap,
    +    typename VertexIndexMap, typename TSPVertexVisitor>
    +void metric_tsp_approx(VertexListGraph& g, WeightMap w, VertexIndexMap id,
    +    TSPVertexVisitor vis)
    +
    +template<typename VertexListGraph, typename WeightMap,
    +    typename TSPVertexVisitor>
    +void metric_tsp_approx_from_vertex(VertexListGraph& g,
    +    typename graph_traits<VertexListGraph>::vertex_descriptor start,
    +    WeightMap w, TSPVertexVisitor vis)
    +
    +
    + +

    +This is a traveling salesperson heuristic for generating a tour of vertices +for a fully connected undirected graph with weighted edges that obey the triangle inequality. +The current implementation is based off of the algorithm presented in Introduction to Algorithms +on page 1029. This implementation generates solutions that are twice as long as the optimal tour in the worst case. +The pseudo-code is listed below. +

    + + + + + +
    +
    +TSP-APPROX(G, w)
    +  select a vertex r in V[G]
    +  compute a minimum spanning tree T for G from root r
    +    using PRIM-MST(G, r, w)
    +  let L be the list of vertices visited in a preorder traversal of T
    +  return (the Hamiltonian cycle H that visites the vertices in the order L)
    +
    +
    + + +

    Where Defined

    + +

    +boost/graph/metric_tsp_approx.hpp + +

    + +

    Parameters

    + +IN: const Graph& g +
    + An undirected graph. The type Graph must be a + model of Vertex List Graph + and Incidence Graph [2].
    +
    + +IN: vertex_descriptor start +
    + The vertex that will be the start (and end) of the tour.
    + Default: *vertices(g).first +
    + +IN: WeightMap weightmap +
    + The weight 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.
    + Default: get(edge_weight, g)
    +
    + +IN: VertexIndexMap indexmap +
    + This maps each vertex to an integer in the range [0, + num_vertices(g)). This is necessary for efficient updates of the + heap data structure when an edge is relaxed. The type + VertexIndexMap must be a model of + Readable Property Map. The value type of the map must be an + integer type. The vertex descriptor type of the graph needs to be + usable as the key type of the map.
    + 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. +
    +
    + +OUT: OutputIterator o +
    + The OutputIterator holds the vertices of the tour. + The type OutputIterator must be a model of the + OutputIterator concept. +
    + +OUT: TSPTourVisitor vis +
    + Use this to specify actions that you would like to happen + when the algorithm visits a vertex of the tour. + The type TSPTourVisitor must be a model of the TSP Tour Visitor + concept. + The visitor object is passed by value [1].
    +
    + +

    Complexity

    + +

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

    + +

    Example

    + +

    +The file examples/metric_tsp_approx_example.cpp +contains an example of using this TSP approximation algorithm. + + +

    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. +

    +

    [2] + Passing an adjacency_list with a vertex not set selected by + vecS will result in O(n2) performance. +

    +
    + + +
    Copyright © 2008 +Matyas Egyhazy +
    + + + diff --git a/doc/table_of_contents.html b/doc/table_of_contents.html index c7c86a61..2c54bab7 100644 --- a/doc/table_of_contents.html +++ b/doc/table_of_contents.html @@ -8,10 +8,10 @@ --> Table of Contents: Boost Graph Library - -C++ Boost + +C++ Boost
    @@ -70,25 +70,28 @@
  • DFS Visitor
  • Dijkstra Visitor
  • Bellman Ford Visitor -
  • A* Visitor
  • +
  • A* Visitor
  • Event Visitor -
  • Planar Face Visitor +
  • Planar Face Visitor +
  • TSP Tour Visitor
  • EventVisitorList Adaptors
      -
    1. Event Visitor List -
    2. bfs_visitor -
    3. dfs_visitor -
    4. dijkstra_visitor -
    5. bellman_visitor -
    6. astar_visitor
    7. +
    8. Event Visitor List +
    9. bfs_visitor +
    10. dfs_visitor +
    11. dijkstra_visitor +
    12. bellman_visitor +
    13. astar_visitor
  • Event Visitors
      -
    1. predecessor_recorder -
    2. distance_recorder -
    3. time_stamper -
    4. property_writer +
    5. predecessor_recorder +
    6. distance_recorder +
    7. time_stamper +
    8. property_writer +
    9. tsp_tour_visitor
    10. +
    11. tsp_tour_len_visitor
  • Graph classes
      @@ -152,28 +155,28 @@
    1. prim_minimum_spanning_tree
    -
  • Connected Components Algorithms -
      -
    1. connected_components -
    2. strong_components - -
    3. biconnected_components -
    4. articulation_points -
    5. Incremental Connected Components -
        -
      1. initialize_incremental_components -
      2. incremental_components -
      3. same_component -
      4. component_index -
      -
  • +
  • Connected Components Algorithms +
      +
    1. connected_components +
    2. strong_components + +
    3. biconnected_components +
    4. articulation_points +
    5. Incremental Connected Components +
        +
      1. initialize_incremental_components +
      2. incremental_components +
      3. same_component +
      4. component_index +
      +
  • Maximum Flow and Matching Algorithms
    1. edmunds_karp_max_flow
    2. push_relabel_max_flow
    3. kolmogorov_max_flow
    4. -
    5. edmonds_maximum_cardinality_matching +
    6. edmonds_maximum_cardinality_matching
  • Sparse Matrix Ordering Algorithms @@ -184,34 +187,39 @@
  • minimum_degree_ordering
  • -
  • topological_sort -
  • transitive_closure -
  • copy_graph -
  • transpose_graph -
  • isomorphism - -
  • sequential_vertex_coloring -
  • sloan_ordering
  • +
  • topological_sort +
  • transitive_closure +
  • copy_graph +
  • transpose_graph +
  • isomorphism + +
  • Path and Tour Algorithms +
      +
    1. metric_tsp_approx
    2. +
    +
  • + +
  • sequential_vertex_coloring +
  • sloan_ordering
  • sloan_start_end_vertices
  • ith_wavefront, max_wavefront, aver_wavefront, and rms_wavefront
  • brandes_betweenness_centrality
  • Layout algorithms
      -
    1. random_graph_layout
    2. +
    3. random_graph_layout
    4. circle_layout
    5. kamada_kawai_spring_layout
    6. -
    7. fruchterman_reingold_force_directed_layout
    8. +
    9. fruchterman_reingold_force_directed_layout
    10. gursoy_atun_layout
    11. -
    -
  • + +
  • Clustering algorithms -
      +
      1. betweenness_centrality_clustering
      2. -
      +
  • -
  • astar_search
  • +
  • astar_search
  • lengauer_tarjan_dominator_tree
  • minimum_cycle_ratio and maximum_cycle_ratio
  • Planar Graph Algorithms @@ -293,4 +301,4 @@ HREF="mailto:lums@osl.iu.edu">lums@osl.iu.edu) - + diff --git a/doc/tsp_tour_len_visitor.html b/doc/tsp_tour_len_visitor.html new file mode 100644 index 00000000..d972e9d3 --- /dev/null +++ b/doc/tsp_tour_len_visitor.html @@ -0,0 +1,123 @@ + + + +Boost Graph Library: tsp_tour_len_visitor + +C++ Boost + +
    + +

    +
    +tsp_tour_len_visitor<Graph, WeightMap, OutputIterator, Length>
    +
    +

    + +This type is a TSP tour visitor. It supplies the OutputIterator with the vertices of the tour and +records the total length of the tour. + +

    Example

    + +
    +double d(0.0);
    +std::vector<Vertex> c;
    +boost::metric_tsp_approx
    +  (g, get(edge_weight, g),
    +  make_tsp_tour_len_visitor(g, std::back_inserter(c), d, get(edge_weight, g)));
    +
    + + +

    Model of

    + +TSP Tour Visitor + +

    Template Parameters

    + +

    + + + + + + + + + + + + + + + + + + + + + + + + + +
    ParameterDescriptionDefault
    Graph +The graph type +None
    WeightMap +The weight 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. +None
    OutputIterator +An OutputIterator +None
    Length +A suitable container for the length of the tour. It must implement additive operators. +None
    + +

    Where Defined

    + +

    + +boost/graph/metric_tsp_approx.hpp + +

    Member Functions

    + +This class implements all of the member functions required by TSPTourVisitor. + +

    Non-Member Functions

    + + + + + + + + +
    FunctionDescription
    +template <typename Graph, typename WeightMap, typename OutputIterator, typename Length>
    +tsp_tour_len_visitor<OutputIterator>
    +make_tsp_tour_len_visitor(Graph const& g, OutIter iter, Length& l, WeightMap map) +
    +Returns a tour_len_visitor that records the TSP tour in the OutputIterator parameter and the tour's length in the Length parameter. +
    + +

    See Also

    + +None + +
    +
    + + +
    Copyright © 2008 +Matyas Egyhazy +
    + + + diff --git a/doc/tsp_tour_visitor.html b/doc/tsp_tour_visitor.html new file mode 100644 index 00000000..dc34393a --- /dev/null +++ b/doc/tsp_tour_visitor.html @@ -0,0 +1,96 @@ + + + +Boost Graph Library: tsp_tour_visitor + +C++ Boost + +
    + +

    +
    +tsp_tour_visitor<OutputIterator>
    +
    +

    + +This type is a simple TSP tour visitor. It supplies the OutputIterator with the vertices of the tour. + +

    Example

    + +
    +std::vector<Vertex> c;
    +boost::metric_tsp_approx
    +  (g, get(edge_weight, g), make_tsp_tour_visitor(std::back_inserter(c));
    +
    + + +

    Model of

    + +TSP Tour Visitor + +

    Template Parameters

    + +

    + + + + + + + + + + +
    ParameterDescriptionDefault
    OutputIterator +An OutputIterator +None
    + +

    Where Defined

    + +

    + +boost/graph/metric_tsp_approx.hpp + +

    Member Functions

    + +This class implements all of the member functions required by TSPTourVisitor. + +

    Non-Member Functions

    + + + + + + + + +
    FunctionDescription
    +template <typename OutputIterator>
    +tsp_tour_visitor<OutputIterator>
    +make_tsp_tour_visitor(OutputIterator iter) +
    +Returns a simple tsp_tour_visitor that records the TSP tour in the OutputIterator parameter +
    + +

    See Also

    + +None + +
    +
    + + +
    Copyright © 2008 +Matyas Egyhazy +
    + + + diff --git a/include/boost/graph/exception.hpp b/include/boost/graph/exception.hpp index 09c82edc..382d6719 100644 --- a/include/boost/graph/exception.hpp +++ b/include/boost/graph/exception.hpp @@ -15,29 +15,40 @@ namespace boost { - struct bad_graph : public std::invalid_argument { - bad_graph(const std::string& what_arg) - : std::invalid_argument(what_arg) { } - }; + struct bad_graph : public std::invalid_argument { + bad_graph(const std::string& what_arg) + : std::invalid_argument(what_arg) { } + }; - struct not_a_dag : public bad_graph { - not_a_dag() - : bad_graph("The graph must be a DAG.") { } - }; + struct not_a_dag : public bad_graph { + not_a_dag() + : bad_graph("The graph must be a DAG.") + { } + }; - struct negative_edge : public bad_graph { - negative_edge() - : bad_graph("The graph may not contain an edge with negative weight."){ } - }; + struct negative_edge : public bad_graph { + negative_edge() + : bad_graph("The graph may not contain an edge with negative weight.") + { } + }; - struct negative_cycle : public bad_graph { - negative_cycle() - : bad_graph("The graph may not contain negative cycles.") { } - }; - struct not_connected : public bad_graph { - not_connected() - : bad_graph("The graph must be connected.") { } - }; + struct negative_cycle : public bad_graph { + negative_cycle() + : bad_graph("The graph may not contain negative cycles.") + { } + }; + + struct not_connected : public bad_graph { + not_connected() + : bad_graph("The graph must be connected.") + { } + }; + + struct not_complete : public bad_graph { + not_complete() + : bad_graph("The graph must be complete.") + { } + }; } // namespace boost diff --git a/include/boost/graph/metric_tsp_approx.hpp b/include/boost/graph/metric_tsp_approx.hpp new file mode 100644 index 00000000..cf56aa2e --- /dev/null +++ b/include/boost/graph/metric_tsp_approx.hpp @@ -0,0 +1,313 @@ + +//======================================================================= +// Copyright 2008 +// Author: Matyas W Egyhazy +// +// 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_METRIC_TSP_APPROX_HPP +#define BOOST_GRAPH_METRIC_TSP_APPROX_HPP + +// metric_tsp_approx +// Generates an approximate tour solution for the traveling salesperson +// problem in polynomial time. The current algorithm guarantees a tour with a +// length at most as long as 2x optimal solution. The graph should have +// 'natural' (metric) weights such that the triangle inequality is maintained. +// Graphs must be fully interconnected. + +// TODO: +// There are a couple of improvements that could be made. +// 1) Change implementation to lower uppper bound Christofides heuristic +// 2) Implement a less restrictive TSP heuristic (one that does not rely on +// triangle inequality). +// 3) Determine if the algorithm can be implemented without creating a new +// graph. + +#include + +#include +#include +#include +#include +#include +#include + + +namespace boost +{ + // Define a concept for the concept-checking library. + template + struct TSPVertexVisitorConcept + { + private: + Visitor vis_; + public: + typedef typename graph_traits::vertex_descriptor Vertex; + + BOOST_CONCEPT_USAGE(TSPVertexVisitorConcept) + { + Visitor vis(vis_); // require copy construction + Graph g(1); + Vertex v(*vertices(g).first); + vis_.visit_vertex(v, g); // require visit_vertex + } + }; + + // Tree visitor that keeps track of a preorder traversal of a tree + // TODO: Consider migrating this to the graph_as_tree header. + // TODO: Parameterize the underlying stores o it doesn't have to be a vector. + template class PreorderTraverser + { + private: + std::vector& path_; + public: + typedef typename std::vector::const_iterator const_iterator; + + PreorderTraverser(std::vector& p) : path_(p) {} + + void preorder(Node n, const Tree& t) + { path_.push_back(n); } + + void inorder(Node n, const Tree& t) const {} + void postorder(Node, const Tree& t) const {} + + const_iterator begin() const { return path_.begin(); } + const_iterator end() const { return path_.end(); } + }; + + // Forward declarations + template class tsp_tour_visitor; + template class tsp_tour_len_visitor; + + template + void metric_tsp_approx_tour(VertexListGraph& g, OutputIterator o) + { + metric_tsp_approx_from_vertex(g, *vertices(g).first, + get(edge_weight, g), get(vertex_index, g), + tsp_tour_visitor(o)); + } + + template + void metric_tsp_approx_tour(VertexListGraph& g, WeightMap w, OutputIterator o) + { + metric_tsp_approx_from_vertex(g, *vertices(g).first, + w, tsp_tour_visitor(o)); + } + + template + void metric_tsp_approx_tour_from_vertex(VertexListGraph& g, + typename graph_traits::vertex_descriptor start, + OutputIterator o) + { + metric_tsp_approx_from_vertex(g, start, get(edge_weight, g), + get(vertex_index, g), tsp_tour_visitor(o)); + } + + template + void metric_tsp_approx_tour_from_vertex(VertexListGraph& g, + typename graph_traits::vertex_descriptor start, + WeightMap w, OutputIterator o) + { + metric_tsp_approx_from_vertex(g, start, w, get(vertex_index, g), + tsp_tour_visitor(o)); + } + + template + void metric_tsp_approx(VertexListGraph& g, TSPVertexVisitor vis) + { + metric_tsp_approx_from_vertex(g, *vertices(g).first, + get(edge_weight, g), get(vertex_index, g), vis); + } + + template + void metric_tsp_approx(VertexListGraph& g, Weightmap w, + TSPVertexVisitor vis) + { + metric_tsp_approx_from_vertex(g, *vertices(g).first, w, + get(vertex_index, g), vis); + } + + template + void metric_tsp_approx(VertexListGraph& g, WeightMap w, VertexIndexMap id, + TSPVertexVisitor vis) + { + metric_tsp_approx_from_vertex(g, *vertices(g).first, w, id, vis); + } + + template + void metric_tsp_approx_from_vertex(VertexListGraph& g, + typename graph_traits::vertex_descriptor start, + WeightMap w, TSPVertexVisitor vis) + { + metric_tsp_approx_from_vertex(g, start, w, get(vertex_index, g), vis); + } + + template < + typename VertexListGraph, + typename WeightMap, + typename VertexIndexMap, + typename TSPVertexVisitor> + void metric_tsp_approx_from_vertex(const VertexListGraph& g, + typename graph_traits::vertex_descriptor start, + WeightMap weightmap, + VertexIndexMap indexmap, + TSPVertexVisitor vis) + { + using namespace boost; + using namespace std; + + BOOST_CONCEPT_ASSERT((VertexListGraphConcept)); + BOOST_CONCEPT_ASSERT((TSPVertexVisitorConcept)); + + // Types related to the input graph (GVertex is a template parameter). + typedef typename graph_traits::vertex_descriptor GVertex; + typedef typename graph_traits::vertex_iterator GVItr; + + // 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; + + // And then re-cast it as a tree. + typedef iterator_property_map::iterator, property_map::type> ParentMap; + typedef graph_as_tree Tree; + typedef tree_traits::node_descriptor Node; + + // A predecessor map. + typedef vector PredMap; + typedef iterator_property_map PredPMap; + + PredMap preds(num_vertices(g)); + PredPMap pred_pmap(preds.begin(), indexmap); + + // Compute a spanning tree over the in put g. + prim_minimum_spanning_tree(g, pred_pmap, + root_vertex(start) + .vertex_index_map(indexmap) + .weight_map(weightmap)); + + // Build a MST using the predecessor map from prim mst + MSTImpl mst(num_vertices(g)); + std::size_t cnt = 0; + pair mst_verts(vertices(mst)); + for(typename PredMap::iterator vi(preds.begin()); vi != preds.end(); ++vi, ++cnt) + { + if(indexmap[*vi] != cnt) { + add_edge(*next(mst_verts.first, indexmap[*vi]), + *next(mst_verts.first, cnt), mst); + } + } + + // Build a tree abstraction over the MST. + vector parent(num_vertices(mst)); + Tree t(mst, *vertices(mst).first, + make_iterator_property_map(parent.begin(), + get(vertex_index, mst))); + + // Create tour using a preorder traversal of the mst + vector tour; + PreorderTraverser tvis(tour); + traverse_tree(0, t, tvis); + + pair g_verts(vertices(g)); + for(PreorderTraverser::const_iterator curr(tvis.begin()); + curr != tvis.end(); ++curr) + { + // TODO: This is will be O(n^2) if vertex storage of g != vecS. + GVertex v = *next(g_verts.first, get(vertex_index, mst)[*curr]); + vis.visit_vertex(v, g); + } + + // Connect back to the start of the tour + vis.visit_vertex(*g_verts.first, g); + } + + // Default tsp tour visitor that puts the tour in an OutputIterator + template + class tsp_tour_visitor + { + OutItr itr_; + public: + tsp_tour_visitor(OutItr itr) + : itr_(itr) + { } + + template + void visit_vertex(Vertex v, const Graph& g) + { + BOOST_CONCEPT_ASSERT((OutputIterator)); + *itr_++ = v; + } + + }; + + // Tsp tour visitor that adds the total tour length. + template + class tsp_tour_len_visitor + { + typedef typename graph_traits::vertex_descriptor Vertex; + BOOST_CONCEPT_ASSERT((OutputIterator)); + + OutIter iter_; + Length& tourlen_; + WeightMap& wmap_; + Vertex previous_; + + // Helper function for getting the null vertex. + Vertex null() + { return graph_traits::null_vertex(); } + + public: + tsp_tour_len_visitor(Graph const&, OutIter iter, Length& l, WeightMap map) + : iter_(iter), tourlen_(l), wmap_(map), previous_(null()) + { } + + void visit_vertex(Vertex v, const Graph& g) + { + typedef typename graph_traits::edge_descriptor Edge; + + // If it is not the start, then there is a + // previous vertex + if(previous_ != null()) + { + // NOTE: For non-adjacency matrix graphs g, this bit of code + // will be linear in the degree of previous_ or v. A better + // solution would be to visit edges of the graph, but that + // would require revisiting the core algorithm. + Edge e; + bool found; + tie(e, found) = edge(previous_, v, g); + if(!found) { + throw not_complete(); + } + + tourlen_ += wmap_[e]; + } + + previous_ = v; + *iter_++ = v; + } + }; + + // Object generator(s) + template + inline tsp_tour_visitor + make_tsp_tour_visitor(OutIter iter) + { return tsp_tour_visitor(iter); } + + template + inline tsp_tour_len_visitor + make_tsp_tour_len_visitor(Graph const& g, OutIter iter, Length& l, WeightMap map) + { return tsp_tour_len_visitor(g, iter, l, map); } + +} //boost + +#endif // BOOST_GRAPH_METRIC_TSP_APPROX_HPP \ No newline at end of file diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 956fa7ed..59cbff54 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -4,7 +4,7 @@ # (See accompanying file LICENSE_1_0.txt or copy at # http://www.boost.org/LICENSE_1_0.txt) -# Define SGB (stanford graph base top level directory) and +# Define SGB (stanford graph base top level directory) and # LEDA (also top level directory) at the command line of jam using -s import modules ; @@ -20,66 +20,44 @@ if [ modules.peek : EXPAT_INCLUDE ] && [ modules.peek : EXPAT_LIBPATH ] optional_tests += [ run graphml_test.cpp ../build//boost_graph : : "graphml_test.xml" ] ; } -test-suite graph_test : +test-suite graph_test : [ run transitive_closure_test.cpp ] - [ compile adj_list_cc.cpp ] # adj_list_test needs some work -JGS # unit-test adj_list_test : adj_list_test.cpp ; [ run adj_list_edge_list_set.cpp ] - [ compile adj_matrix_cc.cpp ] - [ run bfs.cpp ../../test/build//boost_test_exec_monitor ] - [ compile bfs_cc.cpp ] - [ run bellman-test.cpp ] - - [ run betweenness_centrality_test.cpp ] - + [ run betweenness_centrality_test.cpp ] [ run bidir_remove_edge.cpp ] - [ run csr_graph_test.cpp : : : : : release ] - [ run dag_longest_paths.cpp ] - [ run dfs.cpp ../../test/build//boost_test_exec_monitor ] - [ compile dfs_cc.cpp ] - [ compile dijkstra_cc.cpp ] - [ run dijkstra_heap_performance.cpp : 10000 ] - [ run dominator_tree_test.cpp ] - [ run relaxed_heap_test.cpp : 5000 15000 ] - [ compile edge_list_cc.cpp ] - [ compile filtered_graph_cc.cpp ] - [ run graph.cpp ] - [ compile graph_concepts.cpp ] - - [ run graphviz_test.cpp - /boost/test//boost_test_exec_monitor/static + [ run graphviz_test.cpp + /boost/test//boost_test_exec_monitor/static ../build//boost_graph ] - [ run gursoy_atun_layout_test.cpp ] - [ run layout_test.cpp : : : always_show_run_output intel:off ] - [ run serialize.cpp + [ run serialize.cpp ../../serialization/build//boost_serialization : : : ] - [ compile reverse_graph_cc.cpp ] + [ compile reverse_graph_cc.cpp ] [ run sequential_vertex_coloring.cpp ] @@ -87,13 +65,13 @@ test-suite graph_test : [ run isomorphism.cpp ../../test/build//boost_test_exec_monitor ] - [ run adjacency_matrix_test.cpp ] + [ run adjacency_matrix_test.cpp ] [ compile vector_graph_cc.cpp ] [ compile copy.cpp ] - - [ compile property_iter.cpp ] + + [ compile property_iter.cpp ] [ run bundled_properties.cpp ] @@ -125,19 +103,19 @@ test-suite graph_test : [ run named_vertices_test.cpp ] - [ run all_planar_input_files_test.cpp - ../../filesystem/build + [ run all_planar_input_files_test.cpp + ../../filesystem/build ../../system/build : $(PLANAR_INPUT_FILES) ] - [ run parallel_edges_loops_test.cpp - ../../filesystem/build + [ run parallel_edges_loops_test.cpp + ../../filesystem/build ../../system/build : $(PLANAR_INPUT_FILES) ] [ run r_c_shortest_paths_test.cpp ] - [ run is_straight_line_draw_test.cpp ] + [ run metric_tsp_approx.cpp : metric_tsp_approx.txt ] $(optional_tests) ; @@ -148,18 +126,18 @@ if [ modules.peek : SDB ] != "" local SDB_DEPENDCIES = $(SGB) $(SGB)/libgb.a ; - compile stanford_graph_cc.cpp + compile stanford_graph_cc.cpp $(SDB_DEPENDCIES) ; } # Run LEDA tests only when -sLEDA= is set. if [ modules.peek : LEDA ] != "" { - local LEDA_DEPENDENCIES = - $(LEDA)/incl + local LEDA_DEPENDENCIES = + $(LEDA)/incl $(LEDA)/libG.a ; - compile leda_graph_cc.cpp + compile leda_graph_cc.cpp $(LEDA_DEPENDENCIES) ; } diff --git a/test/metric_tsp_approx.cpp b/test/metric_tsp_approx.cpp new file mode 100644 index 00000000..166cf7c5 --- /dev/null +++ b/test/metric_tsp_approx.cpp @@ -0,0 +1,319 @@ +//======================================================================= +// Copyright 2008 +// Author: Matyas W Egyhazy +// +// 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 + +template +struct cmpPnt +{ + bool operator()(const boost::simple_point& l, + const boost::simple_point& r) const + { return (l.x > r.x); } +}; + +//add edges to the graph (for each node connect it to all other nodes) +template +void connectAllEuclidean(VertexListGraph& g, + const PointContainer& points, + WeightMap wmap, // Property maps passed by value + VertexIndexMap vmap, // Property maps passed by value + int sz) +{ + using namespace boost; + using namespace std; + typedef typename graph_traits::edge_descriptor Edge; + typedef typename graph_traits::vertex_iterator VItr; + + Edge e; + bool inserted; + + pair verts(vertices(g)); + for (VItr src(verts.first); src != verts.second; src++) + { + for (VItr dest(src); dest != verts.second; dest++) + { + if (dest != src) + { + double weight(sqrt(pow( + static_cast(points[vmap[*src]].x - + points[vmap[*dest]].x), 2.0) + + pow(static_cast(points[vmap[*dest]].y - + points[vmap[*src]].y), 2.0))); + + tie(e, inserted) = add_edge(*src, *dest, g); + + wmap[e] = weight; + } + + } + + } +} + +// Create a randomly generated point +// scatter time execution +void testScalability(unsigned numpts) +{ + using namespace boost; + using namespace std; + + typedef adjacency_matrix > > 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; + + mt19937 rng(time(0)); + uniform_int<> range(0.01, (numpts * 2)); + variate_generator > + pnt_gen(rng, range); + + PointSet points; + simple_point pnt; + + while (points.size() < numpts) + { + pnt.x = pnt_gen(); + pnt.y = pnt_gen(); + points.insert(pnt); + } + + Graph g(numpts); + WeightMap weight_map(get(edge_weight, g)); + vector > point_vec(points.begin(), points.end()); + + connectAllEuclidean(g, point_vec, weight_map, get(vertex_index, g), numpts); + + Container c; + timer t; + double len = 0.0; + + // Run the TSP approx, creating the visitor on the fly. + metric_tsp_approx(g, make_tsp_tour_len_visitor(g, back_inserter(c), len, weight_map)); + + cout << "Number of points: " << num_vertices(g) << endl; + cout << "Number of edges: " << num_edges(g) << endl; + cout << "Length of tour: " << len << endl; + cout << "Elapsed: " << t.elapsed() << endl; +} + +template +void checkAdjList(PositionVec v) +{ + using namespace std; + using namespace boost; + + typedef adjacency_list Graph; + typedef graph_traits::vertex_descriptor Vertex; + typedef graph_traits ::edge_descriptor Edge; + typedef vector Container; + typedef map VertexIndexMap; + typedef map EdgeWeightMap; + typedef associative_property_map VPropertyMap; + typedef associative_property_map EWeightPropertyMap; + typedef graph_traits::vertex_iterator VItr; + + Container c; + EdgeWeightMap w_map; + VertexIndexMap v_map; + VPropertyMap v_pmap(v_map); + EWeightPropertyMap w_pmap(w_map); + + Graph g(v.size()); + + //create vertex index map + VItr vi, ve; + int idx(0); + for (tie(vi, ve) = vertices(g); vi != ve; ++vi) + { + Vertex v(*vi); + v_pmap[v] = idx; + idx++; + } + + connectAllEuclidean(g, v, w_pmap, + v_pmap, v.size()); + + metric_tsp_approx_from_vertex(g, + *vertices(g).first, + w_pmap, + v_pmap, + tsp_tour_visitor > + (back_inserter(c))); + + cout << "adj_list" << endl; + for (Container::iterator itr = c.begin(); itr != c.end(); ++itr) { + cout << v_map[*itr] << " "; + } + cout << endl << endl; + + c.clear(); +} + +static void usage() +{ + using namespace std; + cerr << "To run this program properly please place a " + << "file called graph.txt" + << endl << "into the current working directory." << endl + << "Each line of this file should be a coordinate specifying the" + << endl << "location of a vertex" << endl + << "For example: " << endl << "1,2" << endl << "20,4" << endl + << "15,7" << endl << endl; +} + +int main(int argc, char* argv[]) +{ + using namespace boost; + using namespace std; + + typedef vector > PositionVec; + 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; + + // Make sure that the the we can parse the given file. + if(argc < 2) { + usage(); + return -1; + } + + // Open the graph file, failing if one isn't given on the command line. + ifstream fin(argv[1]); + if (!fin) + { + usage(); + return -1; + } + + string line; + PositionVec position_vec; + + int n(0); + while (getline(fin, line)) + { + simple_point vertex; + + size_t idx(line.find(",")); + string xStr(line.substr(0, idx)); + string yStr(line.substr(idx + 1, line.size() - idx)); + + vertex.x = lexical_cast(xStr); + vertex.y = lexical_cast(yStr); + + position_vec.push_back(vertex); + n++; + } + + fin.close(); + + Container c; + Graph g(position_vec.size()); + WeightMap weight_map(get(edge_weight, g)); + VertexMap v_map = get(vertex_index, g); + + connectAllEuclidean(g, position_vec, weight_map, v_map, n); + + metric_tsp_approx_tour(g, back_inserter(c)); + + for (vector::iterator itr = c.begin(); itr != c.end(); ++itr) + { + cout << *itr << " "; + } + cout << endl << endl; + + c.clear(); + + checkAdjList(position_vec); + + metric_tsp_approx_from_vertex(g, *vertices(g).first, + get(edge_weight, g), get(vertex_index, g), + tsp_tour_visitor > > + (back_inserter(c))); + + for (vector::iterator itr = c.begin(); itr != c.end(); ++itr) + { + cout << *itr << " "; + } + cout << endl << endl; + + c.clear(); + + double len(0.0); + try { + metric_tsp_approx(g, make_tsp_tour_len_visitor(g, back_inserter(c), len, weight_map)); + } + catch (const bad_graph& e) { + cerr << "bad_graph: " << e.what() << endl; + return -1; + } + + cout << "Number of points: " << num_vertices(g) << endl; + cout << "Number of edges: " << num_edges(g) << endl; + cout << "Length of Tour: " << len << endl; + + int cnt(0); + pair triangleEdge; + for (vector::iterator itr = c.begin(); itr != c.end(); + ++itr, ++cnt) + { + cout << *itr << " "; + + if (cnt == 2) + { + triangleEdge.first = *itr; + } + if (cnt == 3) + { + triangleEdge.second = *itr; + } + } + cout << endl << endl; + c.clear(); + + testScalability(1000); + + // if the graph is not fully connected then some of the + // assumed triangle-inequality edges may not exist + remove_edge(edge(triangleEdge.first, triangleEdge.second, g).first, g); + + // Make sure that we can actually trap incomplete graphs. + bool caught = false; + try { + double len = 0.0; + metric_tsp_approx(g, make_tsp_tour_len_visitor(g, back_inserter(c), len, weight_map)); + } + catch (const bad_graph& e) { caught = true; } + BOOST_ASSERT(caught); + + return 0; +} diff --git a/test/metric_tsp_approx.txt b/test/metric_tsp_approx.txt new file mode 100644 index 00000000..1af437ac --- /dev/null +++ b/test/metric_tsp_approx.txt @@ -0,0 +1,8 @@ +2,5 +2,3 +1,2 +4,5 +5,4 +4,3 +6,3 +3,1 \ No newline at end of file From 5c899afa22257a2de6844c33fe486bbb77c3d77a Mon Sep 17 00:00:00 2001 From: Andrew Sutton Date: Mon, 3 Nov 2008 15:50:29 +0000 Subject: [PATCH 035/224] Include correct headers for read_dimacs.hpp, fixing #2460. Added a compile test (just a stub for now) to ensuer that the file will compile without any additional includes. [SVN r49563] --- include/boost/graph/read_dimacs.hpp | 111 ++++++++++++++-------------- test/Jamfile.v2 | 1 + test/dimacs.cpp | 11 +++ 3 files changed, 69 insertions(+), 54 deletions(-) create mode 100644 test/dimacs.cpp diff --git a/include/boost/graph/read_dimacs.hpp b/include/boost/graph/read_dimacs.hpp index 4d4d1601..736cc6cc 100644 --- a/include/boost/graph/read_dimacs.hpp +++ b/include/boost/graph/read_dimacs.hpp @@ -9,24 +9,27 @@ /* Reads maximal flow problem in extended DIMACS format. - This works, but could use some polishing. + This works, but could use some polishing. */ /* ----------------------------------------------------------------- */ #include -#include -#include +#include +#include +#include + +#include namespace boost { template int read_dimacs_max_flow(Graph& g, - CapacityMap capacity, + CapacityMap capacity, ReverseEdgeMap reverse_edge, typename graph_traits::vertex_descriptor& src, typename graph_traits::vertex_descriptor& sink, - std::istream& in=std::cin) + std::istream& in = std::cin) { // const int MAXLINE = 100; /* max line length in the input file */ const int ARC_FIELDS = 3; /* no of fields in arc line */ @@ -37,7 +40,7 @@ int read_dimacs_max_flow(Graph& g, 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; - + std::vector verts; long m, n, /* number of edges and nodes */ @@ -48,11 +51,11 @@ int read_dimacs_max_flow(Graph& g, no_nslines=0, /* no of node-source-lines */ no_nklines=0, /* no of node-source-lines */ no_alines=0; /* no of arc-lines */ - + std::string in_line; /* for reading input line */ char pr_type[3]; /* for reading type of the problem */ char nd; /* source (s) or sink (t) */ - + int k, /* temporary */ err_no; /* no of detected error */ @@ -78,9 +81,9 @@ int read_dimacs_max_flow(Graph& g, const int EN19 = 18; const int EN20 = 19; const int EN22 = 20; - - static char *err_message[] = - { + + static char *err_message[] = + { /* 0*/ "more than one problem line.", /* 1*/ "wrong number of parameters in the problem line.", /* 2*/ "it is not a Max Flow problem line.", @@ -121,14 +124,14 @@ int read_dimacs_max_flow(Graph& g, case '\n': /* skip empty lines */ case '\0': /* skip empty lines at the end of file */ break; - + case 'p': /* problem description */ if ( no_plines > 0 ) /* more than one problem line */ { err_no = EN1 ; goto error; } - + no_plines = 1; - + if ( /* reading problem line: type of problem, no of nodes, no of arcs */ sscanf ( in_line.c_str(), "%*c %3s %ld %ld", pr_type, &n, &m ) @@ -136,11 +139,11 @@ int read_dimacs_max_flow(Graph& g, ) /*wrong number of parameters in the problem line*/ { err_no = EN2; goto error; } - + if ( strcmp ( pr_type, PROBLEM_TYPE ) ) /*wrong problem type*/ { err_no = EN3; goto error; } - + if ( n <= 0 || m <= 0 ) /*wrong value of no of arcs or nodes*/ { err_no = EN4; goto error; } @@ -150,83 +153,83 @@ int read_dimacs_max_flow(Graph& g, verts.push_back(add_vertex(g)); } break; - + case 'n': /* source(s) description */ if ( no_plines == 0 ) /* there was not problem line above */ { err_no = EN8; goto error; } - + /* reading source or sink */ k = sscanf ( in_line.c_str(),"%*c %ld %c", &i, &nd ); --i; // index from 0 if ( k < NODE_FIELDS ) /* node line is incorrect */ { err_no = EN11; goto error; } - + if ( i < 0 || i > n ) /* wrong value of node */ { err_no = EN12; goto error; } - + switch (nd) { case 's': /* source line */ - + if ( no_nslines != 0) - /* more than one source line */ + /* more than one source line */ { err_no = EN9; goto error; } - + no_nslines = 1; src = verts[i]; break; - + case 't': /* sink line */ - + if ( no_nklines != 0) /* more than one sink line */ { err_no = EN9; goto error; } - + no_nklines = 1; sink = verts[i]; break; - + default: /* wrong type of node-line */ - err_no = EN12; goto error; + err_no = EN12; goto error; } break; - + case 'a': /* arc description */ - if ( no_nslines == 0 || no_nklines == 0 ) + if ( no_nslines == 0 || no_nklines == 0 ) /* there was not source and sink description above */ { err_no = EN14; goto error; } - + if ( no_alines >= m ) /*too many arcs on input*/ { err_no = EN16; goto error; } - + if ( /* reading an arc description */ sscanf ( in_line.c_str(),"%*c %ld %ld %ld", &tail, &head, &cap ) != ARC_FIELDS - ) + ) /* arc description is not correct */ { err_no = EN15; goto error; } --tail; // index from 0, not 1 --head; if ( tail < 0 || tail > n || - head < 0 || head > n + head < 0 || head > n ) /* wrong value of nodes */ { err_no = EN17; goto error; } - { - edge_descriptor e1, e2; + { + edge_descriptor e1, e2; bool in1, in2; tie(e1, in1) = add_edge(verts[tail], verts[head], g); tie(e2, in2) = add_edge(verts[head], verts[tail], g); if (!in1 || !in2) { - std::cerr << "unable to add edge (" << head << "," << tail << ")" + std::cerr << "unable to add edge (" << head << "," << tail << ")" << std::endl; return -1; } @@ -237,38 +240,38 @@ int read_dimacs_max_flow(Graph& g, } ++no_alines; break; - + default: /* unknown type of line */ err_no = EN18; goto error; - + } /* end of switch */ } /* end of input loop */ - - /* ----- all is red or error while reading ----- */ - + + /* ----- all is red or error while reading ----- */ + if ( feof (stdin) == 0 ) /* reading error */ - { err_no=EN21; goto error; } - + { err_no=EN21; goto error; } + if ( no_lines == 0 ) /* empty input */ - { err_no = EN22; goto error; } - + { err_no = EN22; goto error; } + if ( no_alines < m ) /* not enough arcs */ - { err_no = EN19; goto error; } - - if ( out_degree(src, g) == 0 || out_degree(sink, g) == 0 ) + { err_no = EN19; goto error; } + + if ( out_degree(src, g) == 0 || out_degree(sink, g) == 0 ) /* no arc goes out of the source */ { err_no = EN20; goto error; } - + /* Thanks God! all is done */ return (0); - + /* ---------------------------------- */ error: /* error found reading input */ - - printf ( "\nline %ld of input - %s\n", + + printf ( "\nline %ld of input - %s\n", no_lines, err_message[err_no] ); - + exit (1); return (0); /* to avoid warning */ } diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 59cbff54..b69332ca 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -116,6 +116,7 @@ test-suite graph_test : [ run r_c_shortest_paths_test.cpp ] [ run is_straight_line_draw_test.cpp ] [ run metric_tsp_approx.cpp : metric_tsp_approx.txt ] + [ compile dimacs.cpp ] $(optional_tests) ; diff --git a/test/dimacs.cpp b/test/dimacs.cpp new file mode 100644 index 00000000..f0edea89 --- /dev/null +++ b/test/dimacs.cpp @@ -0,0 +1,11 @@ + +#include +#include + +// This is obviously just a stub test. It's currently only used as a compile +// check to make sure that the includes are appropriate. + +int main() +{ + return 0; +} From 4f9ce0c88d3fb6a8362119c1eb6f5ea95b2844c6 Mon Sep 17 00:00:00 2001 From: "Michael A. Jackson" Date: Fri, 7 Nov 2008 17:02:56 +0000 Subject: [PATCH 036/224] Updating CMake files to latest trunk. Added dependency information for regression tests and a few new macros for internal use. [SVN r49627] --- test/CMakeLists.txt | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 163a2931..4ff827db 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -1,3 +1,5 @@ +boost_additional_test_dependencies(graph BOOST_DEPENDS test assign) + boost_test_run(transitive_closure_test) boost_test_compile(adj_list_cc) boost_test_run(adj_list_edge_list_set) @@ -5,13 +7,13 @@ boost_test_compile(adj_matrix_cc) boost_test_run(bfs) boost_test_compile(bfs_cc) boost_test_run(bellman-test) -boost_test_run(betweenness_centrality_test DEPENDS boost_graph-shared) +boost_test_run(betweenness_centrality_test DEPENDS boost_graph SHARED) boost_test_run(csr_graph_test) boost_test_run(dag_longest_paths) boost_test_run(dfs) boost_test_compile(dfs_cc) boost_test_compile(dijkstra_cc) -boost_test_run(dijkstra_heap_performance ARGS 10000 DEPENDS boost_graph-shared) +boost_test_run(dijkstra_heap_performance ARGS 10000 DEPENDS boost_graph SHARED) boost_test_run(dominator_tree_test) boost_test_run(relaxed_heap_test ARGS 5000 15000) boost_test_compile(edge_list_cc) @@ -19,7 +21,7 @@ boost_test_compile(filtered_graph_cc) boost_test_run(graph) boost_test_compile(graph_concepts) boost_test_run(graphviz_test - DEPENDS boost_test_exec_monitor boost_graph-static) + DEPENDS boost_test_exec_monitor boost_graph STATIC) boost_test_run(gursoy_atun_layout_test) boost_test_run(layout_test) boost_test_run(serialize DEPENDS boost_serialization) From bafd8ea2488bee624da08c99e84308919ca886a0 Mon Sep 17 00:00:00 2001 From: "Michael A. Jackson" Date: Fri, 7 Nov 2008 17:05:27 +0000 Subject: [PATCH 037/224] Updating dependency information for modularized libraries. [SVN r49628] --- module.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/module.cmake b/module.cmake index b7015a64..738381c6 100644 --- a/module.cmake +++ b/module.cmake @@ -1,3 +1,3 @@ -boost_module(graph DEPENDS property_map tuple multi_index any) +boost_module(graph DEPENDS property_map tuple multi_index any random) # any is there because of the dependency on boost/dynamic_property_map.hpp From 597d89ead2f43f7b2e7e835b39c7c825d68465bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=BCrgen=20Hunold?= Date: Fri, 5 Dec 2008 17:53:22 +0000 Subject: [PATCH 038/224] Add deprecation header for wrong-spelled Edmonds-Karp-Max-Flox. Preparaion to fix #416 [SVN r50137] --- include/boost/graph/edmunds_karp_max_flow.hpp | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 include/boost/graph/edmunds_karp_max_flow.hpp diff --git a/include/boost/graph/edmunds_karp_max_flow.hpp b/include/boost/graph/edmunds_karp_max_flow.hpp new file mode 100644 index 00000000..3697db20 --- /dev/null +++ b/include/boost/graph/edmunds_karp_max_flow.hpp @@ -0,0 +1,19 @@ +//======================================================================= +// (c) Copyright Juergen Hunold 2008 +// 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_DEPRECATED_INCLUDE_EDMONDS_KARP_MAX_FLOW_HPP +#define BOOST_DEPRECATED_INCLUDE_EDMONDS_KARP_MAX_FLOW_HPP + +#if defined(_MSC_VER) || defined(__BORLANDC__) || defined(__DMC__) +# pragma message ("Warning: This header is deprecated. Please use: boost/graph/edmonds_karp_max_flow.hpp") +#elif defined(__GNUC__) || defined(__HP_aCC) || defined(__SUNPRO_CC) || defined(__IBMCPP__) +# warning "This header is deprecated. Please use: boost/graph/edmonds_karp_max_flow.hpp" +#endif + +#include + +#endif // BOOST_DEPRECATED_INCLUDE_EDMONDS_KARP_MAX_FLOW_HPP From bc707a8f6737196d3de5222d95d3fe712cdfaf0b Mon Sep 17 00:00:00 2001 From: Andrew Sutton Date: Mon, 8 Dec 2008 15:06:05 +0000 Subject: [PATCH 039/224] Whitespace cleanup. [SVN r50188] --- include/boost/graph/astar_search.hpp | 98 ++++++++++++++-------------- 1 file changed, 49 insertions(+), 49 deletions(-) diff --git a/include/boost/graph/astar_search.hpp b/include/boost/graph/astar_search.hpp index e1b95c4a..6db52d6a 100644 --- a/include/boost/graph/astar_search.hpp +++ b/include/boost/graph/astar_search.hpp @@ -26,7 +26,7 @@ namespace boost { - + template struct AStarHeuristicConcept { void constraints() @@ -37,8 +37,8 @@ namespace boost { Heuristic h; typename graph_traits::vertex_descriptor u; }; - - + + template class astar_heuristic : public std::unary_function< typename graph_traits::vertex_descriptor, CostType> @@ -48,9 +48,9 @@ namespace boost { astar_heuristic() {} CostType operator()(Vertex u) { return static_cast(0); } }; - - + + template struct AStarVisitorConcept { void constraints() @@ -70,22 +70,22 @@ namespace boost { typename graph_traits::vertex_descriptor u; typename graph_traits::edge_descriptor e; }; - - + + template class astar_visitor : public bfs_visitor { public: astar_visitor() {} astar_visitor(Visitors vis) : bfs_visitor(vis) {} - + template void edge_relaxed(Edge e, Graph& g) { invoke_visitors(this->m_vis, e, g, on_edge_relaxed()); } template void edge_not_relaxed(Edge e, Graph& g) { - invoke_visitors(this->m_vis, e, g, on_edge_not_relaxed()); + invoke_visitors(this->m_vis, e, g, on_edge_not_relaxed()); } private: template @@ -99,10 +99,10 @@ namespace boost { return astar_visitor(vis); } typedef astar_visitor<> default_astar_visitor; - + namespace detail { - + template struct astar_bfs_visitor { - + typedef typename property_traits::value_type C; typedef typename property_traits::value_type ColorValue; typedef color_traits Color; typedef typename property_traits::value_type distance_type; - + astar_bfs_visitor(AStarHeuristic h, UniformCostVisitor vis, UpdatableQueue& Q, PredecessorMap p, CostMap c, DistanceMap d, WeightMap w, @@ -124,8 +124,8 @@ namespace boost { : m_h(h), m_vis(vis), m_Q(Q), m_predecessor(p), m_cost(c), m_distance(d), m_weight(w), m_color(col), m_combine(combine), m_compare(compare), m_zero(zero) {} - - + + template void initialize_vertex(Vertex u, Graph& g) { m_vis.initialize_vertex(u, g); @@ -143,16 +143,16 @@ namespace boost { m_vis.finish_vertex(u, g); } template - void examine_edge(Edge e, Graph& g) { + void examine_edge(Edge e, Graph& g) { if (m_compare(get(m_weight, e), m_zero)) throw negative_edge(); m_vis.examine_edge(e, g); } template void non_tree_edge(Edge, Graph&) {} - - - + + + template void tree_edge(Edge e, Graph& g) { m_decreased = relax(e, g, m_weight, m_predecessor, m_distance, @@ -166,8 +166,8 @@ namespace boost { } else m_vis.edge_not_relaxed(e, g); } - - + + template void gray_target(Edge e, Graph& g) { distance_type old_distance = get(m_distance, target(e, g)); @@ -192,8 +192,8 @@ namespace boost { } else m_vis.edge_not_relaxed(e, g); } - - + + template void black_target(Edge e, Graph& g) { distance_type old_distance = get(m_distance, target(e, g)); @@ -213,9 +213,9 @@ namespace boost { } else m_vis.edge_not_relaxed(e, g); } - - - + + + AStarHeuristic m_h; UniformCostVisitor m_vis; UpdatableQueue& m_Q; @@ -228,13 +228,13 @@ namespace boost { BinaryPredicate m_compare; bool m_decreased; C m_zero; - + }; - + } // namespace detail - - + + template IndirectCmp; IndirectCmp icmp(cost, compare); - + typedef typename graph_traits::vertex_descriptor Vertex; typedef mutable_queue, IndirectCmp, VertexIndexMap> MutableQueue; MutableQueue Q(num_vertices(g), icmp, index_map); - + detail::astar_bfs_visitor bfs_vis(h, vis, Q, predecessor, cost, distance, weight, color, combine, compare, zero); - + breadth_first_visit(g, s, Q, bfs_vis, color); } - - + + // Non-named parameter interface template ::value_type ColorValue; typedef color_traits Color; typename graph_traits::vertex_iterator ui, ui_end; @@ -305,15 +305,15 @@ namespace boost { } put(distance, s, zero); put(cost, s, h(s)); - + astar_search_no_init (g, s, h, vis, predecessor, cost, distance, weight, color, index_map, compare, combine, inf, zero); - + } - - - + + + namespace detail { template @@ -363,14 +363,14 @@ namespace boost { std::vector cost_map(n); std::vector color_map(num_vertices(g)); default_color_type c = white_color; - + detail::astar_dispatch2 (g, s, h, choose_param(cost, make_iterator_property_map (cost_map.begin(), index_map, cost_map[0])), choose_param(distance, make_iterator_property_map - (distance_map.begin(), index_map, + (distance_map.begin(), index_map, distance_map[0])), weight, index_map, choose_param(color, make_iterator_property_map @@ -378,8 +378,8 @@ namespace boost { params); } } // namespace detail - - + + // Named parameter interface template ::vertex_descriptor s, AStarHeuristic h, const bgl_named_params& params) { - + detail::astar_dispatch1 (g, s, h, get_param(params, vertex_rank), @@ -399,9 +399,9 @@ namespace boost { choose_const_pmap(get_param(params, vertex_index), g, vertex_index), get_param(params, vertex_color), params); - + } - + } // namespace boost #endif // BOOST_GRAPH_ASTAR_SEARCH_HPP From 4a2994c9d747d502d4b040c2b4f6f02e10bf0082 Mon Sep 17 00:00:00 2001 From: Andrew Sutton Date: Mon, 8 Dec 2008 15:06:55 +0000 Subject: [PATCH 040/224] Removing GCC check for hash_set/hash_map so we don't automatically break any code. Added a section of workarounds to the documentation. [SVN r50189] --- doc/known_problems.html | 26 ++++++++++++++++++-------- include/boost/graph/adjacency_list.hpp | 9 +++------ 2 files changed, 21 insertions(+), 14 deletions(-) diff --git a/doc/known_problems.html b/doc/known_problems.html index 13561330..dbec8729 100644 --- a/doc/known_problems.html +++ b/doc/known_problems.html @@ -8,14 +8,17 @@ --> Known Problems - -C++ Boost + +C++ Boost
    -

    Known Problems

    +

    Known Problems and Workarounds

    + +This is a list of known problems compiling the BGL for different compilers and +versions.
    1. The subgraph adaptor has several known problems: @@ -23,7 +26,7 @@
    2. Each instance of subgraph has its own copy of internal vertex and edge properties. Only at the root subgraph are the properties valid.
    3. - +
    4. Edge and vertex removal functions are unimplemented.
    5. The graph is required to have vertex descriptors of integral @@ -38,9 +41,16 @@
    6. Using a GraphProperty with adjacency_list may cause a VC++ internal compiler error.
    7. Using get(property, graph, edge) may cause a VC++ internal compiler error.
    8. -
    9. "using boost::tie;" may cause VC++ internal compiler error. +
    10. "using boost::tie;" may cause VC++ internal compiler error.
    +

    Workarounds

    +

    +Compiler Warnings on hash_set and hash_map. Versions of +GCC >= 4.3 deprecate these headers and data structures and will emit warnings when +compiling the BGL. To suppress these warnings and the hash-based storage selectors +define the BOOST_NO_HASH prior to including any Boost.Graph headers. +



    @@ -57,4 +67,4 @@ HREF="mailto:lums@osl.iu.edu">lums@osl.iu.edu) - + diff --git a/include/boost/graph/adjacency_list.hpp b/include/boost/graph/adjacency_list.hpp index e75ed169..5a0f066c 100644 --- a/include/boost/graph/adjacency_list.hpp +++ b/include/boost/graph/adjacency_list.hpp @@ -17,12 +17,9 @@ #include #include -// Thef 4.3 series deprecates hash_set and hash_map. -// TODO: Migrate this to Boost.Config. -#if __GNUC__ >= 4 && __GNUC_MINOR__ >= 3 -# define BOOST_NO_HASH -#endif - +// TODO: Deprecating this requires some cooperation from Boost.Config. It's not +// a good idea to just refuse the inclusion because it could break otherwise +// functioning code. #if !defined BOOST_NO_HASH # ifdef BOOST_HASH_SET_HEADER # include BOOST_HASH_SET_HEADER From 3fdea479bd6c92476118031ce1b6a43789af60bf Mon Sep 17 00:00:00 2001 From: Andrew Sutton Date: Mon, 8 Dec 2008 15:22:32 +0000 Subject: [PATCH 041/224] Fixing #2550. Added a check for this condition in the test files. [SVN r50191] --- include/boost/graph/adjacency_matrix.hpp | 223 ++++++++++++----------- test/adjacency_matrix_test.cpp | 61 +++++-- 2 files changed, 155 insertions(+), 129 deletions(-) diff --git a/include/boost/graph/adjacency_matrix.hpp b/include/boost/graph/adjacency_matrix.hpp index 9770e51a..9a102d7b 100644 --- a/include/boost/graph/adjacency_matrix.hpp +++ b/include/boost/graph/adjacency_matrix.hpp @@ -31,7 +31,7 @@ #include namespace boost { - + namespace detail { template @@ -40,7 +40,7 @@ namespace boost { typedef edge_desc_impl Base; public: matrix_edge_desc_impl() { } - matrix_edge_desc_impl(bool exists, Vertex s, Vertex d, + matrix_edge_desc_impl(bool exists, Vertex s, Vertex d, const void* ep = 0) : Base(s, d, ep), m_exists(exists) { } bool exists() const { return m_exists; } @@ -53,13 +53,15 @@ namespace boost { bool operator()(const Edge& e) const { return e.exists(); } }; + // Note to self... The int for get_edge_exists and set_edge exist helps + // make these calls unambiguous. template bool get_edge_exists(const std::pair& stored_edge, int) { return stored_edge.first; } template void set_edge_exists( - std::pair& stored_edge, + std::pair& stored_edge, bool flag, int ) { @@ -91,7 +93,7 @@ namespace boost { template inline void - set_property(std::pair& stored_edge, + set_property(std::pair& stored_edge, const EdgeProperty& ep, int) { stored_edge.second = ep; } @@ -107,7 +109,7 @@ namespace boost { template inline void set_property(EdgeProxy, const EdgeProperty&, ...) {} - + //======================================================================= // Directed Out Edge Iterator @@ -133,9 +135,9 @@ namespace boost { , EdgeDescriptor , std::ptrdiff_t > super_t; - + dir_adj_matrix_out_edge_iter() { } - + dir_adj_matrix_out_edge_iter( const MatrixIter& i , const VertexDescriptor& src @@ -148,11 +150,11 @@ namespace boost { ++this->base_reference(); ++m_targ; } - + inline EdgeDescriptor - dereference() const + dereference() const { - return EdgeDescriptor(get_edge_exists(*this->base(), 0), m_src, m_targ, + return EdgeDescriptor(get_edge_exists(*this->base(), 0), m_src, m_targ, &get_property(*this->base())); } VertexDescriptor m_src, m_targ; @@ -184,9 +186,9 @@ namespace boost { , EdgeDescriptor , std::ptrdiff_t > super_t; - + dir_adj_matrix_in_edge_iter() { } - + dir_adj_matrix_in_edge_iter( const MatrixIter& i , const MatrixIter& last @@ -204,11 +206,11 @@ namespace boost { this->base_reference() = m_last; } } - + inline EdgeDescriptor - dereference() const + dereference() const { - return EdgeDescriptor(get_edge_exists(*this->base(), 0), m_src, m_targ, + return EdgeDescriptor(get_edge_exists(*this->base(), 0), m_src, m_targ, &get_property(*this->base())); } MatrixIter m_last; @@ -223,7 +225,7 @@ namespace boost { typename VertexDescriptor, typename MatrixIter , typename VerticesSizeType, typename EdgeDescriptor > - struct undir_adj_matrix_out_edge_iter + struct undir_adj_matrix_out_edge_iter : iterator_adaptor< undir_adj_matrix_out_edge_iter , MatrixIter @@ -241,9 +243,9 @@ namespace boost { , EdgeDescriptor , std::ptrdiff_t > super_t; - + undir_adj_matrix_out_edge_iter() { } - + undir_adj_matrix_out_edge_iter( const MatrixIter& i , const VertexDescriptor& src @@ -269,16 +271,16 @@ namespace boost { } ++m_targ; } - + inline EdgeDescriptor - dereference() const + dereference() const { return EdgeDescriptor( get_edge_exists(*this->base(), 0), m_src, m_targ , &get_property(*this->base()) ); } - + VertexDescriptor m_src, m_inc, m_targ; VerticesSizeType m_n; }; @@ -290,7 +292,7 @@ namespace boost { typename VertexDescriptor, typename MatrixIter , typename VerticesSizeType, typename EdgeDescriptor > - struct undir_adj_matrix_in_edge_iter + struct undir_adj_matrix_in_edge_iter : iterator_adaptor< undir_adj_matrix_in_edge_iter , MatrixIter @@ -308,9 +310,9 @@ namespace boost { , EdgeDescriptor , std::ptrdiff_t > super_t; - + undir_adj_matrix_in_edge_iter() { } - + undir_adj_matrix_in_edge_iter( const MatrixIter& i , const VertexDescriptor& src @@ -336,16 +338,16 @@ namespace boost { } ++m_targ; } - + inline EdgeDescriptor - dereference() const + dereference() const { return EdgeDescriptor( get_edge_exists(*this->base(), 0), m_targ, m_src , &get_property(*this->base()) ); } - + VertexDescriptor m_src, m_inc, m_targ; VerticesSizeType m_n; }; @@ -353,7 +355,7 @@ namespace boost { //======================================================================= // Edge Iterator - template struct adj_matrix_edge_iter : iterator_adaptor< @@ -373,17 +375,17 @@ namespace boost { , EdgeDescriptor , std::ptrdiff_t > super_t; - + adj_matrix_edge_iter() { } - - adj_matrix_edge_iter(const MatrixIter& i, const MatrixIter& start, const VerticesSizeType& n) + + adj_matrix_edge_iter(const MatrixIter& i, const MatrixIter& start, const VerticesSizeType& n) : super_t(i), m_start(start), m_src(0), m_targ(0), m_n(n) { } void increment() { increment_dispatch(this->base_reference(), Directed()); } - + void increment_dispatch(MatrixIter& i, directedS) { ++i; @@ -397,7 +399,7 @@ namespace boost { ++m_targ; } } - + void increment_dispatch(MatrixIter& i, undirectedS) { ++i; @@ -413,14 +415,14 @@ namespace boost { } inline EdgeDescriptor - dereference() const + dereference() const { return EdgeDescriptor( get_edge_exists( *this->base(), 0), m_src, m_targ, &get_property(*this->base()) ); } - + MatrixIter m_start; VerticesSizeType m_src, m_targ, m_n; }; @@ -444,9 +446,9 @@ namespace boost { typedef typename mpl::if_::type directed_category; - + typedef disallow_parallel_edge_tag edge_parallel_category; - + typedef std::size_t vertex_descriptor; typedef detail::matrix_edge_desc_impl Traits; - + public: #if !defined(BOOST_MSVC) || BOOST_MSVC > 1300 // The bidirectionalS tag is not allowed with the adjacency_matrix @@ -487,14 +489,14 @@ namespace boost { vertex_property_type; typedef typename detail::retag_property_list::type edge_property_type; - + private: typedef typename detail::retag_property_list::retagged maybe_vertex_bundled; typedef typename detail::retag_property_list::retagged maybe_edge_bundled; - + public: // The types that are actually bundled typedef typename mpl::if_c<(is_same::value), @@ -534,7 +536,7 @@ namespace boost { { return (std::numeric_limits::max)(); } - + //private: if friends worked, these would be private typedef detail::dir_adj_matrix_out_edge_iter< @@ -560,11 +562,11 @@ namespace boost { typedef typename mpl::if_< typename Directed::is_directed_t, DirInEdgeIter, UnDirInEdgeIter >::type unfiltered_in_edge_iter; - + typedef detail::adj_matrix_edge_iter< Directed, MatrixIter, size_type, edge_descriptor > unfiltered_edge_iter; - + public: // IncidenceGraph concept required types @@ -596,8 +598,8 @@ namespace boost { typedef adjacency_matrix_class_tag graph_tag; // Constructor required by MutableGraph - adjacency_matrix(vertices_size_type n_vertices) - : m_matrix(Directed::is_directed ? + adjacency_matrix(vertices_size_type n_vertices) + : m_matrix(Directed::is_directed ? (n_vertices * n_vertices) : (n_vertices * (n_vertices + 1) / 2)), m_vertex_set(0, n_vertices), @@ -618,7 +620,7 @@ namespace boost { const edge_bundled& operator[](edge_descriptor e) const { return get(edge_bundle, *this)[e]; } #endif - + //private: if friends worked, these would be private typename Matrix::const_reference @@ -647,9 +649,9 @@ namespace boost { std::vector m_vertex_properties; size_type m_num_edges; }; - + //========================================================================= - // Functions required by the AdjacencyMatrix concept + // Functions required by the AdjacencyMatrix concept template std::pair::edge_descriptor, @@ -665,7 +667,7 @@ namespace boost { } //========================================================================= - // Functions required by the IncidenceGraph concept + // Functions required by the IncidenceGraph concept // O(1) template @@ -685,7 +687,7 @@ namespace boost { , last(l, u, g.m_vertex_set.size()); detail::does_edge_exist pred; typedef typename Graph::out_edge_iterator out_edge_iterator; - return std::make_pair(out_edge_iterator(pred, first, last), + return std::make_pair(out_edge_iterator(pred, first, last), out_edge_iterator(pred, last, last)); } @@ -707,15 +709,15 @@ namespace boost { typename Graph::unfiltered_out_edge_iter first(f, u, g.m_vertex_set.size()) , last(l, u, g.m_vertex_set.size()); - + detail::does_edge_exist pred; typedef typename Graph::out_edge_iterator out_edge_iterator; - return std::make_pair(out_edge_iterator(pred, first, last), + return std::make_pair(out_edge_iterator(pred, first, last), out_edge_iterator(pred, last, last)); } - + // O(N) - template + template typename adjacency_matrix::degree_size_type out_degree(typename adjacency_matrix::vertex_descriptor u, const adjacency_matrix& g) @@ -729,7 +731,7 @@ namespace boost { // O(1) template + typename Dir, typename Vertex> typename adjacency_matrix::vertex_descriptor source(const detail::matrix_edge_desc_impl& e, const adjacency_matrix&) @@ -739,7 +741,7 @@ namespace boost { // O(1) template + typename Dir, typename Vertex> typename adjacency_matrix::vertex_descriptor target(const detail::matrix_edge_desc_impl& e, const adjacency_matrix&) @@ -748,7 +750,7 @@ namespace boost { } //========================================================================= - // Functions required by the BidirectionalGraph concept + // Functions required by the BidirectionalGraph concept // O(1) template @@ -767,7 +769,7 @@ namespace boost { , last(l, l, u, g.m_vertex_set.size()); detail::does_edge_exist pred; typedef typename Graph::in_edge_iterator in_edge_iterator; - return std::make_pair(in_edge_iterator(pred, first, last), + return std::make_pair(in_edge_iterator(pred, first, last), in_edge_iterator(pred, last, last)); } @@ -789,15 +791,15 @@ namespace boost { typename Graph::unfiltered_in_edge_iter first(f, u, g.m_vertex_set.size()) , last(l, u, g.m_vertex_set.size()); - + detail::does_edge_exist pred; typedef typename Graph::in_edge_iterator in_edge_iterator; - return std::make_pair(in_edge_iterator(pred, first, last), + return std::make_pair(in_edge_iterator(pred, first, last), in_edge_iterator(pred, last, last)); } - + // O(N) - template + template typename adjacency_matrix::degree_size_type in_degree(typename adjacency_matrix::vertex_descriptor u, const adjacency_matrix& g) @@ -810,7 +812,7 @@ namespace boost { } //========================================================================= - // Functions required by the AdjacencyGraph concept + // Functions required by the AdjacencyGraph concept template std::pair::adjacency_iterator, @@ -830,7 +832,7 @@ namespace boost { } //========================================================================= - // Functions required by the VertexListGraph concept + // Functions required by the VertexListGraph concept template std::pair::vertex_iterator, @@ -846,10 +848,10 @@ namespace boost { num_vertices(const adjacency_matrix& g) { return g.m_vertex_set.size(); } - + //========================================================================= - // Functions required by the EdgeListGraph concept - + // Functions required by the EdgeListGraph concept + template std::pair::edge_iterator, typename adjacency_matrix::edge_iterator> @@ -857,11 +859,11 @@ namespace boost { { typedef adjacency_matrix Graph; Graph& g = const_cast(g_); - + typename Graph::unfiltered_edge_iter - first(g.m_matrix.begin(), g.m_matrix.begin(), + first(g.m_matrix.begin(), g.m_matrix.begin(), g.m_vertex_set.size()), - last(g.m_matrix.end(), g.m_matrix.begin(), + last(g.m_matrix.end(), g.m_matrix.begin(), g.m_vertex_set.size()); detail::does_edge_exist pred; typedef typename Graph::edge_iterator edge_iterator; @@ -876,9 +878,9 @@ namespace boost { { return g.m_num_edges; } - + //========================================================================= - // Functions required by the MutableGraph concept + // Functions required by the MutableGraph concept // O(1) template @@ -888,14 +890,14 @@ namespace boost { const EP& ep, adjacency_matrix& g) { - typedef typename adjacency_matrix::edge_descriptor + typedef typename adjacency_matrix::edge_descriptor edge_descriptor; if (detail::get_edge_exists(g.get_edge(u,v), 0) == false) { ++(g.m_num_edges); detail::set_property(g.get_edge(u,v), ep, 0); detail::set_edge_exists(g.get_edge(u,v), true, 0); return std::make_pair - (edge_descriptor(true, u, v, &detail::get_property(g.get_edge(u,v))), + (edge_descriptor(true, u, v, &detail::get_property(g.get_edge(u,v))), true); } else return std::make_pair @@ -913,15 +915,18 @@ namespace boost { return add_edge(u, v, ep, g); } - // O(1) + // O(1) template void remove_edge(typename adjacency_matrix::vertex_descriptor u, typename adjacency_matrix::vertex_descriptor v, adjacency_matrix& g) { - --(g.m_num_edges); - detail::set_edge_exists(g.get_edge(u,v), false, 0); + // Don'remove the edge unless it already exists. + if(detail::get_edge_exists(g.get_edge(u,v), 0)) { + --(g.m_num_edges); + detail::set_edge_exists(g.get_edge(u,v), false, 0); + } } // O(1) @@ -933,7 +938,7 @@ namespace boost { remove_edge(source(e, g), target(e, g), g); } - + template inline typename adjacency_matrix::vertex_descriptor add_vertex(adjacency_matrix& g) { @@ -966,7 +971,7 @@ namespace boost { (typename adjacency_matrix::vertex_descriptor u, adjacency_matrix& g) { - typename adjacency_matrix::vertex_iterator + typename adjacency_matrix::vertex_iterator vi, vi_end; for (tie(vi, vi_end) = vertices(g); vi != vi_end; ++vi) remove_edge(u, *vi, g); @@ -989,10 +994,10 @@ namespace boost { //========================================================================= // Vertex Property Map - - template - class adj_matrix_vertex_property_map + + template + class adj_matrix_vertex_property_map : public put_get_helper > { @@ -1031,10 +1036,10 @@ namespace boost { 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; }; }; @@ -1079,14 +1084,14 @@ namespace boost { struct vertex_property_selector { typedef detail::adj_matrix_vertex_property_selector type; }; - + //========================================================================= // Edge Property Map - template - class adj_matrix_edge_property_map + template + class adj_matrix_edge_property_map : public put_get_helper > { @@ -1121,56 +1126,56 @@ namespace boost { namespace detail { - template - typename boost::property_map, + typename boost::property_map, Property>::type get_dispatch(adjacency_matrix& g, Property, vertex_property_tag) { typedef adjacency_matrix Graph; - typedef typename boost::property_map, + typedef typename boost::property_map, Property>::type PA; return PA(&g); } - template - typename boost::property_map, + typename boost::property_map, Property>::type get_dispatch(adjacency_matrix&, Property, edge_property_tag) { - typedef typename boost::property_map, + typedef typename boost::property_map, Property>::type PA; return PA(); } - template - typename boost::property_map, + 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, + typedef typename boost::property_map, Property>::const_type PA; return PA(&g); } - template - typename boost::property_map, + typename boost::property_map, Property>::const_type get_dispatch(const adjacency_matrix&, Property, edge_property_tag) { - typedef typename boost::property_map, + typedef typename boost::property_map, Property>::const_type PA; return PA(); } } // namespace detail - template inline typename property_map, Property>::type @@ -1180,7 +1185,7 @@ namespace boost { return detail::get_dispatch(g, p, Kind()); } - template inline typename property_map, Property>::const_type @@ -1190,7 +1195,7 @@ namespace boost { return detail::get_dispatch(g, p, Kind()); } - template inline typename property_traits< @@ -1202,7 +1207,7 @@ namespace boost { return get(get(p, g), key); } - template inline void put(Property p, adjacency_matrix& g, @@ -1213,11 +1218,11 @@ namespace boost { Map pmap = get(p, g); put(pmap, key, value); } - + //========================================================================= // Other Functions - template + template typename adjacency_matrix::vertex_descriptor vertex(typename adjacency_matrix::vertices_size_type n, const adjacency_matrix& g) @@ -1252,7 +1257,7 @@ namespace boost { result_type; return result_type(&g, p); } - + template inline T diff --git a/test/adjacency_matrix_test.cpp b/test/adjacency_matrix_test.cpp index 75d32c90..7b87e8ac 100644 --- a/test/adjacency_matrix_test.cpp +++ b/test/adjacency_matrix_test.cpp @@ -53,9 +53,7 @@ void run_test() Graph1 g1(24); Graph2 g2(24); - boost::add_edge(boost::vertex(0, g1), boost::vertex(7, g1), g1); - boost::add_edge(boost::vertex(0, g2), boost::vertex(7, g2), g2); - boost::add_edge(boost::vertex(1, g1), boost::vertex(2, g1), g1); +boost::add_edge(boost::vertex(1, g1), boost::vertex(2, g1), g1); boost::add_edge(boost::vertex(1, g2), boost::vertex(2, g2), g2); boost::add_edge(boost::vertex(2, g1), boost::vertex(10, g1), g1); boost::add_edge(boost::vertex(2, g2), boost::vertex(10, g2), g2); @@ -171,7 +169,7 @@ void run_test() { BOOST_CHECK(boost::get(index_map1, *vi1) == boost::get(index_map2, *vi2)); - for (boost::tie(ei1, eend1) = boost::out_edges(*vi1, g1), + for (boost::tie(ei1, eend1) = boost::out_edges(*vi1, g1), boost::tie(ei2, eend2) = boost::out_edges(*vi2, g2); ei1 != eend1; ++ei1, ++ei2) @@ -188,7 +186,7 @@ void run_test() { BOOST_CHECK(boost::get(index_map1, *vi1) == boost::get(index_map2, *vi2)); - for (boost::tie(iei1, ieend1) = boost::in_edges(*vi1, g1), + for (boost::tie(iei1, ieend1) = boost::in_edges(*vi1, g1), boost::tie(iei2, ieend2) = boost::in_edges(*vi2, g2); iei1 != ieend1; ++iei1, ++iei2) @@ -198,23 +196,46 @@ void run_test() } } -int test_main(int, char*[]) +template +void test_remove_edges() { - // Use setS to keep out edges in order, so they match the adjacency_matrix. - typedef boost::adjacency_list - UGraph1; - typedef boost::adjacency_matrix - UGraph2; - run_test(); + using namespace boost; - // Use setS to keep out edges in order, so they match the adjacency_matrix. - typedef boost::adjacency_list - BGraph1; - typedef boost::adjacency_matrix - BGraph2; - run_test(); + // Build a 2-vertex graph + Graph g(2); + add_edge(vertex(0, g), vertex(1, g), g); + BOOST_CHECK(num_vertices(g) == 2); + BOOST_CHECK(num_edges(g) == 1); + remove_edge(vertex(0, g), vertex(1, g), g); + BOOST_CHECK(num_edges(g) == 0); - return 0; + // Make sure we don't decrement the edge count if the edge doesn't actually + // exist. + remove_edge(vertex(0, g), vertex(1, g), g); + BOOST_CHECK(num_edges(g) == 0); +} + + +int test_main(int, char*[]) +{ + // Use setS to keep out edges in order, so they match the adjacency_matrix. + typedef boost::adjacency_list + UGraph1; + typedef boost::adjacency_matrix + UGraph2; + run_test(); + + // Use setS to keep out edges in order, so they match the adjacency_matrix. + typedef boost::adjacency_list + BGraph1; + typedef boost::adjacency_matrix + BGraph2; + run_test(); + + test_remove_edges(); + test_remove_edges(); + + return 0; } From 9ad0c6a23c6cd1e9532113b87d22e6942282ae73 Mon Sep 17 00:00:00 2001 From: Andrew Sutton Date: Mon, 8 Dec 2008 19:03:20 +0000 Subject: [PATCH 042/224] Fixed #1622. A viable solution relies on the fact that incident edges in a loop are stored adjacently in the out edge list of the vertex. A simple modification of the global edge erasing loop for undirected graphs will skip the next iterator if both the current and next contain the same iterator. [SVN r50206] --- include/boost/graph/detail/adjacency_list.hpp | 392 +++++++++--------- test/Jamfile.v2 | 1 + test/adj_list_loops.cpp | 119 ++++++ 3 files changed, 320 insertions(+), 192 deletions(-) create mode 100644 test/adj_list_loops.cpp diff --git a/include/boost/graph/detail/adjacency_list.hpp b/include/boost/graph/detail/adjacency_list.hpp index 43a27bde..b85f307d 100644 --- a/include/boost/graph/detail/adjacency_list.hpp +++ b/include/boost/graph/detail/adjacency_list.hpp @@ -140,7 +140,7 @@ namespace boost { , EdgeDescriptor , Difference > super_t; - + inline out_edge_iter() { } inline out_edge_iter(const BaseIter& i, const VertexDescriptor& src) : super_t(i), m_src(src) { } @@ -148,12 +148,12 @@ namespace boost { inline EdgeDescriptor dereference() const { - return EdgeDescriptor(m_src, (*this->base()).get_target(), + return EdgeDescriptor(m_src, (*this->base()).get_target(), &(*this->base()).get_property()); } VertexDescriptor m_src; }; - + template struct in_edge_iter : iterator_adaptor< @@ -173,9 +173,9 @@ namespace boost { , EdgeDescriptor , Difference > super_t; - + inline in_edge_iter() { } - inline in_edge_iter(const BaseIter& i, const VertexDescriptor& src) + inline in_edge_iter(const BaseIter& i, const VertexDescriptor& src) : super_t(i), m_src(src) { } inline EdgeDescriptor @@ -211,10 +211,10 @@ namespace boost { > super_t; undirected_edge_iter() {} - + explicit undirected_edge_iter(EdgeIter i) : super_t(i) {} - + inline EdgeDescriptor dereference() const { return EdgeDescriptor( @@ -268,11 +268,11 @@ namespace boost { inline stored_edge_property(Vertex target, const Property& p = Property()) : stored_edge(target), m_property(new Property(p)) { } - stored_edge_property(const self& x) + stored_edge_property(const self& x) : Base(x), m_property(const_cast(x).m_property) { } self& operator=(const self& x) { Base::operator=(x); - m_property = const_cast(x).m_property; + m_property = const_cast(x).m_property; return *this; } inline Property& get_property() { return *m_property; } @@ -298,7 +298,7 @@ namespace boost { inline stored_edge_iter(Vertex v, Iter i, void* = 0) : stored_edge(v), m_iter(i) { } inline Property& get_property() { return m_iter->get_property(); } - inline const Property& get_property() const { + inline const Property& get_property() const { return m_iter->get_property(); } inline Iter get_iter() const { return m_iter; } @@ -317,11 +317,11 @@ namespace boost { public: typedef Property property_type; inline stored_ra_edge_iter() { } - inline stored_ra_edge_iter(Vertex v, Iter i = Iter(), + inline stored_ra_edge_iter(Vertex v, Iter i = Iter(), EdgeVec* edge_vec = 0) : 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 const Property& get_property() const { + inline const Property& get_property() const { return (*m_vec)[m_i].get_property(); } inline Iter get_iter() const { return m_vec->begin() + m_i; } @@ -331,7 +331,7 @@ namespace boost { }; } // namespace detail - + template const typename property_value::type& get(Tag property_tag, @@ -355,7 +355,7 @@ namespace boost { { return get_property_value(e.get_property(), property_tag); } - + //========================================================================= // Directed Edges Helper Class @@ -378,7 +378,7 @@ namespace boost { template inline void remove_directed_edge_if_dispatch(incidence_iterator first, - incidence_iterator last, + incidence_iterator last, EdgeList& el, Predicate pred, boost::allow_parallel_edge_tag) { @@ -397,8 +397,8 @@ namespace boost { template inline void remove_directed_edge_if_dispatch(incidence_iterator first, - incidence_iterator last, - EdgeList& el, + incidence_iterator last, + EdgeList& el, Predicate pred, boost::disallow_parallel_edge_tag) { @@ -410,12 +410,12 @@ namespace boost { } } - template inline void - undirected_remove_out_edge_if_dispatch(Graph& g, + undirected_remove_out_edge_if_dispatch(Graph& g, incidence_iterator first, - incidence_iterator last, + incidence_iterator last, EdgeList& el, Predicate pred, boost::allow_parallel_edge_tag) { @@ -444,8 +444,8 @@ namespace boost { else { // Remove the edge from the target detail::remove_directed_edge_dispatch - (*i, - g.out_edge_list(target(*i, g)), + (*i, + g.out_edge_list(target(*i, g)), *(PropT*)(*i).get_property()); } @@ -455,13 +455,13 @@ namespace boost { } el.erase(first.base(), el.end()); } - template inline void - undirected_remove_out_edge_if_dispatch(Graph& g, + undirected_remove_out_edge_if_dispatch(Graph& g, incidence_iterator first, - incidence_iterator last, - EdgeList& el, + incidence_iterator last, + EdgeList& el, Predicate pred, boost::disallow_parallel_edge_tag) { @@ -475,8 +475,8 @@ namespace boost { if (source(*first, g) != target(*first, g)) { // Remove the edge from the target detail::remove_directed_edge_dispatch - (*first, - g.out_edge_list(target(*first, g)), + (*first, + g.out_edge_list(target(*first, g)), *(PropT*)(*first).get_property()); } @@ -510,7 +510,7 @@ namespace boost { // Placement of these overloaded remove_edge() functions // inside the class avoids a VC++ bug. - + // O(E/V) inline void remove_edge(typename Config::edge_descriptor e) @@ -538,7 +538,7 @@ namespace boost { // O(1) template - inline std::pair edges(const directed_edges_helper& g_) { @@ -546,8 +546,8 @@ namespace boost { typedef typename Config::edge_iterator edge_iterator; const graph_type& cg = static_cast(g_); graph_type& g = const_cast(cg); - return std::make_pair( edge_iterator(g.vertex_set().begin(), - g.vertex_set().begin(), + return std::make_pair( edge_iterator(g.vertex_set().begin(), + g.vertex_set().begin(), g.vertex_set().end(), g), edge_iterator(g.vertex_set().begin(), g.vertex_set().end(), @@ -565,7 +565,7 @@ namespace boost { template struct directed_graph_helper - : public directed_edges_helper { + : public directed_edges_helper { typedef typename Config::edge_descriptor edge_descriptor; typedef adj_list_dir_traversal_tag traversal_category; }; @@ -607,7 +607,7 @@ namespace boost { typename Config::vertex_iterator vi, vi_end; for (tie(vi, vi_end) = vertices(g); vi != vi_end; ++vi) remove_out_edge_if(*vi, pred, g); - } + } template inline void @@ -619,7 +619,7 @@ namespace boost { // O(V + E) for allow_parallel_edges // O(V * log(E/V)) for disallow_parallel_edges template - inline void + inline void clear_vertex(typename Config::vertex_descriptor u, directed_graph_helper& g_) { @@ -635,7 +635,7 @@ namespace boost { } template - inline void + inline void clear_out_edges(typename Config::vertex_descriptor u, directed_graph_helper& g_) { @@ -664,27 +664,27 @@ namespace boost { // O(log(E/V)) for disallow_parallel_edge_tag template inline std::pair::edge_descriptor, bool> - add_edge(typename Config::vertex_descriptor u, + add_edge(typename Config::vertex_descriptor u, typename Config::vertex_descriptor v, - const typename Config::edge_property_type& p, + const typename Config::edge_property_type& p, directed_graph_helper& g_) { typedef typename Config::edge_descriptor edge_descriptor; typedef typename Config::graph_type graph_type; typedef typename Config::StoredEdge StoredEdge; graph_type& g = static_cast(g_); - typename Config::OutEdgeList::iterator i; + typename Config::OutEdgeList::iterator i; bool inserted; - boost::tie(i, inserted) = boost::graph_detail::push(g.out_edge_list(u), + boost::tie(i, inserted) = boost::graph_detail::push(g.out_edge_list(u), StoredEdge(v, p)); - return std::make_pair(edge_descriptor(u, v, &(*i).get_property()), + return std::make_pair(edge_descriptor(u, v, &(*i).get_property()), inserted); } // Did not use default argument here because that // causes Visual C++ to get confused. template inline std::pair - add_edge(typename Config::vertex_descriptor u, + add_edge(typename Config::vertex_descriptor u, typename Config::vertex_descriptor v, directed_graph_helper& g_) { @@ -697,7 +697,7 @@ namespace boost { template struct undirected_graph_helper; - struct undir_adj_list_traversal_tag : + struct undir_adj_list_traversal_tag : public virtual vertex_list_graph_tag, public virtual incidence_graph_tag, public virtual adjacency_graph_tag, @@ -713,8 +713,8 @@ namespace boost { // O(E/V) template static void - apply(edge_descriptor e, - undirected_graph_helper& g_, + apply(edge_descriptor e, + undirected_graph_helper& g_, StoredProperty& p) { typedef typename Config::global_edgelist_selector EdgeListS; @@ -722,7 +722,7 @@ namespace boost { typedef typename Config::graph_type graph_type; graph_type& g = static_cast(g_); - + typename Config::OutEdgeList& out_el = g.out_edge_list(source(e, g)); typename Config::OutEdgeList::iterator out_i = out_el.begin(); for (; out_i != out_el.end(); ++out_i) @@ -777,7 +777,7 @@ namespace boost { // O(E/V) template inline void - remove_edge_and_property(Graph& g, EdgeList& el, Vertex v, + remove_edge_and_property(Graph& g, EdgeList& el, Vertex v, boost::allow_parallel_edge_tag cat) { typedef typename Graph::global_edgelist_selector EdgeListS; @@ -785,15 +785,23 @@ namespace boost { typedef typename EdgeList::value_type StoredEdge; typename EdgeList::iterator i = el.begin(), end = el.end(); - for (; i != end; ++i) - if ((*i).get_target() == v) + for (; i != end; ++i) { + if((*i).get_target() == v) { + // NOTE: Wihtout this skip, this loop will double-delete properties + // of loop edges. This solution is based on the observation that + // the incidence edges of a vertex with a loop are adjacent in the + // out edge list. This *may* actually hold for multisets also. + bool skip = (next(i) != end && i->get_iter() == next(i)->get_iter()); g.m_edges.erase((*i).get_iter()); + if(skip) ++i; + } + } detail::erase_from_incidence_list(el, v, cat); } // O(log(E/V)) template inline void - remove_edge_and_property(Graph& g, EdgeList& el, Vertex v, + remove_edge_and_property(Graph& g, EdgeList& el, Vertex v, boost::disallow_parallel_edge_tag) { typedef typename Graph::global_edgelist_selector EdgeListS; @@ -857,15 +865,15 @@ namespace boost { // Had to make these non-members to avoid accidental instantiation // on SGI MIPSpro C++ template - inline typename C::InEdgeList& - in_edge_list(undirected_graph_helper&, + inline typename C::InEdgeList& + in_edge_list(undirected_graph_helper&, typename C::vertex_descriptor v) { typename C::stored_vertex* sv = (typename C::stored_vertex*)v; return sv->m_out_edges; } template - inline const typename C::InEdgeList& + inline const typename C::InEdgeList& in_edge_list(const undirected_graph_helper&, typename C::vertex_descriptor v) { typename C::stored_vertex* sv = (typename C::stored_vertex*)v; @@ -886,8 +894,8 @@ namespace boost { // O(E/V) or O(log(E/V)) template void - remove_edge(typename Config::vertex_descriptor u, - typename Config::vertex_descriptor v, + remove_edge(typename Config::vertex_descriptor u, + typename Config::vertex_descriptor v, undirected_graph_helper& g_) { typedef typename Config::global_edgelist_selector EdgeListS; @@ -899,7 +907,7 @@ namespace boost { detail::remove_edge_and_property(g, g.out_edge_list(u), v, Cat()); detail::erase_from_incidence_list(g.out_edge_list(v), u, Cat()); } - + template void remove_out_edge_if(typename Config::vertex_descriptor u, Predicate pred, @@ -907,7 +915,7 @@ namespace boost { { typedef typename Config::global_edgelist_selector EdgeListS; BOOST_STATIC_ASSERT((!is_same::value)); - + typedef typename Config::graph_type graph_type; typedef typename Config::OutEdgeList::value_type::property_type PropT; graph_type& g = static_cast(g_); @@ -949,7 +957,7 @@ namespace boost { // O(1) template - inline std::pair edges(const undirected_graph_helper& g_) { @@ -963,7 +971,7 @@ namespace boost { // O(1) template inline typename Config::edges_size_type - num_edges(const undirected_graph_helper& g_) + num_edges(const undirected_graph_helper& g_) { typedef typename Config::graph_type graph_type; const graph_type& g = static_cast(g_); @@ -971,7 +979,7 @@ namespace boost { } // O(E/V * E/V) template - inline void + inline void clear_vertex(typename Config::vertex_descriptor u, undirected_graph_helper& g_) { @@ -982,7 +990,7 @@ namespace boost { 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 + typename Config::OutEdgeList::iterator ei = el.begin(), ei_end = el.end(); for (; ei != ei_end; ++ei) { detail::erase_from_incidence_list @@ -995,8 +1003,8 @@ namespace boost { // O(log(E/V)) for disallow_parallel_edge_tag template inline std::pair - add_edge(typename Config::vertex_descriptor u, - typename Config::vertex_descriptor v, + add_edge(typename Config::vertex_descriptor u, + typename Config::vertex_descriptor v, const typename Config::edge_property_type& p, undirected_graph_helper& g_) { @@ -1007,11 +1015,11 @@ namespace boost { bool inserted; typename Config::EdgeContainer::value_type e(u, v, p); - typename Config::EdgeContainer::iterator p_iter + typename Config::EdgeContainer::iterator p_iter = graph_detail::push(g.m_edges, e).first; typename Config::OutEdgeList::iterator i; - boost::tie(i, inserted) = boost::graph_detail::push(g.out_edge_list(u), + boost::tie(i, inserted) = boost::graph_detail::push(g.out_edge_list(u), StoredEdge(v, p_iter, &g.m_edges)); if (inserted) { boost::graph_detail::push(g.out_edge_list(v), StoredEdge(u, p_iter, &g.m_edges)); @@ -1025,8 +1033,8 @@ namespace boost { } template inline std::pair - add_edge(typename Config::vertex_descriptor u, - typename Config::vertex_descriptor v, + add_edge(typename Config::vertex_descriptor u, + typename Config::vertex_descriptor v, undirected_graph_helper& g_) { typename Config::edge_property_type p; @@ -1036,7 +1044,7 @@ namespace boost { // O(1) template inline typename Config::degree_size_type - degree(typename Config::vertex_descriptor u, + degree(typename Config::vertex_descriptor u, const undirected_graph_helper& g_) { typedef typename Config::graph_type Graph; @@ -1045,9 +1053,9 @@ namespace boost { } template - inline std::pair - in_edges(typename Config::vertex_descriptor u, + in_edges(typename Config::vertex_descriptor u, const undirected_graph_helper& g_) { typedef typename Config::graph_type Graph; @@ -1068,7 +1076,7 @@ namespace boost { //========================================================================= // Bidirectional Graph Helper Class - struct bidir_adj_list_traversal_tag : + struct bidir_adj_list_traversal_tag : public virtual vertex_list_graph_tag, public virtual incidence_graph_tag, public virtual adjacency_graph_tag, @@ -1084,15 +1092,15 @@ namespace boost { // Had to make these non-members to avoid accidental instantiation // on SGI MIPSpro C++ template - inline typename C::InEdgeList& - in_edge_list(bidirectional_graph_helper&, + inline typename C::InEdgeList& + in_edge_list(bidirectional_graph_helper&, typename C::vertex_descriptor v) { typename C::stored_vertex* sv = (typename C::stored_vertex*)v; return sv->m_in_edges; } template - inline const typename C::InEdgeList& + inline const typename C::InEdgeList& in_edge_list(const bidirectional_graph_helper&, typename C::vertex_descriptor v) { typename C::stored_vertex* sv = (typename C::stored_vertex*)v; @@ -1118,9 +1126,9 @@ namespace boost { } template - inline std::pair - in_edges(typename Config::vertex_descriptor u, + in_edges(typename Config::vertex_descriptor u, const bidirectional_graph_helper& g_) { typedef typename Config::graph_type graph_type; @@ -1134,7 +1142,7 @@ namespace boost { // O(1) template - inline std::pair edges(const bidirectional_graph_helper& g_) { @@ -1156,7 +1164,7 @@ namespace boost { { typedef typename Config::graph_type graph_type; typedef typename Config::out_edge_iterator out_edge_iterator; - + std::pair get_parallel_edge_sublist(typename Config::edge_descriptor e, const graph_type& g, @@ -1197,7 +1205,7 @@ namespace boost { typedef typename Config::edgelist_selector OutEdgeListS; - std::pair rng = + 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); @@ -1227,8 +1235,8 @@ namespace boost { // O(log(E/V)) for disallow_parallel_edge_tag template inline void - remove_edge(typename Config::vertex_descriptor u, - typename Config::vertex_descriptor v, + remove_edge(typename Config::vertex_descriptor u, + typename Config::vertex_descriptor v, bidirectional_graph_helper_with_property& g_) { typedef typename Config::global_edgelist_selector EdgeListS; @@ -1264,7 +1272,7 @@ namespace boost { typedef typename Config::graph_type graph_type; typedef typename Config::OutEdgeList::value_type::property_type PropT; graph_type& g = static_cast(g_); - + typedef typename Config::EdgeIter EdgeIter; typedef std::vector Garbage; Garbage garbage; @@ -1338,7 +1346,7 @@ namespace boost { // O(1) template inline typename Config::edges_size_type - num_edges(const bidirectional_graph_helper_with_property& g_) + num_edges(const bidirectional_graph_helper_with_property& g_) { typedef typename Config::graph_type graph_type; const graph_type& g = static_cast(g_); @@ -1358,20 +1366,20 @@ namespace boost { 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 + typename Config::OutEdgeList::iterator ei = el.begin(), ei_end = el.end(); for (; ei != ei_end; ++ei) { detail::erase_from_incidence_list (in_edge_list(g, (*ei).get_target()), u, Cat()); g.m_edges.erase((*ei).get_iter()); - } + } typename Config::InEdgeList& in_el = in_edge_list(g, u); - typename Config::InEdgeList::iterator + typename Config::InEdgeList::iterator in_ei = in_el.begin(), in_ei_end = in_el.end(); for (; in_ei != in_ei_end; ++in_ei) { detail::erase_from_incidence_list (g.out_edge_list((*in_ei).get_target()), u, Cat()); - g.m_edges.erase((*in_ei).get_iter()); + g.m_edges.erase((*in_ei).get_iter()); } g.out_edge_list(u).clear(); in_edge_list(g, u).clear(); @@ -1389,13 +1397,13 @@ namespace boost { 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 + typename Config::OutEdgeList::iterator ei = el.begin(), ei_end = el.end(); for (; ei != ei_end; ++ei) { detail::erase_from_incidence_list (in_edge_list(g, (*ei).get_target()), u, Cat()); g.m_edges.erase((*ei).get_iter()); - } + } g.out_edge_list(u).clear(); } @@ -1411,12 +1419,12 @@ namespace boost { typedef typename Config::edge_parallel_category Cat; graph_type& g = static_cast(g_); typename Config::InEdgeList& in_el = in_edge_list(g, u); - typename Config::InEdgeList::iterator + typename Config::InEdgeList::iterator in_ei = in_el.begin(), in_ei_end = in_el.end(); for (; in_ei != in_ei_end; ++in_ei) { detail::erase_from_incidence_list (g.out_edge_list((*in_ei).get_target()), u, Cat()); - g.m_edges.erase((*in_ei).get_iter()); + g.m_edges.erase((*in_ei).get_iter()); } in_edge_list(g, u).clear(); } @@ -1426,7 +1434,7 @@ namespace boost { template inline std::pair add_edge(typename Config::vertex_descriptor u, - typename Config::vertex_descriptor v, + typename Config::vertex_descriptor v, const typename Config::edge_property_type& p, bidirectional_graph_helper_with_property& g_) { @@ -1436,19 +1444,19 @@ namespace boost { typedef typename Config::StoredEdge StoredEdge; bool inserted; typename Config::EdgeContainer::value_type e(u, v, p); - typename Config::EdgeContainer::iterator p_iter + typename Config::EdgeContainer::iterator p_iter = graph_detail::push(g.m_edges, e).first; typename Config::OutEdgeList::iterator i; - boost::tie(i, inserted) = boost::graph_detail::push(g.out_edge_list(u), + boost::tie(i, inserted) = boost::graph_detail::push(g.out_edge_list(u), StoredEdge(v, p_iter, &g.m_edges)); if (inserted) { boost::graph_detail::push(in_edge_list(g, v), StoredEdge(u, p_iter, &g.m_edges)); - return std::make_pair(edge_descriptor(u, v, &p_iter->m_property), + return std::make_pair(edge_descriptor(u, v, &p_iter->m_property), true); } else { g.m_edges.erase(p_iter); - return std::make_pair(edge_descriptor(u, v, - &i->get_iter()->get_property()), + return std::make_pair(edge_descriptor(u, v, + &i->get_iter()->get_property()), false); } } @@ -1465,7 +1473,7 @@ namespace boost { // O(1) template inline typename Config::degree_size_type - degree(typename Config::vertex_descriptor u, + degree(typename Config::vertex_descriptor u, const bidirectional_graph_helper_with_property& g_) { typedef typename Config::graph_type graph_type; @@ -1505,15 +1513,15 @@ namespace boost { // Borland gets confused about constness. // O(E/V) - inline std::pair - edge_dispatch(const AdjList& g, - vertex_descriptor u, vertex_descriptor v, + inline std::pair + edge_dispatch(const AdjList& g, + vertex_descriptor u, vertex_descriptor v, boost::allow_parallel_edge_tag) const { bool found; const typename Config::OutEdgeList& el = g.out_edge_list(u); - typename Config::OutEdgeList::const_iterator - i = std::find_if(el.begin(), el.end(), + typename Config::OutEdgeList::const_iterator + i = std::find_if(el.begin(), el.end(), detail::target_is(v)); found = (i != g.out_edge_list(u).end()); if (found) @@ -1523,9 +1531,9 @@ namespace boost { return std::make_pair(edge_descriptor(u, v, 0), false); } // O(log(E/V)) - inline std::pair - edge_dispatch(const AdjList& g, - vertex_descriptor u, vertex_descriptor v, + inline std::pair + edge_dispatch(const AdjList& g, + vertex_descriptor u, vertex_descriptor v, boost::disallow_parallel_edge_tag) const { bool found; @@ -1533,7 +1541,7 @@ namespace boost { but the VC++ std::set::find() const returns const_iterator. And since iterator should be convertible to const_iterator, the following should work everywhere. -Jeremy */ - typename Config::OutEdgeList::const_iterator + typename Config::OutEdgeList::const_iterator i = g.out_edge_list(u).find(StoredEdge(v)), end = g.out_edge_list(u).end(); found = (i != end); @@ -1546,9 +1554,9 @@ namespace boost { }; template - inline std::pair - adjacent_vertices(typename Config::vertex_descriptor u, + adjacent_vertices(typename Config::vertex_descriptor u, const adj_list_helper& g_) { typedef typename Config::graph_type AdjList; @@ -1561,9 +1569,9 @@ namespace boost { adjacency_iterator(last, &g)); } template - inline std::pair - inv_adjacent_vertices(typename Config::vertex_descriptor u, + inv_adjacent_vertices(typename Config::vertex_descriptor u, const adj_list_helper& g_) { typedef typename Config::graph_type AdjList; @@ -1576,9 +1584,9 @@ namespace boost { inv_adjacency_iterator(last, &g)); } template - inline std::pair - out_edges(typename Config::vertex_descriptor u, + out_edges(typename Config::vertex_descriptor u, const adj_list_helper& g_) { typedef typename Config::graph_type AdjList; @@ -1590,7 +1598,7 @@ namespace boost { out_edge_iterator(g.out_edge_list(u).end(), u)); } template - inline std::pair vertices(const adj_list_helper& g_) { @@ -1609,7 +1617,7 @@ namespace boost { } template inline typename Config::degree_size_type - out_degree(typename Config::vertex_descriptor u, + out_degree(typename Config::vertex_descriptor u, const adj_list_helper& g_) { typedef typename Config::graph_type AdjList; @@ -1618,8 +1626,8 @@ namespace boost { } template inline std::pair - edge(typename Config::vertex_descriptor u, - typename Config::vertex_descriptor v, + edge(typename Config::vertex_descriptor u, + typename Config::vertex_descriptor v, const adj_list_helper& g_) { typedef typename Config::graph_type Graph; @@ -1642,8 +1650,8 @@ namespace boost { typename Config::OutEdgeList& el = g.out_edge_list(u); typename Config::OutEdgeList::iterator first, last; typename Config::EdgeContainer fake_edge_container; - tie(first, last) = - std::equal_range(el.begin(), el.end(), + tie(first, last) = + std::equal_range(el.begin(), el.end(), StoredEdge(v, fake_edge_container.end(), &fake_edge_container)); return std::make_pair(out_edge_iterator(first, u), @@ -1652,7 +1660,7 @@ namespace boost { template inline typename Config::degree_size_type - in_degree(typename Config::vertex_descriptor u, + in_degree(typename Config::vertex_descriptor u, const directed_edges_helper& g_) { typedef typename Config::graph_type Graph; @@ -1666,7 +1674,7 @@ namespace boost { inline typename boost::property_map::type - get_dispatch(adj_list_helper&, Property, + get_dispatch(adj_list_helper&, Property, boost::edge_property_tag) { typedef typename Config::graph_type Graph; typedef typename boost::property_map::type PA; @@ -1674,9 +1682,9 @@ namespace boost { } template inline - typename boost::property_map::const_type - get_dispatch(const adj_list_helper&, Property, + get_dispatch(const adj_list_helper&, Property, boost::edge_property_tag) { typedef typename Config::graph_type Graph; typedef typename boost::property_map::const_type PA; @@ -1685,9 +1693,9 @@ namespace boost { template inline - typename boost::property_map::type - get_dispatch(adj_list_helper& g, Property, + get_dispatch(adj_list_helper& g, Property, boost::vertex_property_tag) { typedef typename Config::graph_type Graph; typedef typename boost::property_map::type PA; @@ -1697,7 +1705,7 @@ namespace boost { inline typename boost::property_map::const_type - get_dispatch(const adj_list_helper& g, Property, + get_dispatch(const adj_list_helper& g, Property, boost::vertex_property_tag) { typedef typename Config::graph_type Graph; typedef typename boost::property_map::const_type PA; @@ -1717,7 +1725,7 @@ namespace boost { } template inline - typename boost::property_map::const_type get(Property p, const adj_list_helper& g) { typedef typename property_kind::type Kind; @@ -1727,7 +1735,7 @@ namespace boost { template inline typename boost::property_traits< - typename boost::property_map::type >::reference get(Property p, adj_list_helper& g, const Key& key) { @@ -1737,7 +1745,7 @@ namespace boost { template inline typename boost::property_traits< - typename boost::property_map::const_type >::reference get(Property p, const adj_list_helper& g, const Key& key) { @@ -1746,7 +1754,7 @@ namespace boost { template inline void - put(Property p, adj_list_helper& g, + put(Property p, adj_list_helper& g, const Key& key, const Value& value) { typedef typename Config::graph_type Graph; @@ -1786,7 +1794,7 @@ namespace boost { { return 0; } - + inline adj_list_impl() { } inline adj_list_impl(const adj_list_impl& x) { @@ -1855,7 +1863,7 @@ namespace boost { inline StoredVertexList& vertex_set() { return m_vertices; } inline const StoredVertexList& vertex_set() const { return m_vertices; } - inline void copy_impl(const adj_list_impl& x_) + inline void copy_impl(const adj_list_impl& x_) { const Derived& x = static_cast(x_); @@ -1876,9 +1884,9 @@ namespace boost { edge_iterator ei, ei_end; for (tie(ei, ei_end) = edges(x); ei != ei_end; ++ei) { edge_descriptor e; - bool inserted; + bool inserted; vertex_descriptor s = source(*ei,x), t = target(*ei,x); - tie(e, inserted) = add_edge(vertex_map[(stored_vertex*)s], + tie(e, inserted) = add_edge(vertex_map[(stored_vertex*)s], vertex_map[(stored_vertex*)t], *this); *((edge_property_type*)e.m_eproperty) = *((edge_property_type*)(*ei).m_eproperty); @@ -1913,7 +1921,7 @@ namespace boost { { typedef typename Config::vertex_descriptor vertex_descriptor; Derived& g = static_cast(g_); - if (optional v + if (optional v = g.vertex_by_property(get_property_value(p, vertex_bundle))) return *v; @@ -1941,7 +1949,7 @@ namespace boost { // O(V) template inline typename Config::vertex_descriptor - vertex(typename Config::vertices_size_type n, + vertex(typename Config::vertices_size_type n, const adj_list_impl& g_) { const Derived& g = static_cast(g_); @@ -1956,8 +1964,8 @@ namespace boost { namespace detail { template - inline void - remove_vertex_dispatch(Graph& g, vertex_descriptor u, + inline void + remove_vertex_dispatch(Graph& g, vertex_descriptor u, boost::directed_tag) { typedef typename Graph::edge_parallel_category edge_parallel_category; @@ -1970,8 +1978,8 @@ namespace boost { } template - inline void - remove_vertex_dispatch(Graph& g, vertex_descriptor u, + inline void + remove_vertex_dispatch(Graph& g, vertex_descriptor u, boost::undirected_tag) { typedef typename Graph::global_edgelist_selector EdgeListS; @@ -1981,7 +1989,7 @@ namespace boost { g.m_vertices.erase(g.m_vertices.begin() + u); vertex_descriptor V = num_vertices(g); for (vertex_descriptor v = 0; v < V; ++v) - reindex_edge_list(g.out_edge_list(v), u, + reindex_edge_list(g.out_edge_list(v), u, edge_parallel_category()); typedef typename Graph::EdgeContainer Container; typedef typename Container::iterator Iter; @@ -1994,8 +2002,8 @@ namespace boost { } } template - inline void - remove_vertex_dispatch(Graph& g, vertex_descriptor u, + inline void + remove_vertex_dispatch(Graph& g, vertex_descriptor u, boost::bidirectional_tag) { typedef typename Graph::global_edgelist_selector EdgeListS; @@ -2007,10 +2015,10 @@ namespace boost { vertex_descriptor v; if (u != V) { for (v = 0; v < V; ++v) - reindex_edge_list(g.out_edge_list(v), u, + reindex_edge_list(g.out_edge_list(v), u, edge_parallel_category()); for (v = 0; v < V; ++v) - reindex_edge_list(in_edge_list(g, v), u, + reindex_edge_list(in_edge_list(g, v), u, edge_parallel_category()); typedef typename Graph::EdgeContainer Container; @@ -2027,7 +2035,7 @@ namespace boost { template inline void - reindex_edge_list(EdgeList& el, vertex_descriptor u, + reindex_edge_list(EdgeList& el, vertex_descriptor u, boost::allow_parallel_edge_tag) { typename EdgeList::iterator ei = el.begin(), e_end = el.end(); @@ -2037,7 +2045,7 @@ namespace boost { } template inline void - reindex_edge_list(EdgeList& el, vertex_descriptor u, + reindex_edge_list(EdgeList& el, vertex_descriptor u, boost::disallow_parallel_edge_tag) { typename EdgeList::iterator ei = el.begin(), e_end = el.end(); @@ -2054,14 +2062,14 @@ namespace boost { } // namespace detail struct vec_adj_list_tag { }; - + template class vec_adj_list_impl : public adj_list_helper { typedef typename Config::OutEdgeList OutEdgeList; typedef typename Config::InEdgeList InEdgeList; - typedef typename Config::StoredVertexList StoredVertexList; + typedef typename Config::StoredVertexList StoredVertexList; public: typedef typename Config::vertex_descriptor vertex_descriptor; typedef typename Config::edge_descriptor edge_descriptor; @@ -2081,7 +2089,7 @@ namespace boost { { return (std::numeric_limits::max)(); } - + inline vec_adj_list_impl() { } inline vec_adj_list_impl(const vec_adj_list_impl& x) { @@ -2106,7 +2114,7 @@ namespace boost { : m_vertices(num_vertices) { while (first != last) { - add_edge((*first).first, (*first).second, + add_edge((*first).first, (*first).second, static_cast(*this)); ++first; } @@ -2118,7 +2126,7 @@ namespace boost { : m_vertices(num_vertices) { while (first != last) { - add_edge((*first).first, (*first).second, *ep_iter, + add_edge((*first).first, (*first).second, *ep_iter, static_cast(*this)); ++first; ++ep_iter; @@ -2135,7 +2143,7 @@ namespace boost { inline const OutEdgeList& out_edge_list(vertex_descriptor v) const { return m_vertices[v].m_out_edges; } - inline void copy_impl(const vec_adj_list_impl& x_) + inline void copy_impl(const vec_adj_list_impl& x_) { const Graph& x = static_cast(x_); // Copy the stored vertex objects by adding each vertex @@ -2149,7 +2157,7 @@ namespace boost { edge_iterator ei, ei_end; for (tie(ei, ei_end) = edges(x); ei != ei_end; ++ei) { edge_descriptor e; - bool inserted; + bool inserted; tie(e, inserted) = add_edge(source(*ei,x), target(*ei,x) , *this); *((edge_property_type*)e.m_eproperty) = *((edge_property_type*)(*ei).m_eproperty); @@ -2161,14 +2169,14 @@ namespace boost { // Had to make these non-members to avoid accidental instantiation // on SGI MIPSpro C++ template - inline typename C::InEdgeList& - in_edge_list(vec_adj_list_impl& g, + inline typename C::InEdgeList& + in_edge_list(vec_adj_list_impl& g, typename C::vertex_descriptor v) { return g.m_vertices[v].m_in_edges; } template - inline const typename C::InEdgeList& - in_edge_list(const vec_adj_list_impl& g, + inline const typename C::InEdgeList& + in_edge_list(const vec_adj_list_impl& g, typename C::vertex_descriptor v) { return g.m_vertices[v].m_in_edges; } @@ -2189,7 +2197,7 @@ namespace boost { vec_adj_list_impl& g_) { typedef typename Config::vertex_descriptor vertex_descriptor; Graph& g = static_cast(g_); - if (optional v + if (optional v = g.vertex_by_property(get_property_value(p, vertex_bundle))) return *v; typedef typename Config::stored_vertex stored_vertex; @@ -2203,7 +2211,7 @@ namespace boost { // either u or v is greater than the number of vertices. template inline std::pair - add_edge(typename Config::vertex_descriptor u, + add_edge(typename Config::vertex_descriptor u, typename Config::vertex_descriptor v, const typename Config::edge_property_type& p, vec_adj_list_impl& g_) @@ -2217,7 +2225,7 @@ namespace boost { } template inline std::pair - add_edge(typename Config::vertex_descriptor u, + add_edge(typename Config::vertex_descriptor u, typename Config::vertex_descriptor v, vec_adj_list_impl& g_) { @@ -2238,8 +2246,8 @@ namespace boost { } // O(1) template - inline typename Config::vertex_descriptor - vertex(typename Config::vertices_size_type n, + inline typename Config::vertex_descriptor + vertex(typename Config::vertices_size_type n, const vec_adj_list_impl&) { return n; @@ -2252,13 +2260,13 @@ namespace boost { // Adjacency List Generator template struct adj_list_gen { - typedef typename detail::is_random_access::type + typedef typename detail::is_random_access::type is_rand_access; - typedef typename has_property::type has_edge_property; + typedef typename has_property::type has_edge_property; typedef typename DirectedS::is_directed_t DirectedT; typedef typename DirectedS::is_bidir_t BidirectionalT; @@ -2273,7 +2281,7 @@ namespace boost { typedef GraphProperty graph_property_type; typedef std::size_t vertices_size_type; - typedef adjacency_list_traits + typedef adjacency_list_traits Traits; typedef typename Traits::directed_category directed_category; @@ -2281,13 +2289,13 @@ namespace boost { typedef typename Traits::vertex_descriptor vertex_descriptor; typedef typename Traits::edge_descriptor edge_descriptor; - typedef void* vertex_ptr; + typedef void* vertex_ptr; // need to reorganize this to avoid instantiating stuff // that doesn't get used -JGS // VertexList and vertex_iterator - typedef typename container_gen::type SeqVertexList; typedef boost::integer_range RandVertexList; typedef typename mpl::if_ >::type EdgeContainer; - typedef typename mpl::and_::type >::type on_edge_storage; typedef typename mpl::if_::type + typedef typename container_gen::type OutEdgeList; typedef typename OutEdgeList::size_type degree_size_type; typedef typename OutEdgeList::iterator OutEdgeIter; @@ -2358,10 +2366,10 @@ namespace boost { typedef undirected_edge_iter< EdgeIter , edge_descriptor - , EdgeIterDiff + , EdgeIterDiff > UndirectedEdgeIter; // also used for bidirectional - typedef adj_list_edge_iterator DirectedEdgeIter; typedef typename mpl::if_ struct adj_list_edge_property_map - : public put_get_helper< + : public put_get_helper< Ref, - adj_list_edge_property_map > { @@ -2667,7 +2675,7 @@ namespace boost { class Vertex> struct adj_list_edge_all_properties_map : public put_get_helper > { @@ -2692,12 +2700,12 @@ namespace boost { typedef typename property_value::type value_type; typedef value_type& reference; typedef const value_type& const_reference; - + typedef adj_list_edge_property_map - type; typedef adj_list_edge_property_map - const_type; }; }; @@ -2708,7 +2716,7 @@ namespace boost { type; typedef adj_list_edge_all_properties_map - const_type; }; }; @@ -2738,11 +2746,11 @@ namespace boost { }; } // namespace detail - template <> + template <> struct edge_property_selector { typedef detail::adj_list_edge_property_selector type; }; - template <> + template <> struct edge_property_selector { typedef detail::adj_list_edge_property_selector type; }; @@ -2757,7 +2765,7 @@ namespace boost { typedef typename Choice::const_type const_type; }; }; - template <> + template <> struct vertex_property_selector { typedef adj_list_vertex_property_selector type; }; @@ -2770,7 +2778,7 @@ namespace boost { typedef typename Choice::const_type const_type; }; }; - template <> + template <> struct vertex_property_selector { typedef vec_adj_list_vertex_property_selector type; }; @@ -2792,7 +2800,7 @@ namespace BOOST_STD_EXTENSION_NAMESPACE { #endif template - struct hash< boost::detail::stored_edge > + struct hash< boost::detail::stored_edge > { std::size_t operator()(const boost::detail::stored_edge& e) const @@ -2802,7 +2810,7 @@ namespace BOOST_STD_EXTENSION_NAMESPACE { }; template - struct hash< boost::detail::stored_edge_property > + struct hash< boost::detail::stored_edge_property > { std::size_t operator()(const boost::detail::stored_edge_property& e) const @@ -2812,7 +2820,7 @@ namespace BOOST_STD_EXTENSION_NAMESPACE { }; template - struct hash< boost::detail::stored_edge_iter > + struct hash< boost::detail::stored_edge_iter > { std::size_t operator()(const boost::detail::stored_edge_iter& e) const @@ -2838,17 +2846,17 @@ namespace BOOST_STD_EXTENSION_NAMESPACE { /* Implementation Notes: - + Many of the public interface functions in this file would have been more conveniently implemented as inline friend functions. However there are a few compiler bugs that make that approach non-portable. - + 1. g++ inline friend in namespace bug 2. g++ using clause doesn't work with inline friends 3. VC++ doesn't have Koenig lookup - For these reasons, the functions were all written as non-inline free + For these reasons, the functions were all written as non-inline free functions, and static cast was used to convert from the helper class to the adjacency_list derived class. diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index b69332ca..71abf97b 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -29,6 +29,7 @@ test-suite graph_test : # unit-test adj_list_test : adj_list_test.cpp ; [ run adj_list_edge_list_set.cpp ] + [ run adj_list_loops.cpp ] [ compile adj_matrix_cc.cpp ] [ run bfs.cpp ../../test/build//boost_test_exec_monitor ] [ compile bfs_cc.cpp ] diff --git a/test/adj_list_loops.cpp b/test/adj_list_loops.cpp new file mode 100644 index 00000000..d47116cd --- /dev/null +++ b/test/adj_list_loops.cpp @@ -0,0 +1,119 @@ + +#if __GNUC__ == 4 && __GNUC_MINOR__ >= 3 +# define BOOST_NO_HASH +#endif + +#include "typestr.hpp" + +#include + +#include +#include + +using namespace boost; + +// TODO: Integrate this into a larger adj_list test suite. + +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); + Vertex u = *vertices(g).first; + Vertex v = *next(vertices(g).first, 2); + add_edge(u, v, g); + BOOST_ASSERT(num_vertices(g) == 5); + BOOST_ASSERT(num_edges(g) == 1); + remove_edge(u, v, g); + BOOST_ASSERT(num_edges(g) == 0); + +} + + +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); + Vertex u = *vertices(g).first; + Vertex v = *next(vertices(g).first, 2); + add_edge(u, v, g); + add_edge(u, v, g); + BOOST_ASSERT(num_vertices(g) == 5); + BOOST_ASSERT(num_edges(g) == 2); + remove_edge(u, v, g); + BOOST_ASSERT(num_edges(g) == 0); + +} + +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); + add_edge(v, v, g); + BOOST_ASSERT(num_vertices(g) == 5); + BOOST_ASSERT(num_edges(g) == 1); + remove_edge(v, v, g); + BOOST_ASSERT(num_edges(g) == 0); +} + +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); + add_edge(v, v, g); + add_edge(v, v, g); + BOOST_ASSERT(num_vertices(g) == 5); + BOOST_ASSERT(num_edges(g) == 2); + remove_edge(v, v, g); + BOOST_ASSERT(num_edges(g) == 0); +} + +template +void test() +{ + typedef no_property na; + typedef adjacency_list VVL; + typedef adjacency_list LVL; + typedef adjacency_list SVL; + typedef adjacency_list MVL; + + test_graph_nonloop(); + test_graph_nonloop(); + test_graph_nonloop(); + test_graph_nonloop(); + test_multigraph_nonloop(); + test_multigraph_nonloop(); + test_multigraph_nonloop(); + test_graph_loop(); + test_graph_loop(); + test_graph_loop(); + test_graph_loop(); + test_multigraph_loop(); + test_multigraph_loop(); + test_multigraph_loop(); +} + + +int main() +{ + test(); + test(); + test(); + + return 0; +} From 7f9306dec9cbc98698ed4f48ddc2b00cd7c15032 Mon Sep 17 00:00:00 2001 From: Andrew Sutton Date: Wed, 10 Dec 2008 14:28:25 +0000 Subject: [PATCH 043/224] Added a small test framework for experimenting with invalidating iterators and descriptors. Not part of the test suite. [SVN r50230] --- test/adj_list_invalidation.cpp | 79 ++++++++++++++++++++++++++++++++++ 1 file changed, 79 insertions(+) create mode 100644 test/adj_list_invalidation.cpp diff --git a/test/adj_list_invalidation.cpp b/test/adj_list_invalidation.cpp new file mode 100644 index 00000000..4a868d40 --- /dev/null +++ b/test/adj_list_invalidation.cpp @@ -0,0 +1,79 @@ + +#include +#include + +using namespace std; +using namespace boost; + +// The purpose of this test is simply to provide a testing ground for the +// invalidation of iterators and descriptors. + +template +void make_graph(Graph& g) +{ + // Build a simple (barbell) graph. + typedef typename graph_traits::vertex_descriptor Vertex; + Vertex u = add_vertex(g); + Vertex v = add_vertex(g); + add_edge(u, v, g); +} + +template +void invalidate_edges() +{ + typedef typename graph_traits::edge_descriptor Edge; + typedef typename graph_traits::edge_iterator EdgeIterator; + + Graph g; + make_graph(g); + + // The actual test. These are valid here. + EdgeIterator i = edges(g).first; + Edge e = *i; + + // Add a vertex, see what breaks. + add_vertex(g); + int x; + cout << "...edge iter" << endl; + x = g[*i]; + cout << "...edge desc" << endl; + x = g[e]; +}; + +template +void invalidate_vertices() +{ + typedef typename graph_traits::vertex_descriptor Vertex; + typedef typename graph_traits::vertex_iterator VertexIterator; + + Graph g; + make_graph(g); + + // The actual test. These are valid here. + VertexIterator i = vertices(g).first; + Vertex v = *i; + + // Add a vertex, see what breaks. + add_vertex(g); + int x; + cout << "...vert iter" << endl; + x = g[*i]; + cout << "...vert desc" << endl; + x = g[v]; +} + +int main() +{ + typedef adjacency_list VVU; +// invalidate_vertices(); +// invalidate_edges(); + + typedef adjacency_list VVD; +// invalidate_vertices(); +// invalidate_edges(); + + typedef adjacency_list VVB; +// invalidate_vertices(); +// invalidate_edges(); +} + From a6daa8347266307f47a59827aec975502b7f4bef Mon Sep 17 00:00:00 2001 From: Andrew Sutton Date: Wed, 10 Dec 2008 15:46:05 +0000 Subject: [PATCH 044/224] Added tests for out edge and adjacency components under add_vertex. For some reason, adjacency_iterators seem to remain valid if no operations on other graph types are executed prior to their use, which is completely at odds with what I would expect. [SVN r50231] --- test/adj_list_invalidation.cpp | 103 ++++++++++++++++++++++++++------- 1 file changed, 82 insertions(+), 21 deletions(-) diff --git a/test/adj_list_invalidation.cpp b/test/adj_list_invalidation.cpp index 4a868d40..d14421b4 100644 --- a/test/adj_list_invalidation.cpp +++ b/test/adj_list_invalidation.cpp @@ -1,7 +1,10 @@ #include +#include #include +#include "../../../../../gpld/common/typestr.hpp" + using namespace std; using namespace boost; @@ -13,9 +16,22 @@ void make_graph(Graph& g) { // Build a simple (barbell) graph. typedef typename graph_traits::vertex_descriptor Vertex; - Vertex u = add_vertex(g); - Vertex v = add_vertex(g); - add_edge(u, v, g); + Vertex u = add_vertex(10, g); + Vertex v = add_vertex(20, g); + add_edge(u, v, 100, g); +} + +// Invalid iterators and descriptors will cause a segfault. +template +void test(Graph& g, Iterator i, Descriptor d, string const& str) +{ + int x; + cout << "... " << str << " iter" << endl; + x = g[*i]; +// cout << "... " << x << endl; + cout << "... " << str << " desc" << endl; + x = g[d]; +// cout << "... " << x << endl; } template @@ -33,11 +49,7 @@ void invalidate_edges() // Add a vertex, see what breaks. add_vertex(g); - int x; - cout << "...edge iter" << endl; - x = g[*i]; - cout << "...edge desc" << endl; - x = g[e]; + test(g, i, e, "edges"); }; template @@ -55,25 +67,74 @@ void invalidate_vertices() // Add a vertex, see what breaks. add_vertex(g); - int x; - cout << "...vert iter" << endl; - x = g[*i]; - cout << "...vert desc" << endl; - x = g[v]; + test(g, i, v, "vertices"); } +template +void invalidate_out_edges() +{ + typedef typename graph_traits::edge_descriptor Edge; + typedef typename graph_traits::out_edge_iterator OutIterator; + + Graph g; + make_graph(g); + + // The actual test. These are valid here. + OutIterator i = out_edges(*vertices(g).first, g).first; + Edge e = *i; + + // Add a vertex, see what breaks. + add_vertex(g); + test(g, i, e, "out edges"); +} + +template +void invalidate_adj_verts() +{ + typedef typename graph_traits::vertex_descriptor Vertex; + typedef typename graph_traits::adjacency_iterator AdjIterator; + + Graph g; + make_graph(g); + + // The actual test. These are valid here. + AdjIterator i = adjacent_vertices(*vertices(g).first, g).first; + Vertex v = *i; + + // Add a vertex, see what breaks. + add_vertex(g); + test(g, i, v, "adjacent vertices"); +} + + int main() { typedef adjacency_list VVU; -// invalidate_vertices(); -// invalidate_edges(); - - typedef adjacency_list VVD; -// invalidate_vertices(); -// invalidate_edges(); + cout << "vecS vecS undirectedS" << endl; + invalidate_vertices(); + invalidate_edges(); + invalidate_out_edges(); + invalidate_adj_verts(); typedef adjacency_list VVB; -// invalidate_vertices(); -// invalidate_edges(); + cout << "vecS vecS bidirectionals" << endl; + invalidate_vertices(); + invalidate_edges(); + invalidate_out_edges(); + invalidate_adj_verts(); + + typedef adjacency_list VVD; + cout << "vecS vecS directedS" << endl; + invalidate_vertices(); +// invalidate_edges(); +// invalidate_out_edges(); +// invalidate_adj_verts(); + + typedef adjacency_list VLD; + cout << "vecS listS directedS" << endl; + invalidate_vertices(); + invalidate_edges(); + invalidate_out_edges(); + invalidate_adj_verts(); } From b2724beb09e8fd19e71bf09033c9311954f5932c Mon Sep 17 00:00:00 2001 From: Andrew Sutton Date: Wed, 10 Dec 2008 15:56:02 +0000 Subject: [PATCH 045/224] Added some comments about a peculiar condition in the testing. [SVN r50232] --- test/adj_list_invalidation.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/test/adj_list_invalidation.cpp b/test/adj_list_invalidation.cpp index d14421b4..d1abd628 100644 --- a/test/adj_list_invalidation.cpp +++ b/test/adj_list_invalidation.cpp @@ -123,6 +123,10 @@ int main() invalidate_out_edges(); invalidate_adj_verts(); + // If you comment out the tests before this, then adj_verts test will + // run without segfaulting - at least under gcc-4.3. Not really sure why, + // but I'm guessing it's still not generating valid results, and shouldn't + // be taken as an indicator of stability. typedef adjacency_list VVD; cout << "vecS vecS directedS" << endl; invalidate_vertices(); From 6b4635c403de805d8d7f41c3cf3adc91186c55c3 Mon Sep 17 00:00:00 2001 From: Andrew Sutton Date: Wed, 10 Dec 2008 16:12:39 +0000 Subject: [PATCH 046/224] Fixing the graph type for listS tests. [SVN r50233] --- test/adj_list_invalidation.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/test/adj_list_invalidation.cpp b/test/adj_list_invalidation.cpp index d1abd628..e217c92f 100644 --- a/test/adj_list_invalidation.cpp +++ b/test/adj_list_invalidation.cpp @@ -134,11 +134,11 @@ int main() // invalidate_out_edges(); // invalidate_adj_verts(); - typedef adjacency_list VLD; - cout << "vecS listS directedS" << endl; - invalidate_vertices(); - invalidate_edges(); - invalidate_out_edges(); - invalidate_adj_verts(); + typedef adjacency_list LVD; + cout << "listS vecS directedS" << endl; + invalidate_vertices(); +// invalidate_edges(); +// invalidate_out_edges(); +// invalidate_adj_verts(); } From 70e103d1b9bd382c3706d20bb03e9ef72203c79f Mon Sep 17 00:00:00 2001 From: Andrew Sutton Date: Wed, 10 Dec 2008 16:17:19 +0000 Subject: [PATCH 047/224] Updating the adjacency list invalidation table. [SVN r50234] --- doc/adjacency_list.html | 83 ++++++++++++++++++++++++++--------------- 1 file changed, 52 insertions(+), 31 deletions(-) diff --git a/doc/adjacency_list.html b/doc/adjacency_list.html index 16de125c..0c567231 100644 --- a/doc/adjacency_list.html +++ b/doc/adjacency_list.html @@ -8,10 +8,10 @@ --> Boost Graph Library: Adjacency List - -C++ Boost + +C++ Boost
    @@ -146,7 +146,7 @@ shows how to represent a family tree with a graph.

    Model of

    -VertexAndEdgeListGraph, +VertexAndEdgeListGraph, MutablePropertyGraph, CopyConstructible, Assignable, @@ -178,7 +178,7 @@ interface defined in Section Property Map Concepts or may be bundled properties, which have a more succinct syntax. The types of all property values -must be Copy Constructible, Assignable, and Default Constructible. +must be Copy Constructible, Assignable, and Default Constructible. The property maps obtained from the adjacency_list class are models of the Lvalue Property @@ -322,30 +322,51 @@ each operation. Table: Summary of Descriptor and Iterator Invalidation. - Function Vertex Desc Edge Desc -Vertex Iter Edge Iter Adj Iter - -add_edge() OKOKOKEL=vecS &&
    Directed=directedS
    EL=vecS + Function + Vertex Desc + Edge Desc + Vertex Iter + Edge Iter + Adj Iter -remove_edge()
    remove_edge_if()
    remove_out_edge_if()
    remove_in_edge_if()
    clear_vertex()
    OKOKOK -EL=vecS &&
    Directed=directedS
    EL=vecS + + add_edge() + OK + OK + OK + EL=vecS &&
    Directed=directedS
    + EL=vecS -add_vertex()OKOKOKOKOK + remove_edge()
    remove_edge_if()
    remove_out_edge_if()
    + remove_in_edge_if()
    clear_vertex()
    + + OK + OK + OK + EL=vecS &&
    Directed=directedS
    + EL=vecS -remove_vertex()VL=vecSVL=vecSVL=vecSVL=vecSVL=vecS + add_vertex() + OK + OK + OK + VL=vecS &&
    Directed=directedS
    + VL=vecS &&
    Directed=directedS
    + + + remove_vertex() + VL=vecS + VL=vecS + VL=vecS + VL=vecS + VL=vecS - -

    Associated Types


    @@ -539,7 +560,7 @@ Assignment operator. Makes this graph a copy of graph
    -adjacency_list(vertices_size_type n, 
    +adjacency_list(vertices_size_type n,
                    const GraphProperty& p = GraphProperty())
     
    Creates a graph object with n vertices and zero edges. @@ -550,8 +571,8 @@ Creates a graph object with n vertices and zero edges.
     template <class EdgeIterator>
     adjacency_list(EdgeIterator first, EdgeIterator last,
    -               vertices_size_type n, 
    -               edges_size_type m = 0, 
    +               vertices_size_type n,
    +               edges_size_type m = 0,
                    const GraphProperty& p = GraphProperty())
     
    Creates a graph object with n vertices and with the edges @@ -600,7 +621,7 @@ void swap(adjacency_list& x) Swap the vertices, edges, and properties of this graph with the vertices, edges, and properties of graph x.
    - +

    Non-Member Functions

    @@ -781,7 +802,7 @@ returned edge descriptor points to the already existing edge.

    The placement of the new edge in the out-edge list is in general unspecified, though ordering of the out-edge list can be accomplished -through the choice of OutEdgeList. +through the choice of OutEdgeList. If the VertexList selector is vecS, and if either vertex descriptor u or @@ -821,7 +842,7 @@ value of the edge's internal property storage. Also see the previous void remove_edge(vertex_descriptor u, vertex_descriptor v, adjacency_list& g) -Removes the edge (u,v) from the graph. +Removes the edge (u,v) from the graph.

    This operation causes any outstanding edge descriptors or iterators that point to edge (u,v) to become invalid. In addition, if @@ -867,7 +888,7 @@ void remove_out_edge_if(vertex_descriptor u, Predicate predicate, Removes all out-edges of vertex u from the graph that satisfy the predicate. That is, if the predicate returns true when -applied to an edge descriptor, then the edge is removed. +applied to an edge descriptor, then the edge is removed.

    The affect on descriptor and iterator stability is the same as that of invoking remove_edge() on each of the removed edges. @@ -899,7 +920,7 @@ void remove_edge_if(Predicate predicate, adjacency_list& g) Removes all edges from the graph that satisfy the predicate. That is, if the predicate returns true when -applied to an edge descriptor, then the edge is removed. +applied to an edge descriptor, then the edge is removed.

    The affect on descriptor and iterator stability is the same as that of invoking remove_edge() on each of the removed edges. @@ -912,7 +933,7 @@ vertex_descriptor add_vertex(adjacency_list& g) Adds a vertex to the graph and returns the vertex descriptor for the -new vertex. +new vertex.


    @@ -975,7 +996,7 @@ void remove_vertex(vertex_descriptor u, adjacency_list& g) Remove vertex u from the vertex set of the graph. It is assumed that there are no edges to or from vertex u when it is removed. One way to make sure of this is to invoke clear_vertex() -beforehand. +beforehand.

    If the VertexList template parameter of the adjacency_list was vecS, then all vertex @@ -1110,7 +1131,7 @@ HREF="mailto:lums@osl.iu.edu">lums@osl.iu.edu) - + Boost Graph Library: A* Heuristic Search @@ -50,6 +50,25 @@ astar_search VertexIndexMap index_map, ColorMap color, CompareFunction compare, CombineFunction combine, CostInf inf, CostZero zero); + +// Version that does not initialize property maps (used for implicit graphs) +template <typename VertexListGraph, typename AStarHeuristic, + typename AStarVisitor, typename PredecessorMap, + typename CostMap, typename DistanceMap, + typename WeightMap, typename ColorMap, + typename VertexIndexMap, + typename CompareFunction, typename CombineFunction, + typename CostInf, typename CostZero> +inline void +astar_search_no_init + (VertexListGraph &g, + typename graph_traits<VertexListGraph>::vertex_descriptor s, + AStarHeuristic h, AStarVisitor vis, + PredecessorMap predecessor, CostMap cost, + DistanceMap distance, WeightMap weight, + ColorMap color, VertexIndexMap index_map, + CompareFunction compare, CombineFunction combine, + CostInf inf, CostZero zero)

    @@ -92,7 +111,10 @@ useful for searching large state spaces -- in gameplaying scenarios (e.g. chess), for example -- in which it may not be possible to store the entire graph. Implicit searches can be performed with this implementation of A* by creating special visitors that generate -neighbors of newly-expanded vertices. +neighbors of newly-expanded vertices. Please note that +astar_search_no_init() must be used for implicit graphs; the basic +astar_search() function requires a graph that models +VertexListGraph.

    From 1eba2f9cc5d78ec5fd99a364787e440add27ccec Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Tue, 27 Jan 2009 17:58:45 +0000 Subject: [PATCH 061/224] Fixed typo (missing semicolon) [SVN r50805] --- doc/astar_search.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/astar_search.html b/doc/astar_search.html index b2ee3644..2ea0a6af 100644 --- a/doc/astar_search.html +++ b/doc/astar_search.html @@ -68,7 +68,7 @@ astar_search_no_init DistanceMap distance, WeightMap weight, ColorMap color, VertexIndexMap index_map, CompareFunction compare, CombineFunction combine, - CostInf inf, CostZero zero) + CostInf inf, CostZero zero);

    From 69d72805be149c2fabc93ac11b4ed26fa50cc327 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Tue, 27 Jan 2009 18:03:03 +0000 Subject: [PATCH 062/224] Fixing two parts of #2658; not sure about point 3 of that report [SVN r50806] --- 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 736cc6cc..dcfdbc00 100644 --- a/include/boost/graph/read_dimacs.hpp +++ b/include/boost/graph/read_dimacs.hpp @@ -250,7 +250,7 @@ int read_dimacs_max_flow(Graph& g, /* ----- all is red or error while reading ----- */ - if ( feof (stdin) == 0 ) /* reading error */ + if ( in.eof() == 0 ) /* reading error */ { err_no=EN21; goto error; } if ( no_lines == 0 ) /* empty input */ From 968edbe972f500faa3f6b0e87b9dda9663e26e15 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Tue, 27 Jan 2009 18:48:09 +0000 Subject: [PATCH 063/224] Changed closed_plus to match inf_plus from floyd_warshall_test, changed test to use closed_plus, fixed comments in documentation and replaced std::plus with closed_plus to match implementation, fixes #1164 [SVN r50808] --- doc/floyd_warshall_shortest.html | 12 ++++++------ include/boost/graph/relax.hpp | 9 ++++----- test/floyd_warshall_test.cpp | 29 ++++------------------------- 3 files changed, 14 insertions(+), 36 deletions(-) diff --git a/doc/floyd_warshall_shortest.html b/doc/floyd_warshall_shortest.html index 8952cf26..f4a22a28 100644 --- a/doc/floyd_warshall_shortest.html +++ b/doc/floyd_warshall_shortest.html @@ -1,10 +1,10 @@ Floyd-Warshall All Pairs Shortest Paths @@ -127,7 +127,7 @@ path. The CombineFunction must be a model of BinaryFunction. The argument types must match the value type of the WeightMap. The result type must be the same as the distance value type.
    -Default: std::plus<WM> with WM = typename property_traits<WeightMap>::value_type +Default: boost::closed_plus<WM> with WM = typename property_traits<WeightMap>::value_type

  • IN: distance_inf(WM inf) diff --git a/include/boost/graph/relax.hpp b/include/boost/graph/relax.hpp index 18313cc9..8a23908a 100644 --- a/include/boost/graph/relax.hpp +++ b/include/boost/graph/relax.hpp @@ -24,11 +24,10 @@ namespace boost { { T operator()(const T& a, const T& b) const { using namespace std; - T zero(0); - T result = a + b; - if (result < zero && a >= zero && b >= zero) - return (std::numeric_limits::max)(); - return result; + const T inf = (std::numeric_limits::max)(); + if (a == inf) return inf; + if (b == inf) return inf; + return a + b; } }; diff --git a/test/floyd_warshall_test.cpp b/test/floyd_warshall_test.cpp index 14f96a75..fcb60672 100644 --- a/test/floyd_warshall_test.cpp +++ b/test/floyd_warshall_test.cpp @@ -21,17 +21,6 @@ #include using namespace boost; -template -struct inf_plus{ - T operator()(const T& a, const T& b) const { - T inf = std::numeric_limits::max BOOST_PREVENT_MACRO_SUBSTITUTION(); - if (a == inf || b == inf){ - return inf; - } - return a + b; - } -}; - template inline const T& my_min(const T& x, const T& y) { return x < y? x : y; } @@ -125,20 +114,16 @@ bool acceptance_test(Graph& g, int vec, int e) bool bellman, floyd1, floyd2, floyd3; - std::less compare; - inf_plus combine; floyd1 = boost::floyd_warshall_initialized_all_pairs_shortest_paths (g, matrix, weight_map(boost::get(boost::edge_weight, g)). - distance_compare(compare). distance_combine(combine). distance_inf(int_inf). distance_zero(0)); floyd2 = boost::floyd_warshall_all_pairs_shortest_paths (g, matrix3, - weight_map(local_edge_map). distance_compare(compare). - distance_combine(combine). + weight_map(local_edge_map). distance_inf(int_inf). distance_zero(0)); floyd3 = boost::floyd_warshall_all_pairs_shortest_paths(g, matrix4); @@ -153,8 +138,7 @@ bool acceptance_test(Graph& g, int vec, int e) (g, vec, weight_map(boost::get(boost::edge_weight, g)). distance_map(boost::get(boost::vertex_distance, g)). - predecessor_map(dummy_map).distance_compare(compare). - distance_combine(combine)); + predecessor_map(dummy_map)); distance_row = boost::get(boost::vertex_distance, g); for(boost::tie(firstv2, lastv2) = vertices(g); firstv2 != lastv2; firstv2++){ @@ -302,20 +286,16 @@ bool acceptance_test2(Graph& g, int vec, int e) bool bellman, floyd1, floyd2, floyd3; - std::less compare; - inf_plus combine; floyd1 = boost::floyd_warshall_initialized_all_pairs_shortest_paths (g, matrix, weight_map(boost::get(boost::edge_weight, g)). - distance_compare(compare). distance_combine(combine). distance_inf(int_inf). distance_zero(0)); floyd2 = boost::floyd_warshall_all_pairs_shortest_paths (g, matrix3, - weight_map(local_edge_map). distance_compare(compare). - distance_combine(combine). + weight_map(local_edge_map). distance_inf(int_inf). distance_zero(0)); floyd3 = boost::floyd_warshall_all_pairs_shortest_paths(g, matrix4); @@ -330,8 +310,7 @@ bool acceptance_test2(Graph& g, int vec, int e) (g, vec, weight_map(boost::get(boost::edge_weight, g)). distance_map(boost::get(boost::vertex_distance, g)). - predecessor_map(dummy_map).distance_compare(compare). - distance_combine(combine)); + predecessor_map(dummy_map)); distance_row = boost::get(boost::vertex_distance, g); for(boost::tie(firstv2, lastv2) = vertices(g); firstv2 != lastv2; firstv2++){ From 4844c47f6a096c3cf4f50b03fbf2b7e63485eb34 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Tue, 27 Jan 2009 19:58:18 +0000 Subject: [PATCH 064/224] Documented dijkstra_shortest_paths_no_init, fixed other small issues [SVN r50811] --- doc/dijkstra_shortest_paths.html | 28 +++++++++++++++++++++------- 1 file changed, 21 insertions(+), 7 deletions(-) diff --git a/doc/dijkstra_shortest_paths.html b/doc/dijkstra_shortest_paths.html index 7a439ae1..a0d596da 100644 --- a/doc/dijkstra_shortest_paths.html +++ b/doc/dijkstra_shortest_paths.html @@ -1,10 +1,10 @@ Boost Graph Library: Dijkstra's Shortest Paths @@ -41,6 +41,20 @@ void dijkstra_shortest_paths VertexIndexMap index_map, CompareFunction compare, CombineFunction combine, DistInf inf, DistZero zero, DijkstraVisitor vis, ColorMap color = default) + +// version that does not initialize the property maps (except for the default color map) +template <class VertexListGraph, class DijkstraVisitor, + class PredecessorMap, class DistanceMap, + class WeightMap, class IndexMap, class Compare, class Combine, + class DistZero, class ColorMap> +void +dijkstra_shortest_paths_no_init + (const VertexListGraph& g, + typename graph_traits<VertexListGraph>::vertex_descriptor s, + PredecessorMap predecessor, DistanceMap distance, WeightMap weight, + IndexMap index_map, + Compare compare, Combine combine, DistZero zero, + DijkstraVisitor vis, ColorMap color = default);

    @@ -92,7 +106,7 @@ track of which set each vertex is in. Vertices colored black are in S. Vertices colored white or gray are in V-S. White vertices have not yet been discovered and gray vertices are in the priority queue. By default, the algorithm will allocate an array to store a color -marker for each vertex in the graph. You can provide you own storage +marker for each vertex in the graph. You can provide your own storage and access for colors with the color_map() parameter.

    @@ -109,7 +123,7 @@ indicated by the labels on the right.

     DIJKSTRA(G, s, w)
    -  for each vertex u in V
    +  for each vertex u in V (This loop is not run in dijkstra_shortest_paths_no_init)
         d[u] := infinity 
         p[u] := u 
         color[u] := WHITE
    
    From 4b61796e41f262f06df39aa253c56701c994be27 Mon Sep 17 00:00:00 2001
    From: Jeremiah Willcock 
    Date: Tue, 27 Jan 2009 19:59:40 +0000
    Subject: [PATCH 065/224] Changed Dijkstra shortest path algorithm to use d-ary
     heap by default, and to use a vector_property_map when the graph does not
     model VertexListGraph (only supported for dijkstra_shortest_paths_no_init);
     fixes #708
    
    [SVN r50812]
    ---
     .../boost/graph/dijkstra_shortest_paths.hpp   | 76 +++++++++++++++----
     test/dijkstra_heap_performance.cpp            |  9 +--
     2 files changed, 66 insertions(+), 19 deletions(-)
    
    diff --git a/include/boost/graph/dijkstra_shortest_paths.hpp b/include/boost/graph/dijkstra_shortest_paths.hpp
    index 4e828bb8..0bad30c0 100644
    --- a/include/boost/graph/dijkstra_shortest_paths.hpp
    +++ b/include/boost/graph/dijkstra_shortest_paths.hpp
    @@ -19,6 +19,9 @@
     #include 
     #include 
     #include 
    +#include 
    +#include 
    +#include 
     
     #ifdef BOOST_GRAPH_DIJKSTRA_TESTING
     #  include 
    @@ -27,6 +30,8 @@
     namespace boost {
     
     #ifdef BOOST_GRAPH_DIJKSTRA_TESTING
    +  // This is a misnomer now: it now just refers to the "default heap", which is
    +  // currently d-ary (d=4) but can be changed by a #define.
       static bool dijkstra_relaxed_heap = true;
     #endif
     
    @@ -141,6 +146,42 @@ namespace boost {
     
       } // namespace detail
     
    +  namespace detail {
    +    template 
    +    struct vertex_property_map_generator_helper {};
    +
    +    template 
    +    struct vertex_property_map_generator_helper {
    +      typedef boost::iterator_property_map type;
    +      static type build(const Graph& g, const IndexMap& index, boost::scoped_array& array_holder) {
    +        array_holder.reset(new Value[num_vertices(g)]);
    +        std::fill(array_holder.get(), array_holder.get() + num_vertices(g), Value());
    +        return make_iterator_property_map(array_holder.get(), index);
    +      }
    +    };
    +
    +    template 
    +    struct vertex_property_map_generator_helper {
    +      typedef boost::vector_property_map type;
    +      static type build(const Graph& g, const IndexMap& index, boost::scoped_array& array_holder) {
    +        return make_vector_property_map(index);
    +      }
    +    };
    +
    +    template 
    +    struct vertex_property_map_generator {
    +      typedef boost::is_base_and_derived<
    +                boost::vertex_list_graph_tag,
    +                typename boost::graph_traits::traversal_category>
    +              known_num_vertices;
    +      typedef vertex_property_map_generator_helper helper;
    +      typedef typename helper::type type;
    +      static type build(const Graph& g, const IndexMap& index, boost::scoped_array& array_holder) {
    +        return helper::build(g, index, array_holder);
    +      }
    +    };
    +  }
    +
       // Call breadth first search with default color map.
       template  color(num_vertices(g));
    -    default_color_type c = white_color;
    +    boost::scoped_array color_map_holder;
    +    typedef
    +      detail::vertex_property_map_generator
    +      ColorMapHelper;
    +    typedef typename ColorMapHelper::type ColorMap;
    +    ColorMap color =
    +      ColorMapHelper::build(g, index_map, white_color, color_map_holder);
         dijkstra_shortest_paths_no_init( g, s, predecessor, distance, weight,
           index_map, compare, combine, zero, vis,
    -        make_iterator_property_map(&color[0], index_map, c));
    +        color);
       }
     
       // Call breadth first search
    @@ -183,20 +229,10 @@ namespace boost {
     
     #ifdef BOOST_GRAPH_DIJKSTRA_TESTING
         if (!dijkstra_relaxed_heap) {
    -#ifdef BOOST_GRAPH_TEST_D_ARY_HEAP
    -      boost::scoped_array index_in_heap_map(new std::size_t[num_vertices(g)]);
    -      typedef boost::iterator_property_map IndexInHeapMap;
    -      IndexInHeapMap index_in_heap(&index_in_heap_map[0], index_map);
    -      typedef d_ary_heap_indirect
    -        MutableQueue;
    -      MutableQueue Q(distance, index_in_heap, compare);
    -#else
           typedef mutable_queue, IndirectCmp, IndexMap>
             MutableQueue;
     
           MutableQueue Q(num_vertices(g), icmp, index_map);
    -#endif
    -
           detail::dijkstra_bfs_visitor
           bfs_vis(vis, Q, weight, predecessor, distance, combine, compare, zero);
    @@ -206,9 +242,21 @@ namespace boost {
         }
     #endif // BOOST_GRAPH_DIJKSTRA_TESTING
     
    +#ifdef BOOST_GRAPH_DIJKSTRA_USE_RELAXED_HEAP
         typedef relaxed_heap MutableQueue;
    -
         MutableQueue Q(num_vertices(g), icmp, index_map);
    +#else // Now the default: use a d-ary heap
    +      boost::scoped_array index_in_heap_map_holder;
    +      typedef
    +        detail::vertex_property_map_generator
    +        IndexInHeapMapHelper;
    +      typedef typename IndexInHeapMapHelper::type IndexInHeapMap;
    +      IndexInHeapMap index_in_heap =
    +        IndexInHeapMapHelper::build(g, index_map, index_in_heap_map_holder);
    +      typedef d_ary_heap_indirect
    +        MutableQueue;
    +      MutableQueue Q(distance, index_in_heap, compare);
    +#endif
     
         detail::dijkstra_bfs_visitor
    diff --git a/test/dijkstra_heap_performance.cpp b/test/dijkstra_heap_performance.cpp
    index 6d4a8f5d..37d1160a 100644
    --- a/test/dijkstra_heap_performance.cpp
    +++ b/test/dijkstra_heap_performance.cpp
    @@ -8,7 +8,6 @@
     //           Andrew Lumsdaine
     #ifndef BOOST_GRAPH_DIJKSTRA_TESTING_DIETMAR
     #  define BOOST_GRAPH_DIJKSTRA_TESTING
    -#  define BOOST_GRAPH_TEST_D_ARY_HEAP
     #endif
     
     #include 
    @@ -107,11 +106,7 @@ int main(int argc, char* argv[])
       std::vector relaxed_heap_distances(n);
     
       // Run binary or d-ary heap version
    -#ifdef BOOST_GRAPH_TEST_D_ARY_HEAP
    -  std::cout << "Running Dijkstra's with d-ary heap...";
    -#else
       std::cout << "Running Dijkstra's with binary heap...";
    -#endif
       std::cout.flush();
       timer t;
     #ifdef BOOST_GRAPH_DIJKSTRA_TESTING_DIETMAR
    @@ -125,7 +120,11 @@ int main(int argc, char* argv[])
       std::cout << binary_heap_time << " seconds.\n";
     
       // Run relaxed heap version
    +#ifdef BOOST_GRAPH_DIJKSTRA_USE_RELAXED_HEAP
       std::cout << "Running Dijkstra's with relaxed heap...";
    +#else
    +  std::cout << "Running Dijkstra's with d-ary heap (d=4)...";
    +#endif
       std::cout.flush();
       t.restart();
     #ifdef BOOST_GRAPH_DIJKSTRA_TESTING_DIETMAR
    
    From b0e70a45d0a6e98dd3c2ddeefe5b0e0a3239d44e Mon Sep 17 00:00:00 2001
    From: Jeremiah Willcock 
    Date: Tue, 27 Jan 2009 20:07:25 +0000
    Subject: [PATCH 066/224] Changed template parameter names to match removal of
     Vertex List Graph requirement
    
    [SVN r50813]
    ---
     doc/dijkstra_shortest_paths.html               |  6 +++---
     .../boost/graph/dijkstra_shortest_paths.hpp    | 18 +++++++++---------
     2 files changed, 12 insertions(+), 12 deletions(-)
    
    diff --git a/doc/dijkstra_shortest_paths.html b/doc/dijkstra_shortest_paths.html
    index a0d596da..e80dc8f4 100644
    --- a/doc/dijkstra_shortest_paths.html
    +++ b/doc/dijkstra_shortest_paths.html
    @@ -43,14 +43,14 @@ void dijkstra_shortest_paths
        DijkstraVisitor vis, ColorMap color = default)
     
     // version that does not initialize the property maps (except for the default color map)
    -template <class VertexListGraph, class DijkstraVisitor,
    +template <class Graph, class DijkstraVisitor,
               class PredecessorMap, class DistanceMap,
               class WeightMap, class IndexMap, class Compare, class Combine,
               class DistZero, class ColorMap>
     void
     dijkstra_shortest_paths_no_init
    -  (const VertexListGraph& g,
    -   typename graph_traits<VertexListGraph>::vertex_descriptor s,
    +  (const Graph& g,
    +   typename graph_traits<Graph>::vertex_descriptor s,
        PredecessorMap predecessor, DistanceMap distance, WeightMap weight,
        IndexMap index_map,
        Compare compare, Combine combine, DistZero zero,
    diff --git a/include/boost/graph/dijkstra_shortest_paths.hpp b/include/boost/graph/dijkstra_shortest_paths.hpp
    index 0bad30c0..97c11a8a 100644
    --- a/include/boost/graph/dijkstra_shortest_paths.hpp
    +++ b/include/boost/graph/dijkstra_shortest_paths.hpp
    @@ -183,14 +183,14 @@ namespace boost {
       }
     
       // Call breadth first search with default color map.
    -  template 
       inline void
       dijkstra_shortest_paths_no_init
    -    (const VertexListGraph& g,
    -     typename graph_traits::vertex_descriptor s,
    +    (const Graph& g,
    +     typename graph_traits::vertex_descriptor s,
          PredecessorMap predecessor, DistanceMap distance, WeightMap weight,
          IndexMap index_map,
          Compare compare, Combine combine, DistZero zero,
    @@ -198,7 +198,7 @@ namespace boost {
       {
         boost::scoped_array color_map_holder;
         typedef
    -      detail::vertex_property_map_generator
    +      detail::vertex_property_map_generator
           ColorMapHelper;
         typedef typename ColorMapHelper::type ColorMap;
         ColorMap color =
    @@ -209,14 +209,14 @@ namespace boost {
       }
     
       // Call breadth first search
    -  template 
       inline void
       dijkstra_shortest_paths_no_init
    -    (const VertexListGraph& g,
    -     typename graph_traits::vertex_descriptor s,
    +    (const Graph& g,
    +     typename graph_traits::vertex_descriptor s,
          PredecessorMap predecessor, DistanceMap distance, WeightMap weight,
          IndexMap index_map,
          Compare compare, Combine combine, DistZero zero,
    @@ -225,7 +225,7 @@ namespace boost {
         typedef indirect_cmp IndirectCmp;
         IndirectCmp icmp(distance, compare);
     
    -    typedef typename graph_traits::vertex_descriptor Vertex;
    +    typedef typename graph_traits::vertex_descriptor Vertex;
     
     #ifdef BOOST_GRAPH_DIJKSTRA_TESTING
         if (!dijkstra_relaxed_heap) {
    @@ -248,7 +248,7 @@ namespace boost {
     #else // Now the default: use a d-ary heap
           boost::scoped_array index_in_heap_map_holder;
           typedef
    -        detail::vertex_property_map_generator
    +        detail::vertex_property_map_generator
             IndexInHeapMapHelper;
           typedef typename IndexInHeapMapHelper::type IndexInHeapMap;
           IndexInHeapMap index_in_heap =
    
    From 51d8d9f6beef9778e62f6cfc7c5dd8efc74c729c Mon Sep 17 00:00:00 2001
    From: Jeremiah Willcock 
    Date: Tue, 27 Jan 2009 20:18:33 +0000
    Subject: [PATCH 067/224] Fixed comment syntax
    
    [SVN r50814]
    ---
     doc/johnson_all_pairs_shortest.html | 10 +++++-----
     1 file changed, 5 insertions(+), 5 deletions(-)
    
    diff --git a/doc/johnson_all_pairs_shortest.html b/doc/johnson_all_pairs_shortest.html
    index 4afc6dda..190b4c6f 100644
    --- a/doc/johnson_all_pairs_shortest.html
    +++ b/doc/johnson_all_pairs_shortest.html
    @@ -1,10 +1,10 @@
     
     
     
     Johnson All Pairs Shortest Paths
    
    From 9572d48a0306cbf3a3aba059b9ffa479770a8560 Mon Sep 17 00:00:00 2001
    From: Jeremiah Willcock 
    Date: Tue, 27 Jan 2009 20:19:29 +0000
    Subject: [PATCH 068/224] Changed Johnson ASSP algorithm to use combine rather
     than + to do reweighting (did not change -, though); fixes #732
    
    [SVN r50815]
    ---
     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 45a8cf2c..4d557724 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 (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, get(w, *e) + get(h, a) - get(h, b));
    +        put(w_hat, *e, combine(get(w, *e), (get(h, a) - get(h, b))));
           }
           for (tie(u, u_end) = vertices(g2); u != u_end; ++u) {
             dijkstra_visitor<> dvis;
    @@ -123,7 +123,7 @@ namespace boost {
               if (*u != s && *v != s) {
                 typename Traits1::vertex_descriptor u1, v1;
                 u1 = verts1[id2[*u]]; v1 = verts1[id2[*v]];
    -            D[id2[*u]-1][id2[*v]-1] = get(d, *v) + get(h, *v) - get(h, *u);
    +            D[id2[*u]-1][id2[*v]-1] = combine(get(d, *v), (get(h, *v) - get(h, *u)));
               }
             }
           }
    
    From 50fba1d79f71ef7e5dfaa922bc61b48044a80656 Mon Sep 17 00:00:00 2001
    From: Jeremiah Willcock 
    Date: Tue, 27 Jan 2009 20:19:55 +0000
    Subject: [PATCH 069/224] Tightened handling of inf in example to try to catch
     problems like #732 in the future
    
    [SVN r50816]
    ---
     example/johnson-eg.cpp | 2 +-
     1 file changed, 1 insertion(+), 1 deletion(-)
    
    diff --git a/example/johnson-eg.cpp b/example/johnson-eg.cpp
    index 10c0e46e..8f082d58 100644
    --- a/example/johnson-eg.cpp
    +++ b/example/johnson-eg.cpp
    @@ -56,7 +56,7 @@ main()
       for (int i = 0; i < V; ++i) {
         std::cout << i << " -> ";
         for (int j = 0; j < V; ++j) {
    -      if (D[i][j] > 20 || D[i][j] < -20)
    +      if (D[i][j] == (std::numeric_limits::max)())
             std::cout << std::setw(5) << "inf";
           else
             std::cout << std::setw(5) << D[i][j];
    
    From 83e3ee4b6cb35823c67886f36bae1e2c31fc7e53 Mon Sep 17 00:00:00 2001
    From: Jeremiah Willcock 
    Date: Tue, 27 Jan 2009 21:12:42 +0000
    Subject: [PATCH 070/224] Reverted r14604 to test handling of unconnected
     vertices, and fixed up formatting of output grid
    
    [SVN r50821]
    ---
     example/johnson-eg.cpp | 15 ++++++++-------
     1 file changed, 8 insertions(+), 7 deletions(-)
    
    diff --git a/example/johnson-eg.cpp b/example/johnson-eg.cpp
    index 8f082d58..8ad5471b 100644
    --- a/example/johnson-eg.cpp
    +++ b/example/johnson-eg.cpp
    @@ -8,8 +8,8 @@
     #include 
     #include 
     #include 
    -#include 
     #include 
    +#include 
     #include 
     #include 
     #include 
    @@ -21,11 +21,12 @@ main()
       using namespace boost;
       typedef adjacency_list > > Graph;
    -  const int V = 5;
    +  const int V = 6;
       typedef std::pair < int, int >Edge;
       Edge edge_array[] =
    -    { Edge(0, 1), Edge(0, 4), Edge(0, 2), Edge(1, 3), Edge(1, 4),
    -    Edge(2, 1), Edge(3, 2), Edge(3, 0), Edge(4, 3)
    +    { Edge(0, 1), Edge(0, 2), Edge(0, 3), Edge(0, 4), Edge(0, 5),
    +    Edge(1, 2), Edge(1, 5), Edge(1, 3), Edge(2, 4), Edge(2, 5),
    +    Edge(3, 2), Edge(4, 3), Edge(4, 1), Edge(5, 4)
       };
       const std::size_t E = sizeof(edge_array) / sizeof(Edge);
     #if defined(BOOST_MSVC) && BOOST_MSVC <= 1300
    @@ -38,7 +39,7 @@ main()
     #endif
     
       property_map < Graph, edge_weight_t >::type w = get(edge_weight, g);
    -  int weights[] = { 3, -4, 8, 1, 7, 4, -5, 2, 6 };
    +  int weights[] = { 0, 0, 0, 0, 0, 3, -4, 8, 1, 7, 4, -5, 2, 6 };
       int *wp = weights;
     
       graph_traits < Graph >::edge_iterator e, e_end;
    @@ -49,12 +50,12 @@ main()
       int D[V][V];
       johnson_all_pairs_shortest_paths(g, D, distance_map(&d[0]));
     
    -  std::cout << "     ";
    +  std::cout << "       ";
       for (int k = 0; k < V; ++k)
         std::cout << std::setw(5) << k;
       std::cout << std::endl;
       for (int i = 0; i < V; ++i) {
    -    std::cout << i << " -> ";
    +    std::cout << std::setw(3) << i << " -> ";
         for (int j = 0; j < V; ++j) {
           if (D[i][j] == (std::numeric_limits::max)())
             std::cout << std::setw(5) << "inf";
    
    From 2ed4a273953f8d2d23b7123ba5e4204a4cac9f51 Mon Sep 17 00:00:00 2001
    From: Jeremiah Willcock 
    Date: Tue, 27 Jan 2009 21:18:02 +0000
    Subject: [PATCH 071/224] Applied patch from #2132, closes #2132
    
    [SVN r50823]
    ---
     include/boost/graph/detail/sparse_ordering.hpp | 4 ++--
     1 file changed, 2 insertions(+), 2 deletions(-)
    
    diff --git a/include/boost/graph/detail/sparse_ordering.hpp b/include/boost/graph/detail/sparse_ordering.hpp
    index cf4bbb0b..d70e906d 100644
    --- a/include/boost/graph/detail/sparse_ordering.hpp
    +++ b/include/boost/graph/detail/sparse_ordering.hpp
    @@ -128,7 +128,7 @@ namespace boost {
       //
       template 
       Vertex 
    -  pseudo_peripheral_pair(Graph& G, const Vertex& u, int& ecc,
    +  pseudo_peripheral_pair(Graph const& G, const Vertex& u, int& ecc,
                              ColorMap color, DegreeMap degree)
       {
         typedef typename property_traits::value_type ColorValue;
    @@ -152,7 +152,7 @@ namespace boost {
       // of the ordering generated by RCM.
       //
       template  
    -  Vertex find_starting_node(Graph& G, Vertex r, Color color, Degree degree)
    +  Vertex find_starting_node(Graph const& G, Vertex r, Color color, Degree degree)
       {
         Vertex x, y;
         int eccen_r, eccen_x;
    
    From e27b8977b4b6a574f2d2ed53454f5552b120fa35 Mon Sep 17 00:00:00 2001
    From: Andrew Sutton 
    Date: Fri, 30 Jan 2009 14:14:10 +0000
    Subject: [PATCH 072/224] Fixed doc typo.
    
    [SVN r50901]
    ---
     doc/adjacency_list.html | 2 +-
     1 file changed, 1 insertion(+), 1 deletion(-)
    
    diff --git a/doc/adjacency_list.html b/doc/adjacency_list.html
    index 0c567231..cb23a0ea 100644
    --- a/doc/adjacency_list.html
    +++ b/doc/adjacency_list.html
    @@ -592,7 +592,7 @@ template <class EdgeIterator, class EdgePropertyIterator>
     adjacency_list(EdgeIterator first, EdgeIterator last,
                    EdgePropertyIterator ep_iter,
                    vertices_size_type n,
    -               vertices_size_type m = 0,
    +               edges_size_type m = 0,
                    const GraphProperty& p = GraphProperty())
     
    Creates a graph object with n vertices and with the edges From 23e75246cbb2878e4f5c3d8c806b02e33d2afab5 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Wed, 4 Feb 2009 19:28:31 +0000 Subject: [PATCH 073/224] Fixed qcc errors [SVN r51014] --- include/boost/graph/read_dimacs.hpp | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/include/boost/graph/read_dimacs.hpp b/include/boost/graph/read_dimacs.hpp index dcfdbc00..656e226d 100644 --- a/include/boost/graph/read_dimacs.hpp +++ b/include/boost/graph/read_dimacs.hpp @@ -18,6 +18,7 @@ #include #include #include +#include #include @@ -134,13 +135,13 @@ int read_dimacs_max_flow(Graph& g, if ( /* reading problem line: type of problem, no of nodes, no of arcs */ - sscanf ( in_line.c_str(), "%*c %3s %ld %ld", pr_type, &n, &m ) + std::sscanf ( in_line.c_str(), "%*c %3s %ld %ld", pr_type, &n, &m ) != P_FIELDS ) /*wrong number of parameters in the problem line*/ { err_no = EN2; goto error; } - if ( strcmp ( pr_type, PROBLEM_TYPE ) ) + if ( std::strcmp ( pr_type, PROBLEM_TYPE ) ) /*wrong problem type*/ { err_no = EN3; goto error; } @@ -160,7 +161,7 @@ int read_dimacs_max_flow(Graph& g, { err_no = EN8; goto error; } /* reading source or sink */ - k = sscanf ( in_line.c_str(),"%*c %ld %c", &i, &nd ); + k = std::sscanf ( in_line.c_str(),"%*c %ld %c", &i, &nd ); --i; // index from 0 if ( k < NODE_FIELDS ) /* node line is incorrect */ @@ -208,8 +209,8 @@ int read_dimacs_max_flow(Graph& g, if ( /* reading an arc description */ - sscanf ( in_line.c_str(),"%*c %ld %ld %ld", - &tail, &head, &cap ) + std::sscanf ( in_line.c_str(),"%*c %ld %ld %ld", + &tail, &head, &cap ) != ARC_FIELDS ) /* arc description is not correct */ @@ -269,10 +270,10 @@ int read_dimacs_max_flow(Graph& g, /* ---------------------------------- */ error: /* error found reading input */ - printf ( "\nline %ld of input - %s\n", - no_lines, err_message[err_no] ); + std::printf ( "\nline %ld of input - %s\n", + no_lines, err_message[err_no] ); - exit (1); + std::exit (1); return (0); /* to avoid warning */ } /* -------------------- end of parser -------------------*/ From 17f6ae8dbbcb8f3ee629ea4badb79ee27f1492e4 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Wed, 4 Feb 2009 19:32:05 +0000 Subject: [PATCH 074/224] Trying to fix another qcc problem [SVN r51015] --- include/boost/graph/read_dimacs.hpp | 1 + 1 file changed, 1 insertion(+) diff --git a/include/boost/graph/read_dimacs.hpp b/include/boost/graph/read_dimacs.hpp index 656e226d..2100b316 100644 --- a/include/boost/graph/read_dimacs.hpp +++ b/include/boost/graph/read_dimacs.hpp @@ -16,6 +16,7 @@ #include #include +#include #include #include #include From 78b6d375a7b74f21c729c9329df67f1dc17a389b Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Wed, 4 Feb 2009 20:57:04 +0000 Subject: [PATCH 075/224] Default color map to white, and fixed some warnings [SVN r51019] --- include/boost/graph/two_bit_color_map.hpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/include/boost/graph/two_bit_color_map.hpp b/include/boost/graph/two_bit_color_map.hpp index 3a6d6913..7d6ce871 100644 --- a/include/boost/graph/two_bit_color_map.hpp +++ b/include/boost/graph/two_bit_color_map.hpp @@ -15,6 +15,7 @@ #include #include +#include namespace boost { @@ -50,6 +51,8 @@ struct two_bit_color_map explicit two_bit_color_map(std::size_t n, const IndexMap& index = IndexMap()) : n(n), index(index), data(new unsigned char[(n + 3) / 4]) { + // Fill to white + std::fill(data.get(), data.get() + (n + 3) / 4, 0); } }; @@ -59,7 +62,7 @@ get(const two_bit_color_map& pm, typename two_bit_color_map::key_type key) { typename property_traits::value_type i = get(pm.index, key); - assert (i < pm.n); + assert ((std::size_t)i < pm.n); return two_bit_color_type((pm.data.get()[i / 4] >> ((i % 4) * 2)) & 3); } @@ -70,7 +73,7 @@ put(const two_bit_color_map& pm, two_bit_color_type value) { typename property_traits::value_type i = get(pm.index, key); - assert (i < pm.n); + assert ((std::size_t)i < pm.n); assert (value >= 0 && value < 4); std::size_t byte_num = i / 4; std::size_t bit_position = ((i % 4) * 2); From bac69f84decd0b1b6fd81aafe1f41ed1fb1998e7 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Wed, 4 Feb 2009 20:58:15 +0000 Subject: [PATCH 076/224] Changed to two_bit_color_map by default [SVN r51020] --- .../boost/graph/dijkstra_shortest_paths.hpp | 55 +++++++++++++++---- 1 file changed, 43 insertions(+), 12 deletions(-) diff --git a/include/boost/graph/dijkstra_shortest_paths.hpp b/include/boost/graph/dijkstra_shortest_paths.hpp index 97c11a8a..6233e08b 100644 --- a/include/boost/graph/dijkstra_shortest_paths.hpp +++ b/include/boost/graph/dijkstra_shortest_paths.hpp @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include @@ -182,6 +183,41 @@ namespace boost { }; } + namespace detail { + template + struct default_color_map_generator_helper {}; + + template + struct default_color_map_generator_helper { + typedef boost::two_bit_color_map type; + static type build(const Graph& g, const IndexMap& index) { + size_t nv = num_vertices(g); + return boost::two_bit_color_map(nv, index); + } + }; + + template + struct default_color_map_generator_helper { + typedef boost::vector_property_map type; + static type build(const Graph& g, const IndexMap& index) { + return make_vector_property_map(index); + } + }; + + template + struct default_color_map_generator { + typedef boost::is_base_and_derived< + boost::vertex_list_graph_tag, + typename boost::graph_traits::traversal_category> + known_num_vertices; + typedef default_color_map_generator_helper helper; + typedef typename helper::type type; + static type build(const Graph& g, const IndexMap& index) { + return helper::build(g, index); + } + }; + } + // Call breadth first search with default color map. template color_map_holder; typedef - detail::vertex_property_map_generator + detail::default_color_map_generator ColorMapHelper; typedef typename ColorMapHelper::type ColorMap; ColorMap color = - ColorMapHelper::build(g, index_map, white_color, color_map_holder); + ColorMapHelper::build(g, index_map); dijkstra_shortest_paths_no_init( g, s, predecessor, distance, weight, index_map, compare, combine, zero, vis, color); @@ -279,12 +314,10 @@ namespace boost { Compare compare, Combine combine, DistInf inf, DistZero zero, DijkstraVisitor vis) { - std::vector color(num_vertices(g)); - default_color_type c = white_color; + 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, - make_iterator_property_map(&color[0], index_map, - c)); + color); } // Initialize distances and call breadth first search @@ -366,18 +399,16 @@ namespace boost { std::vector distance_map(n); // Default for color map - typename std::vector::size_type + typename std::vector::size_type m = is_default_param(color) ? num_vertices(g) : 1; - std::vector color_map(m); + boost::two_bit_color_map color_map(m, index_map); detail::dijkstra_dispatch2 (g, s, choose_param(distance, make_iterator_property_map (distance_map.begin(), index_map, distance_map[0])), weight, index_map, params, - choose_param(color, make_iterator_property_map - (color_map.begin(), index_map, - color_map[0]))); + choose_param(color, color_map)); } } // namespace detail From 8a9558f06f10e4f6e03294277bf593a2dba37c70 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Wed, 4 Feb 2009 21:01:27 +0000 Subject: [PATCH 077/224] Added ability to check whether an element is in the heap, and do conditional insert/update operations based on that [SVN r51021] --- include/boost/graph/detail/d_ary_heap.hpp | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/include/boost/graph/detail/d_ary_heap.hpp b/include/boost/graph/detail/d_ary_heap.hpp index 6a249046..ffbaa47c 100644 --- a/include/boost/graph/detail/d_ary_heap.hpp +++ b/include/boost/graph/detail/d_ary_heap.hpp @@ -104,6 +104,7 @@ namespace boost { } void pop() { + put(index_in_heap, data[0], (size_type)(-1)); data[0] = data.back(); put(index_in_heap, data[0], 0); data.pop_back(); @@ -120,6 +121,21 @@ namespace boost { verify_heap(); } + bool contains(const Value& v) const { + return (index != (size_type)(-1)); + } + + void push_or_update(const Value& v) { /* insert if not present, else update */ + size_type index = get(index_in_heap, v); + if (index == (size_type)(-1)) { + index = data.size(); + data.push_back(v); + put(index_in_heap, v, index); + } + preserve_heap_property_up(index); + verify_heap(); + } + private: Compare compare; Container data; @@ -211,6 +227,7 @@ namespace boost { // From the root, swap elements (each one with its smallest child) if there // are any parent-child pairs that violate the heap property void preserve_heap_property_down() { + if (data.empty()) return; size_type index = 0; Value currently_being_moved = data[0]; distance_type currently_being_moved_dist = From 292aea9404796f37036b1aa7c98daa8f2d7a6ddf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=BCrgen=20Hunold?= Date: Thu, 5 Feb 2009 20:07:08 +0000 Subject: [PATCH 078/224] Fix gcc compile error due to "undefined variable 'index'". [SVN r51035] --- include/boost/graph/detail/d_ary_heap.hpp | 1 + 1 file changed, 1 insertion(+) diff --git a/include/boost/graph/detail/d_ary_heap.hpp b/include/boost/graph/detail/d_ary_heap.hpp index ffbaa47c..72981642 100644 --- a/include/boost/graph/detail/d_ary_heap.hpp +++ b/include/boost/graph/detail/d_ary_heap.hpp @@ -122,6 +122,7 @@ namespace boost { } bool contains(const Value& v) const { + size_type index = get(index_in_heap, v); return (index != (size_type)(-1)); } From afa1569043962a271d30a4414ecf04e9e841b8b9 Mon Sep 17 00:00:00 2001 From: Andrew Sutton Date: Sun, 8 Feb 2009 13:23:09 +0000 Subject: [PATCH 079/224] Whitespace cleanup [SVN r51086] --- include/boost/graph/adjacency_list.hpp | 52 +++++++++++++------------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/include/boost/graph/adjacency_list.hpp b/include/boost/graph/adjacency_list.hpp index 20ee41f3..2b7b5d05 100644 --- a/include/boost/graph/adjacency_list.hpp +++ b/include/boost/graph/adjacency_list.hpp @@ -63,7 +63,7 @@ namespace boost { #if !defined BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION #if !defined BOOST_NO_SLIST - struct slistS {}; + struct slistS {}; #endif struct vecS { }; @@ -135,35 +135,35 @@ namespace boost { struct bind_ { typedef std::vector type; }; }; - struct listS { + struct listS { template struct bind_ { typedef std::list type; }; }; - struct setS { + struct setS { template struct bind_ { typedef std::set > type; }; }; - struct multisetS { + struct multisetS { template struct bind_ { typedef std::multiset > type; }; }; #if !defined BOOST_NO_HASH - struct hash_setS { + struct hash_setS { template struct bind_ { typedef BOOST_STD_EXTENSION_NAMESPACE::hash_set > type; }; }; #endif - struct mapS { + struct mapS { template struct bind_ { typedef std::set > type; }; }; #if !defined BOOST_NO_HASH - struct hash_mapS { + struct hash_mapS { template struct bind_ { typedef BOOST_STD_EXTENSION_NAMESPACE::hash_set > type; }; }; @@ -202,54 +202,54 @@ namespace boost { struct parallel_edge_traits { }; template <> - struct parallel_edge_traits { + struct parallel_edge_traits { typedef allow_parallel_edge_tag type; }; template <> - struct parallel_edge_traits { + struct parallel_edge_traits { typedef allow_parallel_edge_tag type; }; #if !defined BOOST_NO_SLIST template <> - struct parallel_edge_traits { + struct parallel_edge_traits { typedef allow_parallel_edge_tag type; }; #endif template <> - struct parallel_edge_traits { + struct parallel_edge_traits { typedef disallow_parallel_edge_tag type; }; template <> - struct parallel_edge_traits { + struct parallel_edge_traits { typedef allow_parallel_edge_tag type; }; #if !defined BOOST_NO_HASH template <> struct parallel_edge_traits { - typedef disallow_parallel_edge_tag type; + typedef disallow_parallel_edge_tag type; }; #endif // mapS is obsolete, replaced with setS template <> - struct parallel_edge_traits { + struct parallel_edge_traits { typedef disallow_parallel_edge_tag type; }; #if !defined BOOST_NO_HASH template <> struct parallel_edge_traits { - typedef disallow_parallel_edge_tag type; + typedef disallow_parallel_edge_tag type; }; #endif namespace detail { - template struct is_random_access { + template struct is_random_access { enum { value = false}; typedef mpl::false_ type; }; template <> - struct is_random_access { - enum { value = true }; + struct is_random_access { + enum { value = true }; typedef mpl::true_ type; }; @@ -299,7 +299,7 @@ namespace boost { typedef typename container_gen::type EdgeContainer; typedef typename DirectedS::is_bidir_t BidirectionalT; typedef typename DirectedS::is_directed_t DirectedT; - typedef typename mpl::and_::type >::type on_edge_storage; public: typedef typename mpl::if_, - VertexListS, OutEdgeListS, DirectedS, + VertexListS, OutEdgeListS, DirectedS, #if !defined(BOOST_GRAPH_NO_BUNDLED_PROPERTIES) typename detail::retag_property_list::type, @@ -382,7 +382,7 @@ namespace boost { private: typedef adjacency_list self; typedef typename detail::adj_list_gen< - self, VertexListS, OutEdgeListS, DirectedS, + self, VertexListS, OutEdgeListS, DirectedS, vertex_property_type, edge_property_type, GraphProperty, EdgeListS >::type Base; @@ -400,7 +400,7 @@ namespace boost { typedef GraphProperty graph_property_type; - inline adjacency_list(const GraphProperty& p = GraphProperty()) + inline adjacency_list(const GraphProperty& p = GraphProperty()) : m_property(p) { } inline adjacency_list(const adjacency_list& x) @@ -416,7 +416,7 @@ namespace boost { } // Required by Mutable Graph - inline adjacency_list(vertices_size_type num_vertices, + inline adjacency_list(vertices_size_type num_vertices, const GraphProperty& p = GraphProperty()) : Base(num_vertices), m_property(p) { } @@ -532,12 +532,12 @@ namespace boost { get(T Bundle::* p, adjacency_list& g) { - typedef typename property_map, T Bundle::*>::type result_type; return result_type(&g, p); } - + template inline @@ -546,7 +546,7 @@ namespace boost { get(T Bundle::* p, adjacency_list const & g) { - typedef typename property_map, T Bundle::*>::const_type result_type; return result_type(&g, p); From 70d7e523359401ea3d1836780a1a3c7948f9e8d2 Mon Sep 17 00:00:00 2001 From: Andrew Sutton Date: Sun, 8 Feb 2009 14:22:14 +0000 Subject: [PATCH 080/224] Added a test for undirected graphs [SVN r51089] --- include/boost/graph/undirected_graph.hpp | 754 +++++++++++++++++++++++ 1 file changed, 754 insertions(+) create mode 100644 include/boost/graph/undirected_graph.hpp diff --git a/include/boost/graph/undirected_graph.hpp b/include/boost/graph/undirected_graph.hpp new file mode 100644 index 00000000..b5261688 --- /dev/null +++ b/include/boost/graph/undirected_graph.hpp @@ -0,0 +1,754 @@ +// (C) Copyright 2007-2009 Andrew Sutton +// +// 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_UNDIRECTED_GRAPH_HPP +#define BOOST_GRAPH_UNDIRECTED_GRAPH_HPP + +#include +#include +#include + +namespace boost +{ + struct undirected_graph_tag { }; + + template +class undirected_graph +{ + typedef property vertex_property; + typedef property edge_property; +public: + typedef adjacency_list graph_type; + +private: + // storage selectors + typedef typename graph_type::vertex_list_selector vertex_list_selector; + typedef typename graph_type::edge_list_selector edge_list_selector; + typedef typename graph_type::out_edge_list_selector out_edge_list_selector; + typedef typename graph_type::directed_selector directed_selector; + +public: + typedef undirected_graph_tag graph_tag; + + // types for properties and bundling + typedef typename graph_type::graph_property_type graph_property_type; + typedef typename graph_type::vertex_property_type vertex_property_type; + typedef typename graph_type::edge_property_type edge_property_type; + typedef typename graph_type::vertex_bundled vertex_bundled; + typedef typename graph_type::edge_bundled edge_bundled; + + // more commonly used graph types + typedef typename graph_type::stored_vertex stored_vertex; + typedef typename graph_type::vertices_size_type vertices_size_type; + typedef typename graph_type::edges_size_type edges_size_type; + typedef typename graph_type::degree_size_type degree_size_type; + typedef typename graph_type::vertex_descriptor vertex_descriptor; + typedef typename graph_type::edge_descriptor edge_descriptor; + + // iterator types + typedef typename graph_type::vertex_iterator vertex_iterator; + typedef typename graph_type::edge_iterator edge_iterator; + typedef typename graph_type::out_edge_iterator out_edge_iterator; + typedef typename graph_type::in_edge_iterator in_edge_iterator; + typedef typename graph_type::adjacency_iterator adjacency_iterator; + + // miscellaneous types + typedef typename graph_type::directed_category directed_category; + 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; + + inline undirected_graph(const GraphProperty& p = GraphProperty()) + : m_graph(p) + , m_num_vertices(0) + , m_num_edges(0) + , m_max_vertex_index(0) + , m_max_edge_index(0) + { } + + inline undirected_graph(const undirected_graph& x) + : m_graph(x) + , m_num_vertices(x.m_num_vertices) + , m_num_edges(x.m_num_edges) + , m_max_vertex_index(x.m_max_vertex_index) + , m_max_edge_index(x.m_max_edge_index) + { } + + inline undirected_graph(vertices_size_type n, + const GraphProperty& p = GraphProperty()) + : m_graph(n, p) + , m_num_vertices(n) + , m_num_edges(0) + , m_max_vertex_index(n) + , m_max_edge_index(0) + { } + + template + inline undirected_graph(EdgeIterator f, + EdgeIterator l, + vertices_size_type n, + edges_size_type m = 0, + const GraphProperty& p = GraphProperty()) + : m_graph(f, l, n, m, p) + , m_num_vertices(n) + , m_num_edges(0) + , m_max_vertex_index(n) + , m_max_edge_index(0) + { + // Can't always guarantee that the number of edges is actually + // m if distance(f, l) != m (or is undefined). + m_num_edges = m_max_edge_index = boost::num_edges(m_graph); + } + + inline undirected_graph& operator =(const undirected_graph& g) + { + if(&g != this) { + m_graph = g.m_graph; + m_num_vertices = g.m_num_vertices; + m_num_edges = g.m_num_edges; + m_max_vertex_index = g.m_max_vertex_index; + } + return *this; + } + + // The impl_() methods are not part of the public interface. + inline graph_type& impl() + { return m_graph; } + + inline const graph_type& impl() const + { return m_graph; } + + + // The following methods are not part of the public interface + inline vertices_size_type num_vertices() const + { return m_num_vertices; } + + inline vertex_descriptor add_vertex() + { + vertex_descriptor v = boost::add_vertex(m_graph); + boost::put(vertex_index, m_graph, v, m_max_vertex_index); + m_num_vertices++; + m_max_vertex_index++; + return v; + } + + inline void clear_vertex(vertex_descriptor v) + { + std::pair + p = boost::out_edges(v, m_graph); + m_num_edges -= std::distance(p.first, p.second); + boost::clear_vertex(v, m_graph); + } + + inline void remove_vertex(vertex_descriptor v) + { + boost::remove_vertex(v, m_graph); + --m_num_vertices; + } + + inline edges_size_type num_edges() const + { return m_num_edges; } + + inline std::pair + add_edge(vertex_descriptor u, + vertex_descriptor v) + { + std::pair ret = boost::add_edge(u, v, m_graph); + if(ret.second) { + boost::put(edge_index, m_graph, ret.first, m_max_edge_index); + ++m_num_edges; + ++m_max_edge_index; + } + return ret; + } + + inline void remove_edge(vertex_descriptor u, vertex_descriptor v) + { + // find all edges, (u, v) + std::vector edges; + out_edge_iterator i, i_end; + for(tie(i, i_end) = boost::out_edges(u, m_graph); i != i_end; ++i) { + if(boost::target(*i, m_graph) == v) { + edges.push_back(*i); + } + } + // remove all edges, (u, v) + typename std::vector::iterator + j = edges.begin(), j_end = edges.end(); + for( ; j != j_end; ++j) { + remove_edge(*j); + } + } + + inline void remove_edge(edge_iterator i) + { + remove_edge(*i); + } + + inline void remove_edge(edge_descriptor e) + { + boost::remove_edge(e, m_graph); + --m_num_edges; + } + + inline vertex_index_type max_vertex_index() const + { return m_max_vertex_index; } + + inline void renumber_vertex_indices() + { + vertex_iterator i, i_end; + tie(i, i_end) = vertices(m_graph); + m_max_vertex_index = renumber_vertex_indices(i, i_end, 0); + } + + inline void + remove_vertex_and_renumber_indices(vertex_iterator i) + { + vertex_iterator j = next(i), end = vertices(m_graph).second; + vertex_index_type n = get(vertex_index, m_graph, *i); + + // remove the offending vertex and renumber everything after + remove_vertex(*i); + m_max_vertex_index = renumber_vertex_indices(j, end, n); + } + + + inline edge_index_type max_edge_index() const + { return m_max_edge_index; } + + inline void renumber_edge_indices() + { + edge_iterator i, end; + tie(i, end) = edges(m_graph); + m_max_edge_index = renumber_edge_indices(i, end, 0); + } + + inline void + remove_edge_and_renumber_indices(edge_iterator i) + { + edge_iterator j = next(i), end = edges(m_graph.second); + edge_index_type n = get(edge_index, m_graph, *i); + + // remove the edge and renumber everything after it + remove_edge(*i); + m_max_edge_index = renumber_edge_indices(j, end, n); + } + + inline void renumber_indices() + { + renumber_vertex_indices(); + renumber_edge_indices(); + } + + // bundled property support +#ifndef BOOST_GRAPH_NO_BUNDLED_PROPERTIES + vertex_bundled& operator [](vertex_descriptor v) + { return m_graph[v]; } + + const vertex_bundled& operator [](vertex_descriptor v) const + { return m_graph[v]; } + + edge_bundled& operator [](edge_descriptor e) + { return m_graph[e]; } + + const edge_bundled& operator [](edge_descriptor e) const + { return m_graph[e]; } +#endif + + // Graph concepts + static inline vertex_descriptor null_vertex() + { return graph_type::null_vertex(); } + + inline void clear() + { + m_graph.clear(); + m_num_vertices = m_max_vertex_index = 0; + m_num_edges = m_max_edge_index = 0; + } + + inline void swap(undirected_graph& g) + { + m_graph.swap(g); + std::swap(m_num_vertices, g.m_num_vertices); + std::swap(m_max_vertex_index, g.m_max_vertex_index); + std::swap(m_num_edges, g.m_num_edges); + std::swap(m_max_edge_index, g.m_max_edge_index); + } + +private: + inline vertices_size_type + renumber_vertex_indices(vertex_iterator i, + vertex_iterator end, + vertices_size_type n) + { + typedef typename property_map::type IndexMap; + IndexMap indices = get(vertex_index, m_graph); + for( ; i != end; ++i) { + indices[*i] = n++; + } + return n; + } + + inline edges_size_type + renumber_edge_indices(edge_iterator i, + edge_iterator end, + edges_size_type n) + { + typedef typename property_map::type IndexMap; + IndexMap indices = get(edge_index, m_graph); + for( ; i != end; ++i) { + indices[*i] = n++; + } + return n; + } + + graph_type m_graph; + vertices_size_type m_num_vertices; + edges_size_type m_num_edges; + vertex_index_type m_max_vertex_index; + edge_index_type m_max_edge_index; +}; + +// IncidenceGraph concepts +template +inline typename undirected_graph::vertex_descriptor +source(typename undirected_graph::edge_descriptor e, + const undirected_graph &g) +{ + return source(e, g.impl()); +} + +template +inline typename undirected_graph::vertex_descriptor +target(typename undirected_graph::edge_descriptor e, + const undirected_graph &g) +{ + return target(e, g.impl()); +} + +template +inline typename undirected_graph::degree_size_type +out_degree(typename undirected_graph::vertex_descriptor v, + const undirected_graph &g) +{ + return out_degree(v, g.impl()); +} + +template +inline std::pair< + typename undirected_graph::out_edge_iterator, + typename undirected_graph::out_edge_iterator +> +out_edges(typename undirected_graph::vertex_descriptor v, + const undirected_graph &g) +{ + return out_edges(v, g.impl()); +} + +// BidirectionalGraph concepts +template +inline typename undirected_graph::degree_size_type +in_degree(typename undirected_graph::vertex_descriptor v, + const undirected_graph &g) +{ + return in_degree(v, g.impl()); +} + +template +inline std::pair< + typename undirected_graph::in_edge_iterator, + typename undirected_graph::in_edge_iterator +> +in_edges(typename undirected_graph::vertex_descriptor v, + const undirected_graph &g) +{ + return in_edges(v, g.impl()); +} + + +template +inline std::pair< + typename undirected_graph::out_edge_iterator, + typename undirected_graph::out_edge_iterator +> +incident_edges(typename undirected_graph::vertex_descriptor v, + const undirected_graph &g) +{ + return out_edges(v, g.impl()); +} + +template +inline typename undirected_graph::degree_size_type +degree(typename undirected_graph::vertex_descriptor v, + const undirected_graph &g) +{ + return degree(v, g.impl()); +} + +// AdjacencyGraph concepts +template +inline std::pair< + typename undirected_graph::adjacency_iterator, + typename undirected_graph::adjacency_iterator + > +adjacent_vertices(typename undirected_graph::vertex_descriptor v, + const undirected_graph& g) +{ + return adjacent_vertices(v, g.impl()); +} + +template +typename undirected_graph::vertex_descriptor +vertex(typename undirected_graph::vertices_size_type n, + const undirected_graph& g) +{ + return vertex(g.impl()); +} + +template +std::pair::edge_descriptor, bool> +edge(typename undirected_graph::vertex_descriptor u, + typename undirected_graph::vertex_descriptor v, + const undirected_graph& g) +{ + return edge(u, v, g.impl()); +} + +// VertexListGraph concepts +template +inline typename undirected_graph::vertices_size_type +num_vertices(const undirected_graph& g) +{ + return g.num_vertices(); +} + +template +inline std::pair< + typename undirected_graph::vertex_iterator, + typename undirected_graph::vertex_iterator +> +vertices(const undirected_graph& g) +{ + return vertices(g.impl()); +} + +// EdgeListGraph concepts +template +inline typename undirected_graph::edges_size_type +num_edges(const undirected_graph& g) +{ + return g.num_edges(); +} + +template +inline std::pair< +typename undirected_graph::edge_iterator, +typename undirected_graph::edge_iterator +> +edges(const undirected_graph& g) +{ + return edges(g.impl()); +} + + +// MutableGraph concepts +template +inline typename undirected_graph::vertex_descriptor +add_vertex(undirected_graph &g) +{ + return g.add_vertex(); +} + + +template +inline void +clear_vertex(typename undirected_graph::vertex_descriptor v, +undirected_graph &g) +{ + return g.clear_vertex(v); +} + +template +inline void +remove_vertex(typename undirected_graph::vertex_descriptor v, + undirected_graph &g) +{ + return g.remove_vertex(v); +} + + + +template +inline std::pair::edge_descriptor, bool> +add_edge(typename undirected_graph::vertex_descriptor u, + typename undirected_graph::vertex_descriptor v, + undirected_graph &g) +{ + return g.add_edge(u, v); +} + + +template +inline void +remove_edge(typename undirected_graph::vertex_descriptor u, + typename undirected_graph::vertex_descriptor v, + undirected_graph &g) +{ + return g.remove_edge(u, v); +} + + +template +inline void +remove_edge(typename undirected_graph::edge_descriptor e, + undirected_graph &g) +{ + return g.remove_edge(e); +} + + +template +inline void +remove_edge(typename undirected_graph::edge_iterator i, + undirected_graph &g) +{ + return g.remove_edge(i); +} + +template +inline void +remove_edge_if(Predicate pred, + undirected_graph &g) + +{ + return remove_edge_if(pred, g.impl()); +} + + +template +inline void +remove_incident_edge_if(typename undirected_graph::vertex_descriptor v, + Predicate pred, + undirected_graph &g) +{ + return remove_out_edge_if(v, pred, g.impl()); +} + +template +inline void +remove_out_edge_if(typename undirected_graph::vertex_descriptor v, + Predicate pred, + undirected_graph &g) +{ + return remove_out_edge_if(v, pred, g.impl()); +} + +template +inline void +remove_in_edge_if(typename undirected_graph::vertex_descriptor v, + Predicate pred, + 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; + }; + }; +} + +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; +}; + +// PropertyGraph concepts +template +inline typename property_map, Property>::type +get(Property p, undirected_graph& g) +{ + return get(p, g.impl()); +} + +template +inline typename property_map, Property>::const_type +get(Property p, const undirected_graph& g) +{ + return get(p, g.impl()); +} + +template +inline typename property_traits< + typename property_map::graph_type, Property>::const_type +>::value_type +get(Property p, const undirected_graph &g, const Key& k) +{ + return get(p, g.impl(), k); +} + +template +inline void +put(Property p, undirected_graph &g, const Key& k, const Value& v) +{ + put(p, g.impl(), k, v); +} + +template +typename graph_property, Property>::type& +get_property(undirected_graph& g, Property p) +{ + return get_property(g.impl(), p); +} + +template +const typename graph_property, Property>::type& +get_property(const undirected_graph& g, Property p) +{ + return get_property(g.impl(), p); +} + +template +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 Bundle::*>::type +get(Type Bundle::* p, undirected_graph& g) +{ +typedef typename property_map, Type Bundle::*>::type + return_type; +return return_type(&g, p); +} + +template +inline typename property_map, Type Bundle::*>::const_type +get(Type Bundle::* p, const undirected_graph& g) +{ +typedef typename property_map, Type Bundle::*>::const_type + return_type; +return return_type(&g, p); +} + +template +inline Type +get(Type Bundle::* p, const undirected_graph &g, const Key& k) +{ +return get(p, g.impl(), k); +} + +template +inline void +put(Type Bundle::* p, undirected_graph &g, const Key& k, const Value& v) +{ +// put(get(p, g.impl()), k, v); +put(p, g.impl(), k, v); +} +#endif + +// Vertex index management + +template +inline typename undirected_graph::vertex_index_type +get_vertex_index(typename undirected_graph::vertex_descriptor v, + const undirected_graph& g) +{ return get(vertex_index, g, v); } + +template +typename undirected_graph::vertex_index_type +max_vertex_index(const undirected_graph& g) +{ return g.max_vertex_index(); } + +template +inline void +renumber_vertex_indices(undirected_graph& g) +{ g.renumber_vertex_indices(); } + +template +inline void +remove_vertex_and_renumber_indices(typename undirected_graph::vertex_iterator i, + undirected_graph& g) +{ g.remove_vertex_and_renumber_indices(i); } + + +// Edge index management + +template +inline typename undirected_graph::edge_index_type +get_edge_index(typename undirected_graph::edge_descriptor v, + const undirected_graph& g) +{ return get(edge_index, g, v); } + +template +typename undirected_graph::edge_index_type +max_edge_index(const undirected_graph& g) +{ return g.max_edge_index(); } + +template +inline void +renumber_edge_indices(undirected_graph& g) +{ + g.renumber_edge_indices(); +} + +template +inline void +remove_edge_and_renumber_indices(typename undirected_graph::edge_iterator i, + undirected_graph& g) +{ g.remove_edge_and_renumber_indices(i); } + +// Index management +template +inline void +renumber_indices(undirected_graph& g) +{ g.renumber_indices(); } + +} /* namespace boost */ + +#endif From 059663710395b2a775af5df64ad3a0c478fb9f25 Mon Sep 17 00:00:00 2001 From: Andrew Sutton Date: Sun, 8 Feb 2009 14:23:16 +0000 Subject: [PATCH 081/224] Added a test for undirected graphs [SVN r51090] --- test/Jamfile.v2 | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index cc7bce07..114cc03b 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -93,6 +93,8 @@ test-suite graph_test : [ run is_straight_line_draw_test.cpp ] [ run metric_tsp_approx.cpp : metric_tsp_approx.txt ] [ compile dimacs.cpp ] + + [ run undirected_graph.cpp ] $(optional_tests) ; From 6671008f35d5f568949aa5ba0cc20c1fca9b01c1 Mon Sep 17 00:00:00 2001 From: Andrew Sutton Date: Sun, 8 Feb 2009 14:25:06 +0000 Subject: [PATCH 082/224] Integrating SOC 2007 code [SVN r51091] --- include/boost/graph/directed_graph.hpp | 748 +++++++++++++++++ include/boost/graph/graph_concepts.hpp | 1024 +++++++++++++----------- include/boost/graph/numeric_values.hpp | 52 ++ 3 files changed, 1370 insertions(+), 454 deletions(-) create mode 100644 include/boost/graph/directed_graph.hpp create mode 100644 include/boost/graph/numeric_values.hpp diff --git a/include/boost/graph/directed_graph.hpp b/include/boost/graph/directed_graph.hpp new file mode 100644 index 00000000..1b71f523 --- /dev/null +++ b/include/boost/graph/directed_graph.hpp @@ -0,0 +1,748 @@ +// (C) Copyright 2007-2009 Andrew Sutton +// +// 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_DIRECTED_GRAPH_HPP +#define BOOST_GRAPH_DIRECTED_GRAPH_HPP + +#include +#include +#include + +namespace boost +{ +struct directed_graph_tag { }; + +/** +* 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 +* EdgeIndexGraph concepts. The graph is also fully mutable, supporting +* both insertions and removals. +* +* @note Special care must be taken when removing vertices or edges since +* those operations can invalidate the numbering of vertices. +*/ +template < + typename VertexProperty = no_property, + typename EdgeProperty = no_property, + typename GraphProperty = no_property +> +class directed_graph +{ + // Wrap the user-specified properties with an index. + typedef property vertex_property; + typedef property edge_property; + +public: + typedef adjacency_list< + listS, listS, bidirectionalS, + vertex_property, edge_property, GraphProperty, + listS + > graph_type; + +private: + // storage selectors + typedef typename graph_type::vertex_list_selector vertex_list_selector; + typedef typename graph_type::edge_list_selector edge_list_selector; + typedef typename graph_type::out_edge_list_selector out_edge_list_selector; + typedef typename graph_type::directed_selector directed_selector; + +public: + typedef directed_graph_tag graph_tag; + + // types for properties and bundling + typedef typename graph_type::graph_property_type graph_property_type; + typedef typename graph_type::vertex_property_type vertex_property_type; + typedef typename graph_type::edge_property_type edge_property_type; + typedef typename graph_type::vertex_bundled vertex_bundled; + typedef typename graph_type::edge_bundled edge_bundled; + + // more commonly used graph types + typedef typename graph_type::stored_vertex stored_vertex; + typedef typename graph_type::vertices_size_type vertices_size_type; + typedef typename graph_type::edges_size_type edges_size_type; + typedef typename graph_type::degree_size_type degree_size_type; + typedef typename graph_type::vertex_descriptor vertex_descriptor; + typedef typename graph_type::edge_descriptor edge_descriptor; + + // iterator types + typedef typename graph_type::vertex_iterator vertex_iterator; + typedef typename graph_type::edge_iterator edge_iterator; + typedef typename graph_type::out_edge_iterator out_edge_iterator; + typedef typename graph_type::in_edge_iterator in_edge_iterator; + typedef typename graph_type::adjacency_iterator adjacency_iterator; + + // miscellaneous types + typedef typename graph_type::directed_category directed_category; + 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; + + inline directed_graph(const GraphProperty& p = GraphProperty()) + : m_graph(p) + , m_num_vertices(0) + , m_num_edges(0) + , m_max_vertex_index(0) + , m_max_edge_index(0) + { } + + inline directed_graph(const directed_graph& x) + : m_graph(x) + , m_num_vertices(x.m_num_vertices) + , m_num_edges(x.m_num_edges) + , m_max_vertex_index(x.m_max_vertex_index) + , m_max_edge_index(x.m_max_edge_index) + { } + + inline directed_graph(vertices_size_type n, + const GraphProperty& p = GraphProperty()) + : m_graph(n, p) + , m_num_vertices(n) + , m_num_edges(0) + , m_max_vertex_index(n) + , m_max_edge_index(0) + { } + + template + inline directed_graph(EdgeIterator f, + EdgeIterator l, + vertices_size_type n, + edges_size_type m = 0, + const GraphProperty& p = GraphProperty()) + : m_graph(f, l, n, m, p) + , m_num_vertices(n) + , m_num_edges(0) + , m_max_vertex_index(n) + , m_max_edge_index(0) + { + // Can't always guarantee that the number of edges is actually + // m if distance(f, l) != m (or is undefined). + m_num_edges = m_max_edge_index = boost::num_edges(m_graph); + } + + inline directed_graph& operator=(const directed_graph& g) + { + if(&g != this) { + m_graph = g.m_graph; + m_num_vertices = g.m_num_vertices; + m_num_edges = g.m_num_edges; + m_max_vertex_index = g.m_max_vertex_index; + m_max_edge_index = g.m_max_edge_index; + } + return *this; + } + + // The impl_() methods are not part of the public interface. + inline graph_type& impl() + { return m_graph; } + + inline const graph_type& impl() const + { return m_graph; } + + + // The following methods are not part of the public interface + inline vertices_size_type num_vertices() const + { return m_num_vertices; } + + inline vertex_descriptor add_vertex() + { + vertex_descriptor v = boost::add_vertex(m_graph); + boost::put(vertex_index, m_graph, v, m_max_vertex_index); + m_num_vertices++; + m_max_vertex_index++; + return v; + } + + inline void clear_vertex(vertex_descriptor v) + { + std::pair + p = boost::out_edges(v, m_graph); + m_num_edges -= std::distance(p.first, p.second); + boost::clear_vertex(v, m_graph); + } + + inline void remove_vertex(vertex_descriptor v) + { + boost::remove_vertex(v, m_graph); + --m_num_vertices; + } + + inline edges_size_type num_edges() const + { return m_num_edges; } + + inline std::pair + add_edge(vertex_descriptor u, + vertex_descriptor v) + { + std::pair ret = boost::add_edge(u, v, m_graph); + if(ret.second) { + boost::put(edge_index, m_graph, ret.first, m_max_edge_index); + ++m_num_edges; + ++m_max_edge_index; + } + return ret; + } + + inline void remove_edge(vertex_descriptor u, vertex_descriptor v) + { + // find all edges, (u, v) + std::vector edges; + out_edge_iterator i, i_end; + for(tie(i, i_end) = boost::out_edges(u, m_graph); i != i_end; ++i) { + if(boost::target(*i, m_graph) == v) { + edges.push_back(*i); + } + } + // remove all edges, (u, v) + typename std::vector::iterator + j = edges.begin(), j_end = edges.end(); + for( ; j != j_end; ++j) { + remove_edge(*j); + } + } + + inline void remove_edge(edge_iterator i) + { + remove_edge(*i); + } + + inline void remove_edge(edge_descriptor e) + { + boost::remove_edge(e, m_graph); + --m_num_edges; + } + + inline vertex_index_type max_vertex_index() const + { return m_max_vertex_index; } + + inline void + renumber_vertex_indices() + { + vertex_iterator i, end; + tie(i, end) = vertices(m_graph); + m_max_vertex_index = renumber_vertex_indices(i, end, 0); + } + + inline void + remove_vertex_and_renumber_indices(vertex_iterator i) + { + vertex_iterator j = next(i), end = vertices(m_graph).second; + vertex_index_type n = get(vertex_index, m_graph, *i); + + // remove the offending vertex and renumber everything after + remove_vertex(*i); + m_max_vertex_index = renumber_vertex_indices(j, end, n); + } + + inline edge_index_type + max_edge_index() const + { return m_max_edge_index; } + + inline void + renumber_edge_indices() + { + edge_iterator i, end; + tie(i, end) = edges(m_graph); + m_max_edge_index = renumber_edge_indices(i, end, 0); + } + + inline void + remove_edge_and_renumber_indices(edge_iterator i) + { + edge_iterator j = next(i), end = edges(m_graph).second; + edge_index_type n = get(edge_index, m_graph, *i); + + // remove the offending edge and renumber everything after + remove_edge(*i); + m_max_edge_index = renumber_edge_indices(j, end, n); + } + + inline void + renumber_indices() + { + renumber_vertex_indices(); + renumber_edge_indices(); + } + + // bundled property support +#ifndef BOOST_GRAPH_NO_BUNDLED_PROPERTIES + vertex_bundled& operator[](vertex_descriptor v) + { return m_graph[v]; } + + const vertex_bundled& operator[](vertex_descriptor v) const + { return m_graph[v]; } + + edge_bundled& operator[](edge_descriptor e) + { return m_graph[e]; } + + const edge_bundled& operator[](edge_descriptor e) const + { return m_graph[e]; } +#endif + + // Graph concepts + static inline vertex_descriptor null_vertex() + { return graph_type::null_vertex(); } + + inline void clear() + { + m_graph.clear(); + m_num_vertices = m_max_vertex_index = 0; + m_num_edges = m_max_edge_index = 0; + } + + inline void swap(directed_graph& g) + { + m_graph.swap(g); + std::swap(m_num_vertices, g.m_num_vertices); + std::swap(m_max_vertex_index, g.m_max_vertex_index); + std::swap(m_num_edges, g.m_num_edges); + std::swap(m_max_edge_index, g.m_max_edge_index); + } + +private: + inline vertices_size_type + renumber_vertex_indices(vertex_iterator i, + vertex_iterator end, + vertices_size_type n) + { + typedef typename property_map::type IndexMap; + IndexMap indices = get(vertex_index, m_graph); + for( ; i != end; ++i) { + indices[*i] = n++; + } + return n; + } + + inline vertices_size_type + renumber_edge_indices(edge_iterator i, + edge_iterator end, + vertices_size_type n) + { + typedef typename property_map::type IndexMap; + IndexMap indices = get(edge_index, m_graph); + for( ; i != end; ++i) { + indices[*i] = n++; + } + return n; + } + + graph_type m_graph; + vertices_size_type m_num_vertices; + edges_size_type m_num_edges; + vertex_index_type m_max_vertex_index; + edge_index_type m_max_edge_index; +}; + +// IncidenceGraph concepts +template +inline typename directed_graph::vertex_descriptor +source(typename directed_graph::edge_descriptor e, + const directed_graph &g) +{ + return source(e, g.impl()); +} + +template +inline typename directed_graph::vertex_descriptor +target(typename directed_graph::edge_descriptor e, + const directed_graph &g) +{ + return target(e, g.impl()); +} + +template +inline typename directed_graph::degree_size_type +out_degree(typename directed_graph::vertex_descriptor v, + const directed_graph &g) +{ + return out_degree(v, g.impl()); +} + +template +inline std::pair< + typename directed_graph::out_edge_iterator, + typename directed_graph::out_edge_iterator +> +out_edges(typename directed_graph::vertex_descriptor v, + const directed_graph &g) +{ + return out_edges(v, g.impl()); +} + +// BidirectionalGraph concepts +template +inline typename directed_graph::degree_size_type +in_degree(typename directed_graph::vertex_descriptor v, + const directed_graph &g) +{ + return in_degree(v, g.impl()); +} + +template +inline std::pair< + typename directed_graph::in_edge_iterator, + typename directed_graph::in_edge_iterator +> +in_edges(typename directed_graph::vertex_descriptor v, + const directed_graph &g) +{ + return in_edges(v, g.impl()); +} + + +template +inline typename directed_graph::degree_size_type +degree(typename directed_graph::vertex_descriptor v, + const directed_graph &g) +{ + return degree(v, g.impl()); +} + +// AdjacencyGraph concepts +template +inline std::pair< + typename directed_graph::adjacency_iterator, + typename directed_graph::adjacency_iterator + > +adjacent_vertices(typename directed_graph::vertex_descriptor v, + const directed_graph& g) +{ + return adjacent_vertices(v, g.impl()); +} + +template +typename directed_graph::vertex_descriptor +vertex(typename directed_graph::vertices_size_type n, + const directed_graph& g) +{ + return vertex(g.impl()); +} + +template +std::pair::edge_descriptor, bool> +edge(typename directed_graph::vertex_descriptor u, + typename directed_graph::vertex_descriptor v, + const directed_graph& g) +{ + return edge(u, v, g.impl()); +} + +// VertexListGraph concepts +template +inline typename directed_graph::vertices_size_type +num_vertices(const directed_graph& g) +{ + return g.num_vertices(); +} + +template +inline std::pair< + typename directed_graph::vertex_iterator, + typename directed_graph::vertex_iterator +> +vertices(const directed_graph& g) +{ + return vertices(g.impl()); +} + +// EdgeListGraph concepts +template +inline typename directed_graph::edges_size_type +num_edges(const directed_graph& g) +{ + return g.num_edges(); +} + +template +inline std::pair< +typename directed_graph::edge_iterator, +typename directed_graph::edge_iterator +> +edges(const directed_graph& g) +{ + return edges(g.impl()); +} + + +// MutableGraph concepts +template +inline typename directed_graph::vertex_descriptor +add_vertex(directed_graph &g) +{ + return g.add_vertex(); +} + + +template +inline void +clear_vertex(typename directed_graph::vertex_descriptor v, +directed_graph &g) +{ + return g.clear_vertex(v); +} + +template +inline void +remove_vertex(typename directed_graph::vertex_descriptor v, + directed_graph &g) +{ + return g.remove_vertex(v); +} + + + +template +inline std::pair::edge_descriptor, bool> +add_edge(typename directed_graph::vertex_descriptor u, + typename directed_graph::vertex_descriptor v, + directed_graph &g) +{ + return g.add_edge(u, v); +} + + +template +inline void +remove_edge(typename directed_graph::vertex_descriptor u, + typename directed_graph::vertex_descriptor v, + directed_graph &g) +{ + return g.remove_edge(u, v); +} + + +template +inline void +remove_edge(typename directed_graph::edge_descriptor e, + directed_graph &g) +{ + return g.remove_edge(e); +} + + +template +inline void +remove_edge(typename directed_graph::edge_iterator i, + directed_graph &g) +{ + return g.remove_edge(i); +} + +template +inline void +remove_edge_if(Predicate pred, + directed_graph &g) + +{ + return remove_edge_if(pred, g.impl()); +} + + +template +inline void +remove_out_edge_if(typename directed_graph::vertex_descriptor v, + Predicate pred, + directed_graph &g) +{ + return remove_out_edge_if(v, pred, g.impl()); +} + +template +inline void +remove_in_edge_if(typename directed_graph::vertex_descriptor v, + Predicate pred, + 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 edge_property_selector +{ + typedef detail::directed_graph_edge_property_selector type; +}; + +// PropertyGraph concepts +template +inline typename property_map, Property>::type +get(Property p, directed_graph& g) +{ + return get(p, g.impl()); +} + +template +inline typename property_map, Property>::const_type +get(Property p, const directed_graph& g) +{ + return get(p, g.impl()); +} + +template +inline typename property_traits< + typename property_map::graph_type, Property>::const_type +>::value_type +get(Property p, const directed_graph &g, const Key& k) +{ + return get(p, g.impl(), k); +} + +template +inline void +put(Property p, directed_graph &g, const Key& k, const Value& v) +{ + put(p, g.impl(), k, v); +} + +template +typename graph_property, Property>::type& +get_property(directed_graph& g, Property p) +{ + return get_property(g.impl(), p); +} + +template +const typename graph_property, Property>::type& +get_property(const directed_graph& g, Property p) +{ + return get_property(g.impl(), p); +} + +template +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 Bundle::*>::type +get(Type Bundle::* p, directed_graph& g) +{ +typedef typename property_map, Type Bundle::*>::type + return_type; +return return_type(&g, p); +} + +template +inline typename property_map, Type Bundle::*>::const_type +get(Type Bundle::* p, const directed_graph& g) +{ +typedef typename property_map, Type Bundle::*>::const_type + return_type; +return return_type(&g, p); +} + +template +inline Type +get(Type Bundle::* p, const directed_graph &g, const Key& k) +{ +return get(p, g.impl(), k); +} + +template +inline void +put(Type Bundle::* p, directed_graph &g, const Key& k, const Value& v) +{ +// put(get(p, g.impl()), k, v); +put(p, g.impl(), k, v); +} +#endif + +// Vertex index management + +template +inline typename directed_graph::vertex_index_type +get_vertex_index(typename directed_graph::vertex_descriptor v, + const directed_graph& g) +{ return get(vertex_index, g, v); } + +template +typename directed_graph::vertex_index_type +max_vertex_index(const directed_graph& g) +{ return g.max_vertex_index(); } + +template +inline void +renumber_vertex_indices(directed_graph& g) +{ g.renumber_vertex_indices(); } + +template +inline void +remove_vertex_and_renumber_indices(typename directed_graph::vertex_iterator i, + directed_graph& g) +{ g.remove_vertex_and_renumber_indices(i); } + +// Edge index management + +template +inline typename directed_graph::edge_index_type +get_edge_index(typename directed_graph::edge_descriptor v, + const directed_graph& g) +{ return get(edge_index, g, v); } + +template +typename directed_graph::edge_index_type +max_edge_index(const directed_graph& g) +{ return g.max_edge_index(); } + +template +inline void +renumber_edge_indices(directed_graph& g) +{ g.renumber_edge_indices(); } + +template +inline void +remove_edge_and_renumber_indices(typename directed_graph::edge_iterator i, + directed_graph& g) +{ g.remove_edge_and_renumber_indices(i); } + +// Index management +template +inline void +renumber_indices(directed_graph& g) +{ g.renumber_indices(); } + +} /* namespace boost */ + +#endif diff --git a/include/boost/graph/graph_concepts.hpp b/include/boost/graph/graph_concepts.hpp index c6a3fe6c..3f5ac0d9 100644 --- a/include/boost/graph/graph_concepts.hpp +++ b/include/boost/graph/graph_concepts.hpp @@ -3,6 +3,8 @@ // Copyright 1997, 1998, 1999, 2000 University of Notre Dame. // Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek // +// Copyright 2009, Andrew Sutton +// // 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) @@ -12,14 +14,14 @@ #define BOOST_GRAPH_CONCEPTS_HPP #include -#include #include +#include #include +#include #include #include #include - namespace boost { // dwa 2003/7/11 -- This clearly shouldn't be necessary, but if @@ -34,477 +36,591 @@ namespace boost && !BOOST_WORKAROUND(__GNUC__, <= 2) \ && !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) # define BOOST_VECTOR_AS_GRAPH_GRAPH_ADL_HACK -#endif +#endif #ifdef BOOST_VECTOR_AS_GRAPH_GRAPH_ADL_HACK template typename T::ThereReallyIsNoMemberByThisNameInT vertices(T const&); -#endif +#endif - namespace concepts { - BOOST_concept(MultiPassInputIterator,(T)) { - BOOST_CONCEPT_USAGE(MultiPassInputIterator) { - BOOST_CONCEPT_ASSERT((InputIterator)); - } - }; + namespace concepts { + BOOST_concept(MultiPassInputIterator,(T)) { + BOOST_CONCEPT_USAGE(MultiPassInputIterator) { + BOOST_CONCEPT_ASSERT((InputIterator)); + } + }; - BOOST_concept(Graph,(G)) - { - typedef typename graph_traits::vertex_descriptor vertex_descriptor; - typedef typename graph_traits::directed_category directed_category; - typedef typename graph_traits::edge_parallel_category - edge_parallel_category; - - typedef typename graph_traits::traversal_category - traversal_category; - - BOOST_CONCEPT_USAGE(Graph) - { - BOOST_CONCEPT_ASSERT((DefaultConstructible)); - BOOST_CONCEPT_ASSERT((EqualityComparable)); - BOOST_CONCEPT_ASSERT((Assignable)); - } - G g; - }; - - BOOST_concept(IncidenceGraph,(G)) - : Graph - { - typedef typename graph_traits::edge_descriptor edge_descriptor; - typedef typename graph_traits::out_edge_iterator - out_edge_iterator; - - typedef typename graph_traits::traversal_category - traversal_category; - - BOOST_CONCEPT_USAGE(IncidenceGraph) { - BOOST_CONCEPT_ASSERT((MultiPassInputIterator)); - BOOST_CONCEPT_ASSERT((DefaultConstructible)); - BOOST_CONCEPT_ASSERT((EqualityComparable)); - BOOST_CONCEPT_ASSERT((Assignable)); - BOOST_CONCEPT_ASSERT((Convertible)); - - p = out_edges(u, g); - n = out_degree(u, g); - e = *p.first; - u = source(e, g); - v = target(e, g); - const_constraints(g); - } - void const_constraints(const G& cg) { - p = out_edges(u, cg); - n = out_degree(u, cg); - e = *p.first; - u = source(e, cg); - v = target(e, cg); - } - std::pair p; - typename graph_traits::vertex_descriptor u, v; - typename graph_traits::edge_descriptor e; - typename graph_traits::degree_size_type n; - G g; - }; - - BOOST_concept(BidirectionalGraph,(G)) - : IncidenceGraph - { - typedef typename graph_traits::in_edge_iterator - in_edge_iterator; - typedef typename graph_traits::traversal_category - traversal_category; - - BOOST_CONCEPT_USAGE(BidirectionalGraph) { - BOOST_CONCEPT_ASSERT((MultiPassInputIterator)); - BOOST_CONCEPT_ASSERT((Convertible)); - - p = in_edges(v, g); - n = in_degree(v, g); - e = *p.first; - const_constraints(g); - } - void const_constraints(const G& cg) { - p = in_edges(v, cg); - n = in_degree(v, cg); - e = *p.first; - } - std::pair p; - typename graph_traits::vertex_descriptor v; - typename graph_traits::edge_descriptor e; - typename graph_traits::degree_size_type n; - G g; - }; - - BOOST_concept(AdjacencyGraph,(G)) - : Graph - { - typedef typename graph_traits::adjacency_iterator - adjacency_iterator; - typedef typename graph_traits::traversal_category - traversal_category; - - BOOST_CONCEPT_USAGE(AdjacencyGraph) { - BOOST_CONCEPT_ASSERT((MultiPassInputIterator)); - BOOST_CONCEPT_ASSERT((Convertible)); - - p = adjacent_vertices(v, g); - v = *p.first; - const_constraints(g); - } - void const_constraints(const G& cg) { - p = adjacent_vertices(v, cg); - } - std::pair p; - typename graph_traits::vertex_descriptor v; - G g; - }; - - BOOST_concept(VertexListGraph,(G)) - : Graph - { - typedef typename graph_traits::vertex_iterator vertex_iterator; - typedef typename graph_traits::vertices_size_type vertices_size_type; - typedef typename graph_traits::traversal_category - traversal_category; - - BOOST_CONCEPT_USAGE(VertexListGraph) { - BOOST_CONCEPT_ASSERT((MultiPassInputIterator)); - BOOST_CONCEPT_ASSERT((Convertible)); - -#ifdef BOOST_VECTOR_AS_GRAPH_GRAPH_ADL_HACK - // dwa 2003/7/11 -- This clearly shouldn't be necessary, but if - // you want to use vector_as_graph, it is! I'm sure the graph - // library leaves these out all over the place. Probably a - // redesign involving specializing a template with a static - // member function is in order :( - using boost::vertices; -#endif - p = vertices(g); - v = *p.first; - const_constraints(g); - } - void const_constraints(const G& cg) { -#ifdef BOOST_VECTOR_AS_GRAPH_GRAPH_ADL_HACK - // dwa 2003/7/11 -- This clearly shouldn't be necessary, but if - // you want to use vector_as_graph, it is! I'm sure the graph - // library leaves these out all over the place. Probably a - // redesign involving specializing a template with a static - // member function is in order :( - using boost::vertices; -#endif - - p = vertices(cg); - v = *p.first; - V = num_vertices(cg); - } - std::pair p; - typename graph_traits::vertex_descriptor v; - G g; - vertices_size_type V; - }; - - BOOST_concept(EdgeListGraph,(G)) - : Graph - { - typedef typename graph_traits::edge_descriptor edge_descriptor; - typedef typename graph_traits::edge_iterator edge_iterator; - typedef typename graph_traits::edges_size_type edges_size_type; - typedef typename graph_traits::traversal_category - traversal_category; - - BOOST_CONCEPT_USAGE(EdgeListGraph) { - BOOST_CONCEPT_ASSERT((MultiPassInputIterator)); - BOOST_CONCEPT_ASSERT((DefaultConstructible)); - BOOST_CONCEPT_ASSERT((EqualityComparable)); - BOOST_CONCEPT_ASSERT((Assignable)); - BOOST_CONCEPT_ASSERT((Convertible)); - - p = edges(g); - e = *p.first; - u = source(e, g); - v = target(e, g); - const_constraints(g); - } - void const_constraints(const G& cg) { - p = edges(cg); - E = num_edges(cg); - e = *p.first; - u = source(e, cg); - v = target(e, cg); - } - std::pair p; - typename graph_traits::vertex_descriptor u, v; - typename graph_traits::edge_descriptor e; - edges_size_type E; - G g; - }; - - BOOST_concept(VertexAndEdgeListGraph,(G)) - : VertexListGraph - , EdgeListGraph - { - }; - - // Where to put the requirement for this constructor? - // G g(n_vertices); - // Not in mutable graph, then LEDA graph's can't be models of - // MutableGraph. - - BOOST_concept(EdgeMutableGraph,(G)) - { - typedef typename graph_traits::edge_descriptor edge_descriptor; - - BOOST_CONCEPT_USAGE(EdgeMutableGraph) { - p = add_edge(u, v, g); - remove_edge(u, v, g); - remove_edge(e, g); - clear_vertex(v, g); - } - G g; - edge_descriptor e; - std::pair p; - typename graph_traits::vertex_descriptor u, v; - }; - - BOOST_concept(VertexMutableGraph,(G)) - { - - BOOST_CONCEPT_USAGE(VertexMutableGraph) { - v = add_vertex(g); - remove_vertex(v, g); - } - G g; - typename graph_traits::vertex_descriptor u, v; - }; - - BOOST_concept(MutableGraph,(G)) - : EdgeMutableGraph - , VertexMutableGraph - { - }; - - template - struct dummy_edge_predicate { - bool operator()(const edge_descriptor&) const { - return false; - } - }; - - BOOST_concept(MutableIncidenceGraph,(G)) - : MutableGraph - { - BOOST_CONCEPT_USAGE(MutableIncidenceGraph) { - remove_edge(iter, g); - remove_out_edge_if(u, p, g); - } - G g; - typedef typename graph_traits::edge_descriptor edge_descriptor; - dummy_edge_predicate p; - typename boost::graph_traits::vertex_descriptor u; - typename boost::graph_traits::out_edge_iterator iter; - }; - - BOOST_concept(MutableBidirectionalGraph,(G)) - : MutableIncidenceGraph - { - BOOST_CONCEPT_USAGE(MutableBidirectionalGraph) - { - remove_in_edge_if(u, p, g); - } - G g; - typedef typename graph_traits::edge_descriptor edge_descriptor; - dummy_edge_predicate p; - typename boost::graph_traits::vertex_descriptor u; - }; - - BOOST_concept(MutableEdgeListGraph,(G)) - : EdgeMutableGraph - { - BOOST_CONCEPT_USAGE(MutableEdgeListGraph) { - remove_edge_if(p, g); - } - G g; - typedef typename graph_traits::edge_descriptor edge_descriptor; - dummy_edge_predicate p; - }; - - BOOST_concept(VertexMutablePropertyGraph,(G)) - : VertexMutableGraph - { - BOOST_CONCEPT_USAGE(VertexMutablePropertyGraph) { - v = add_vertex(vp, g); - } - G g; - typename graph_traits::vertex_descriptor v; - typename vertex_property::type vp; - }; - - BOOST_concept(EdgeMutablePropertyGraph,(G)) - : EdgeMutableGraph - { - typedef typename graph_traits::edge_descriptor edge_descriptor; - - BOOST_CONCEPT_USAGE(EdgeMutablePropertyGraph) { - p = add_edge(u, v, ep, g); - } - G g; - std::pair p; - typename graph_traits::vertex_descriptor u, v; - typename edge_property::type ep; - }; - - BOOST_concept(AdjacencyMatrix,(G)) - : Graph - { - typedef typename graph_traits::edge_descriptor edge_descriptor; - - BOOST_CONCEPT_USAGE(AdjacencyMatrix) { - p = edge(u, v, g); - const_constraints(g); - } - void const_constraints(const G& cg) { - p = edge(u, v, cg); - } - typename graph_traits::vertex_descriptor u, v; - std::pair p; - G g; - }; - - BOOST_concept(ReadablePropertyGraph,(G)(X)(Property)) - : Graph - { - typedef typename property_map::const_type const_Map; - - BOOST_CONCEPT_USAGE(ReadablePropertyGraph) + BOOST_concept(Graph,(G)) { - BOOST_CONCEPT_ASSERT((ReadablePropertyMapConcept)); + typedef typename graph_traits::vertex_descriptor vertex_descriptor; + typedef typename graph_traits::directed_category directed_category; + typedef typename graph_traits::edge_parallel_category + edge_parallel_category; - const_constraints(g); - } - void const_constraints(const G& cg) { - const_Map pmap = get(Property(), cg); - pval = get(Property(), cg, x); - ignore_unused_variable_warning(pmap); - } - G g; - X x; - typename property_traits::value_type pval; - }; + typedef typename graph_traits::traversal_category + traversal_category; - BOOST_concept(PropertyGraph,(G)(X)(Property)) - : ReadablePropertyGraph - { - typedef typename property_map::type Map; - BOOST_CONCEPT_USAGE(PropertyGraph) { - BOOST_CONCEPT_ASSERT((ReadWritePropertyMapConcept)); + BOOST_CONCEPT_USAGE(Graph) + { + BOOST_CONCEPT_ASSERT((DefaultConstructible)); + BOOST_CONCEPT_ASSERT((EqualityComparable)); + BOOST_CONCEPT_ASSERT((Assignable)); + } + G g; + }; - Map pmap = get(Property(), g); - pval = get(Property(), g, x); - put(Property(), g, x, pval); - ignore_unused_variable_warning(pmap); - } - G g; - X x; - typename property_traits::value_type pval; - }; + BOOST_concept(IncidenceGraph,(G)) + : Graph + { + typedef typename graph_traits::edge_descriptor edge_descriptor; + typedef typename graph_traits::out_edge_iterator + out_edge_iterator; - BOOST_concept(LvaluePropertyGraph,(G)(X)(Property)) - : ReadablePropertyGraph - { - typedef typename property_map::type Map; - typedef typename property_map::const_type const_Map; + typedef typename graph_traits::traversal_category + traversal_category; - BOOST_CONCEPT_USAGE(LvaluePropertyGraph) { - BOOST_CONCEPT_ASSERT((LvaluePropertyMapConcept)); + BOOST_CONCEPT_USAGE(IncidenceGraph) { + BOOST_CONCEPT_ASSERT((MultiPassInputIterator)); + BOOST_CONCEPT_ASSERT((DefaultConstructible)); + BOOST_CONCEPT_ASSERT((EqualityComparable)); + BOOST_CONCEPT_ASSERT((Assignable)); + BOOST_CONCEPT_ASSERT((Convertible)); - pval = get(Property(), g, x); - put(Property(), g, x, pval); - } - G g; - X x; - typename property_traits::value_type pval; - }; + p = out_edges(u, g); + n = out_degree(u, g); + e = *p.first; + u = source(e, g); + v = target(e, g); + const_constraints(g); + } + void const_constraints(const G& cg) { + p = out_edges(u, cg); + n = out_degree(u, cg); + e = *p.first; + u = source(e, cg); + v = target(e, cg); + } + std::pair p; + typename graph_traits::vertex_descriptor u, v; + typename graph_traits::edge_descriptor e; + typename graph_traits::degree_size_type n; + G g; + }; - // This needs to move out of the graph library - BOOST_concept(Buffer,(B)) - { - BOOST_CONCEPT_USAGE(Buffer) { - b.push(t); - b.pop(); - typename B::value_type& v = b.top(); - const_constraints(b); - ignore_unused_variable_warning(v); - } - void const_constraints(const B& cb) { - const typename B::value_type& v = cb.top(); - n = cb.size(); - bool e = cb.empty(); - ignore_unused_variable_warning(v); - ignore_unused_variable_warning(e); - } - typename B::size_type n; - typename B::value_type t; - B b; - }; + BOOST_concept(BidirectionalGraph,(G)) + : IncidenceGraph + { + typedef typename graph_traits::in_edge_iterator + in_edge_iterator; + typedef typename graph_traits::traversal_category + traversal_category; - BOOST_concept(ColorValue,(C)) - : EqualityComparable - , DefaultConstructible - { - BOOST_CONCEPT_USAGE(ColorValue) { - c = color_traits::white(); - c = color_traits::gray(); - c = color_traits::black(); - } - C c; - }; + BOOST_CONCEPT_USAGE(BidirectionalGraph) { + BOOST_CONCEPT_ASSERT((MultiPassInputIterator)); + BOOST_CONCEPT_ASSERT((Convertible)); - BOOST_concept(BasicMatrix,(M)(I)(V)) - { - BOOST_CONCEPT_USAGE(BasicMatrix) { - V& elt = A[i][j]; - const_constraints(A); - ignore_unused_variable_warning(elt); - } - void const_constraints(const M& cA) { - const V& elt = cA[i][j]; - ignore_unused_variable_warning(elt); - } - M A; - I i, j; - }; + p = in_edges(v, g); + n = in_degree(v, g); + e = *p.first; + const_constraints(g); + } + void const_constraints(const G& cg) { + p = in_edges(v, cg); + n = in_degree(v, cg); + e = *p.first; + } + std::pair p; + typename graph_traits::vertex_descriptor v; + typename graph_traits::edge_descriptor e; + typename graph_traits::degree_size_type n; + G g; + }; - } // end namespace concepts + BOOST_concept(AdjacencyGraph,(G)) + : Graph + { + typedef typename graph_traits::adjacency_iterator + adjacency_iterator; + typedef typename graph_traits::traversal_category + traversal_category; - using boost::concepts::MultiPassInputIteratorConcept; - using boost::concepts::GraphConcept; - using boost::concepts::IncidenceGraphConcept; - using boost::concepts::BidirectionalGraphConcept; - using boost::concepts::AdjacencyGraphConcept; - using boost::concepts::VertexListGraphConcept; - using boost::concepts::EdgeListGraphConcept; - using boost::concepts::VertexAndEdgeListGraphConcept; - using boost::concepts::EdgeMutableGraphConcept; - using boost::concepts::VertexMutableGraphConcept; - using boost::concepts::MutableGraphConcept; - using boost::concepts::MutableIncidenceGraphConcept; - using boost::concepts::MutableBidirectionalGraphConcept; - using boost::concepts::MutableEdgeListGraphConcept; - using boost::concepts::VertexMutablePropertyGraphConcept; - using boost::concepts::EdgeMutablePropertyGraphConcept; - using boost::concepts::AdjacencyMatrixConcept; - using boost::concepts::ReadablePropertyGraphConcept; - using boost::concepts::PropertyGraphConcept; - using boost::concepts::LvaluePropertyGraphConcept; - using boost::concepts::BufferConcept; - using boost::concepts::ColorValueConcept; - using boost::concepts::BasicMatrixConcept; -} // namespace boost + BOOST_CONCEPT_USAGE(AdjacencyGraph) { + BOOST_CONCEPT_ASSERT((MultiPassInputIterator)); + BOOST_CONCEPT_ASSERT((Convertible)); + p = adjacent_vertices(v, g); + v = *p.first; + const_constraints(g); + } + void const_constraints(const G& cg) { + p = adjacent_vertices(v, cg); + } + std::pair p; + typename graph_traits::vertex_descriptor v; + G g; + }; + + BOOST_concept(VertexListGraph,(G)) + : Graph + { + typedef typename graph_traits::vertex_iterator vertex_iterator; + typedef typename graph_traits::vertices_size_type vertices_size_type; + typedef typename graph_traits::traversal_category + traversal_category; + + BOOST_CONCEPT_USAGE(VertexListGraph) { + BOOST_CONCEPT_ASSERT((MultiPassInputIterator)); + BOOST_CONCEPT_ASSERT((Convertible)); + +#ifdef BOOST_VECTOR_AS_GRAPH_GRAPH_ADL_HACK + // dwa 2003/7/11 -- This clearly shouldn't be necessary, but if + // you want to use vector_as_graph, it is! I'm sure the graph + // library leaves these out all over the place. Probably a + // redesign involving specializing a template with a static + // member function is in order :( + using boost::vertices; +#endif + p = vertices(g); + v = *p.first; + const_constraints(g); + } + void const_constraints(const G& cg) { +#ifdef BOOST_VECTOR_AS_GRAPH_GRAPH_ADL_HACK + // dwa 2003/7/11 -- This clearly shouldn't be necessary, but if + // you want to use vector_as_graph, it is! I'm sure the graph + // library leaves these out all over the place. Probably a + // redesign involving specializing a template with a static + // member function is in order :( + using boost::vertices; +#endif + + p = vertices(cg); + v = *p.first; + V = num_vertices(cg); + } + std::pair p; + typename graph_traits::vertex_descriptor v; + G g; + vertices_size_type V; + }; + + BOOST_concept(EdgeListGraph,(G)) + : Graph + { + typedef typename graph_traits::edge_descriptor edge_descriptor; + typedef typename graph_traits::edge_iterator edge_iterator; + typedef typename graph_traits::edges_size_type edges_size_type; + typedef typename graph_traits::traversal_category + traversal_category; + + BOOST_CONCEPT_USAGE(EdgeListGraph) { + BOOST_CONCEPT_ASSERT((MultiPassInputIterator)); + BOOST_CONCEPT_ASSERT((DefaultConstructible)); + BOOST_CONCEPT_ASSERT((EqualityComparable)); + BOOST_CONCEPT_ASSERT((Assignable)); + BOOST_CONCEPT_ASSERT((Convertible)); + + p = edges(g); + e = *p.first; + u = source(e, g); + v = target(e, g); + const_constraints(g); + } + void const_constraints(const G& cg) { + p = edges(cg); + E = num_edges(cg); + e = *p.first; + u = source(e, cg); + v = target(e, cg); + } + std::pair p; + typename graph_traits::vertex_descriptor u, v; + typename graph_traits::edge_descriptor e; + edges_size_type E; + G g; + }; + + BOOST_concept(VertexAndEdgeListGraph,(G)) + : VertexListGraph + , EdgeListGraph + { + }; + + // Where to put the requirement for this constructor? + // G g(n_vertices); + // Not in mutable graph, then LEDA graph's can't be models of + // MutableGraph. + BOOST_concept(EdgeMutableGraph,(G)) + { + typedef typename graph_traits::edge_descriptor edge_descriptor; + + BOOST_CONCEPT_USAGE(EdgeMutableGraph) { + p = add_edge(u, v, g); + remove_edge(u, v, g); + remove_edge(e, g); + clear_vertex(v, g); + } + G g; + edge_descriptor e; + std::pair p; + typename graph_traits::vertex_descriptor u, v; + }; + + BOOST_concept(VertexMutableGraph,(G)) + { + + BOOST_CONCEPT_USAGE(VertexMutableGraph) { + v = add_vertex(g); + remove_vertex(v, g); + } + G g; + typename graph_traits::vertex_descriptor u, v; + }; + + BOOST_concept(MutableGraph,(G)) + : EdgeMutableGraph + , VertexMutableGraph + { + }; + + template + struct dummy_edge_predicate { + bool operator()(const edge_descriptor&) const { + return false; + } + }; + + BOOST_concept(MutableIncidenceGraph,(G)) + : MutableGraph + { + BOOST_CONCEPT_USAGE(MutableIncidenceGraph) { + remove_edge(iter, g); + remove_out_edge_if(u, p, g); + } + G g; + typedef typename graph_traits::edge_descriptor edge_descriptor; + dummy_edge_predicate p; + typename boost::graph_traits::vertex_descriptor u; + typename boost::graph_traits::out_edge_iterator iter; + }; + + BOOST_concept(MutableBidirectionalGraph,(G)) + : MutableIncidenceGraph + { + BOOST_CONCEPT_USAGE(MutableBidirectionalGraph) + { + remove_in_edge_if(u, p, g); + } + G g; + typedef typename graph_traits::edge_descriptor edge_descriptor; + dummy_edge_predicate p; + typename boost::graph_traits::vertex_descriptor u; + }; + + BOOST_concept(MutableEdgeListGraph,(G)) + : EdgeMutableGraph + { + BOOST_CONCEPT_USAGE(MutableEdgeListGraph) { + remove_edge_if(p, g); + } + G g; + typedef typename graph_traits::edge_descriptor edge_descriptor; + dummy_edge_predicate p; + }; + + BOOST_concept(VertexMutablePropertyGraph,(G)) + : VertexMutableGraph + { + BOOST_CONCEPT_USAGE(VertexMutablePropertyGraph) { + v = add_vertex(vp, g); + } + G g; + typename graph_traits::vertex_descriptor v; + typename vertex_property::type vp; + }; + + BOOST_concept(EdgeMutablePropertyGraph,(G)) + : EdgeMutableGraph + { + typedef typename graph_traits::edge_descriptor edge_descriptor; + + BOOST_CONCEPT_USAGE(EdgeMutablePropertyGraph) { + p = add_edge(u, v, ep, g); + } + G g; + std::pair p; + typename graph_traits::vertex_descriptor u, v; + typename edge_property::type ep; + }; + + BOOST_concept(AdjacencyMatrix,(G)) + : Graph + { + typedef typename graph_traits::edge_descriptor edge_descriptor; + + BOOST_CONCEPT_USAGE(AdjacencyMatrix) { + p = edge(u, v, g); + const_constraints(g); + } + void const_constraints(const G& cg) { + p = edge(u, v, cg); + } + typename graph_traits::vertex_descriptor u, v; + std::pair p; + G g; + }; + + BOOST_concept(ReadablePropertyGraph,(G)(X)(Property)) + : Graph + { + typedef typename property_map::const_type const_Map; + + BOOST_CONCEPT_USAGE(ReadablePropertyGraph) + { + BOOST_CONCEPT_ASSERT((ReadablePropertyMapConcept)); + + const_constraints(g); + } + void const_constraints(const G& cg) { + const_Map pmap = get(Property(), cg); + pval = get(Property(), cg, x); + ignore_unused_variable_warning(pmap); + } + G g; + X x; + typename property_traits::value_type pval; + }; + + BOOST_concept(PropertyGraph,(G)(X)(Property)) + : ReadablePropertyGraph + { + typedef typename property_map::type Map; + BOOST_CONCEPT_USAGE(PropertyGraph) { + BOOST_CONCEPT_ASSERT((ReadWritePropertyMapConcept)); + + Map pmap = get(Property(), g); + pval = get(Property(), g, x); + put(Property(), g, x, pval); + ignore_unused_variable_warning(pmap); + } + G g; + X x; + typename property_traits::value_type pval; + }; + + BOOST_concept(LvaluePropertyGraph,(G)(X)(Property)) + : ReadablePropertyGraph + { + typedef typename property_map::type Map; + typedef typename property_map::const_type const_Map; + + BOOST_CONCEPT_USAGE(LvaluePropertyGraph) { + BOOST_CONCEPT_ASSERT((LvaluePropertyMapConcept)); + + pval = get(Property(), g, x); + put(Property(), g, x, pval); + } + G g; + X x; + typename property_traits::value_type pval; + }; + + // The *IndexGraph concepts are "semantic" graph concpepts. These can be + // applied to describe any graph that has an index map that can be accessed + // using the get(*_index, g) method. For example, adjacency lists with + // VertexSet == vecS are implicitly models of this concept. + // + // NOTE: We could require an associated type vertex_index_type, but that + // would mean propagating that type name into graph_traits and all of the + // other graph implementations. Much easier to simply call it unsigned. + + BOOST_concept(VertexIndexGraph,(Graph)) + { + BOOST_CONCEPT_USAGE(VertexIndexGraph) + { + typedef typename graph_traits::vertex_descriptor Vertex; + typedef typename property_map::type Map; + typedef unsigned Index; // This could be Graph::vertex_index_type + Map m = get(vertex_index, g); + Index x = get(vertex_index, g, Vertex()); + ignore_unused_variable_warning(x); + + // This is relaxed + renumber_vertex_indices(g); + + const_constraints(g); + } + void const_constraints(const Graph& g) + { + typedef typename property_map::const_type Map; + Map m = get(vertex_index, g); + ignore_unused_variable_warning(m); + } + private: + Graph g; + }; + + BOOST_concept(EdgeIndexGraph,(Graph)) + { + BOOST_CONCEPT_USAGE(EdgeIndexGraph) + { + typedef typename graph_traits::edge_descriptor Edge; + typedef typename property_map::type Map; + typedef unsigned Index; // This could be Graph::vertex_index_type + Map m = get(edge_index, g); + Index x = get(edge_index, g, Edge()); + ignore_unused_variable_warning(x); + + // This is relaxed + renumber_edge_indices(g); + + const_constraints(g); + } + void const_constraints(const Graph& g) + { + typedef typename property_map::const_type Map; + Map m = get(edge_index, g); + ignore_unused_variable_warning(m); + } + private: + Graph g; + }; + + // This needs to move out of the graph library + BOOST_concept(Buffer,(B)) + { + BOOST_CONCEPT_USAGE(Buffer) { + b.push(t); + b.pop(); + typename B::value_type& v = b.top(); + const_constraints(b); + ignore_unused_variable_warning(v); + } + void const_constraints(const B& cb) { + const typename B::value_type& v = cb.top(); + n = cb.size(); + bool e = cb.empty(); + ignore_unused_variable_warning(v); + ignore_unused_variable_warning(e); + } + typename B::size_type n; + typename B::value_type t; + B b; + }; + + BOOST_concept(ColorValue,(C)) + : EqualityComparable + , DefaultConstructible + { + BOOST_CONCEPT_USAGE(ColorValue) { + c = color_traits::white(); + c = color_traits::gray(); + c = color_traits::black(); + } + C c; + }; + + BOOST_concept(BasicMatrix,(M)(I)(V)) + { + BOOST_CONCEPT_USAGE(BasicMatrix) { + V& elt = A[i][j]; + const_constraints(A); + ignore_unused_variable_warning(elt); + } + void const_constraints(const M& cA) { + const V& elt = cA[i][j]; + ignore_unused_variable_warning(elt); + } + M A; + I i, j; + }; + + // The following concepts describe aspects of numberic values and measure + // functions. We're extending the notion of numeric values to include + // emulation for zero and infinity. + + BOOST_concept(NumericValue,(Numeric)) + { + BOOST_CONCEPT_USAGE(NumericValue) + { + function_requires< DefaultConstructible >(); + function_requires< CopyConstructible >(); + numeric_values::zero(); + numeric_values::infinity(); + } + }; + + BOOST_concept(DegreeMeasure,(Measure)(Graph)) + { + BOOST_CONCEPT_USAGE(DegreeMeasure) + { + typedef typename Measure::degree_type Degree; + typedef typename Measure::vertex_type Vertex; + + Degree d = m(Vertex(), g); + ignore_unused_variable_warning(d); + } + private: + Measure m; + Graph g; + }; + + BOOST_concept(DistanceMeasure,(Measure)(Graph)) + { + BOOST_CONCEPT_USAGE(DistanceMeasure) + { + typedef typename Measure::distance_type Distance; + typedef typename Measure::result_type Result; + Result r = m(Distance(), g); + ignore_unused_variable_warning(r); + } + private: + Measure m; + Graph g; + }; + +} /* namespace concepts */ + +using boost::concepts::MultiPassInputIteratorConcept; + +// Graph concepts +using boost::concepts::GraphConcept; +using boost::concepts::IncidenceGraphConcept; +using boost::concepts::BidirectionalGraphConcept; +using boost::concepts::AdjacencyGraphConcept; +using boost::concepts::VertexListGraphConcept; +using boost::concepts::EdgeListGraphConcept; +using boost::concepts::VertexAndEdgeListGraphConcept; +using boost::concepts::EdgeMutableGraphConcept; +using boost::concepts::VertexMutableGraphConcept; +using boost::concepts::MutableGraphConcept; +using boost::concepts::MutableIncidenceGraphConcept; +using boost::concepts::MutableBidirectionalGraphConcept; +using boost::concepts::MutableEdgeListGraphConcept; +using boost::concepts::VertexMutablePropertyGraphConcept; +using boost::concepts::EdgeMutablePropertyGraphConcept; +using boost::concepts::AdjacencyMatrixConcept; +using boost::concepts::ReadablePropertyGraphConcept; +using boost::concepts::PropertyGraphConcept; +using boost::concepts::LvaluePropertyGraphConcept; +using boost::concepts::VertexIndexGraphConcept; +using boost::concepts::EdgeIndexGraphConcept; + +// Utility concepts +using boost::concepts::BufferConcept; +using boost::concepts::ColorValueConcept; +using boost::concepts::BasicMatrixConcept; +using boost::concepts::NumericValueConcept; +using boost::concepts::DistanceMeasureConcept; +using boost::concepts::DegreeMeasureConcept; + + +} /* namespace boost */ #include #endif /* BOOST_GRAPH_CONCEPTS_H */ diff --git a/include/boost/graph/numeric_values.hpp b/include/boost/graph/numeric_values.hpp new file mode 100644 index 00000000..84d170cc --- /dev/null +++ b/include/boost/graph/numeric_values.hpp @@ -0,0 +1,52 @@ +// (C) Copyright 2007-2009 Andrew Sutton +// +// 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_NUMERIC_VALUES_HPP +#define BOOST_GRAPH_NUMERIC_VALUES_HPP + +#include + +namespace boost +{ + +#define BOOST_GRAPH_SPECIALIZE_NUMERIC_FLOAT(type) \ + template <> struct numeric_values { \ + typedef type value_type; \ + static type zero() { return 0.0; } \ + static type infinity() { return std::numeric_limits::infinity(); } \ + }; + + /** + * This generic type reports various numeric values for some type. In the + * general case, numeric values simply treat their maximum value as infinity + * and the default-constructed value as 0. + * + * Specializations of this template can redefine the notions of zero and + * infinity for various types. For example, the class is specialized for + * floating point types to use the built in notion of infinity. + */ + template + struct numeric_values + { + typedef T value_type; + + static T zero() + { return T(); } + + static T infinity() + { return std::numeric_limits::max(); } + }; + + // Specializations for floating point types refer to 0.0 and their infinity + // value defined by numeric_limits. + BOOST_GRAPH_SPECIALIZE_NUMERIC_FLOAT(float); + BOOST_GRAPH_SPECIALIZE_NUMERIC_FLOAT(double); + BOOST_GRAPH_SPECIALIZE_NUMERIC_FLOAT(long double); + +#undef BOOST_GRAPH_SPECIALIZE_NUMERIC_VALUE +} + +#endif From 77d5bf7b802b7142646eeb43e5618766f83225ea Mon Sep 17 00:00:00 2001 From: Andrew Sutton Date: Sun, 8 Feb 2009 14:25:32 +0000 Subject: [PATCH 083/224] Integrating SOC 2007 code [SVN r51092] --- test/Jamfile.v2 | 2 +- test/test_graphs.cpp | 49 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 50 insertions(+), 1 deletion(-) create mode 100644 test/test_graphs.cpp diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 114cc03b..64976454 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -94,7 +94,7 @@ test-suite graph_test : [ run metric_tsp_approx.cpp : metric_tsp_approx.txt ] [ compile dimacs.cpp ] - [ run undirected_graph.cpp ] + [ run test_graphs.cpp ] $(optional_tests) ; diff --git a/test/test_graphs.cpp b/test/test_graphs.cpp new file mode 100644 index 00000000..8333db76 --- /dev/null +++ b/test/test_graphs.cpp @@ -0,0 +1,49 @@ + +#include + +#include +#include +#include + +using namespace std; +using namespace boost; + +struct node +{ + node() : n() { } + node(int n) : n(n) { } + + bool operator==(node const& x) const { return n == x.n; } + bool operator<(node const& x) const { return n < x.n; } + + int n; +}; + +struct arc +{ + arc() : n() { } + arc(int n) : n(n) { } + + bool operator==(arc const& x) const { return n == x.n; } + + int n; +}; + +// TODO: Finish implementing this test. Actually, generalize the test so that +// it works for lots of different graph types. + +template +void test() +{ + typedef typename Graph::vertex_descriptor Vertex; + Graph g; + BOOST_ASSERT(num_vertices(g) == 0); + +} + +int main() +{ + test< undirected_graph >(); + test< directed_graph >(); +} + From aed5fa9949d1db3fb0e4b2d7015e499282821f3a Mon Sep 17 00:00:00 2001 From: Andrew Sutton Date: Sun, 8 Feb 2009 14:51:58 +0000 Subject: [PATCH 084/224] Importing all_cliques, all_cycles algorithms [SVN r51094] --- .../boost/graph/bron_kerbosch_all_cliques.hpp | 309 +++++++++++++++ include/boost/graph/directed_graph.hpp | 23 +- include/boost/graph/tiernan_all_cycles.hpp | 373 ++++++++++++++++++ include/boost/graph/undirected_graph.hpp | 20 +- 4 files changed, 709 insertions(+), 16 deletions(-) create mode 100644 include/boost/graph/bron_kerbosch_all_cliques.hpp create mode 100644 include/boost/graph/tiernan_all_cycles.hpp diff --git a/include/boost/graph/bron_kerbosch_all_cliques.hpp b/include/boost/graph/bron_kerbosch_all_cliques.hpp new file mode 100644 index 00000000..b9d4f016 --- /dev/null +++ b/include/boost/graph/bron_kerbosch_all_cliques.hpp @@ -0,0 +1,309 @@ +// (C) Copyright 2007-2009 Andrew Sutton +// +// 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_CLIQUE_HXX +#define BOOST_GRAPH_CLIQUE_HXX + +#include +#include + +#include + +#include +namespace boost { + namespace concepts { + BOOST_concept(CliqueVisitor,(Visitor)(Clique)(Graph)) + { + BOOST_CONCEPT_USAGE(CliqueVisitor) + { + vis.clique(k, g); + } + private: + Visitor vis; + Graph g; + Clique k; + }; + } /* namespace concepts */ +using concepts::CliqueVisitorConcept; +} /* namespace boost */ +#include + +namespace boost +{ +// The algorithm implemented in this paper is based on the so-called +// Algorithm 457, published as: +// +// @article{362367, +// author = {Coen Bron and Joep Kerbosch}, +// title = {Algorithm 457: finding all cliques of an undirected graph}, +// journal = {Communications of the ACM}, +// volume = {16}, +// number = {9}, +// year = {1973}, +// issn = {0001-0782}, +// pages = {575--577}, +// doi = {http://doi.acm.org/10.1145/362342.362367}, +// publisher = {ACM Press}, +// address = {New York, NY, USA}, +// } +// +// Sort of. This implementation is adapted from the 1st version of the +// algorithm and does not implement the candidate selection optimization +// described as published - it could, it just doesn't yet. +// +// The algorithm is given as proportional to (3.14)^(n/3) power. This is +// not the same as O(...), but based on time measures and approximation. +// +// Unfortunately, this implementation may be less efficient on non- +// AdjacencyMatrix modeled graphs due to the non-constant implementation +// of the edge(u,v,g) functions. +// +// TODO: It might be worthwhile to provide functionality for passing +// a connectivity matrix to improve the efficiency of those lookups +// when needed. This could simply be passed as a BooleanMatrix +// s.t. edge(u,v,B) returns true or false. This could easily be +// abstracted for adjacency matricies. +// +// The following paper is interesting for a number of reasons. First, +// it lists a number of other such algorithms and second, it describes +// a new algorithm (that does not appear to require the edge(u,v,g) +// function and appears fairly efficient. It is probably worth investigating. +// +// @article{DBLP:journals/tcs/TomitaTT06, +// author = {Etsuji Tomita and Akira Tanaka and Haruhisa Takahashi}, +// title = {The worst-case time complexity for generating all maximal cliques and computational experiments}, +// journal = {Theor. Comput. Sci.}, +// volume = {363}, +// number = {1}, +// year = {2006}, +// pages = {28-42} +// ee = {http://dx.doi.org/10.1016/j.tcs.2006.06.015} +// } + +/** + * The default clique_visitor supplies an empty visitation function. + */ +struct clique_visitor +{ + template + void clique(const VertexSet&, Graph&) + { } +}; + +/** + * The max_clique_visitor records the size of the maximum clique (but not the + * clique itself). + */ +struct max_clique_visitor +{ + max_clique_visitor(std::size_t& max) + : maximum(max) + { } + + template + inline void clique(const Clique& p, const Graph& g) + { + maximum = std::max(maximum, p.size()); + } + std::size_t& maximum; +}; + +inline max_clique_visitor find_max_clique(std::size_t& max) +{ return max_clique_visitor(max); } + +namespace detail +{ + template + inline bool + is_connected_to_clique(const Graph& g, + typename graph_traits::vertex_descriptor u, + typename graph_traits::vertex_descriptor v, + typename graph_traits::undirected_category) + { + function_requires< AdjacencyMatrixConcept >(); + + return edge(u, v, g).second; + } + + template + inline bool + is_connected_to_clique(const Graph& g, + typename graph_traits::vertex_descriptor u, + typename graph_traits::vertex_descriptor v, + typename graph_traits::directed_category) + { + function_requires< AdjacencyMatrixConcept >(); + // Note that this could alternate between using an || to determine + // full connectivity. I believe that this should produce strongly + // connected components. Note that using && instead of || will + // change the results to a fully connected subgraph (i.e., symmetric + // edges between all vertices s.t., if a->b, then b->a. + return edge(u, v, g).second && edge(v, u, g).second; + } + + template + inline void + filter_unconnected_vertices(const Graph& g, + typename graph_traits::vertex_descriptor v, + const Container& in, + Container& out) + { + function_requires< GraphConcept >(); + + typename graph_traits::directed_category cat; + typename Container::const_iterator i, end = in.end(); + for(i = in.begin(); i != end; ++i) { + if(is_connected_to_clique(g, v, *i, cat)) { + out.push_back(*i); + } + } + } + + template < + typename Graph, + typename Clique, // compsub type + typename Container, // candidates/not type + typename Visitor> + void extend_clique(const Graph& g, + Clique& clique, + Container& cands, + Container& nots, + Visitor vis, + std::size_t min) + { + function_requires< GraphConcept >(); + function_requires< CliqueVisitorConcept >(); + typedef typename graph_traits::vertex_descriptor Vertex; + + // Is there vertex in nots that is connected to all vertices + // in the candidate set? If so, no clique can ever be found. + // This could be broken out into a separate function. + { + typename Container::iterator ni, nend = nots.end(); + typename Container::iterator ci, cend = cands.end(); + for(ni = nots.begin(); ni != nend; ++ni) { + for(ci = cands.begin(); ci != cend; ++ci) { + // if we don't find an edge, then we're okay. + if(!edge(*ni, *ci, g).second) break; + } + // if we iterated all the way to the end, then *ni + // is connected to all *ci + if(ci == cend) break; + } + // if we broke early, we found *ni connected to all *ci + if(ni != nend) return; + } + + // TODO: the original algorithm 457 describes an alternative + // (albeit really complicated) mechanism for selecting candidates. + // The given optimizaiton seeks to bring about the above + // condition sooner (i.e., there is a vertex in the not set + // that is connected to all candidates). unfortunately, the + // method they give for doing this is fairly unclear. + + // basically, for every vertex in not, we should know how many + // vertices it is disconnected from in the candidate set. if + // we fix some vertex in the not set, then we want to keep + // choosing vertices that are not connected to that fixed vertex. + // apparently, by selecting fix point with the minimum number + // of disconnections (i.e., the maximum number of connections + // within the candidate set), then the previous condition wil + // be reached sooner. + + // there's some other stuff about using the number of disconnects + // as a counter, but i'm jot really sure i followed it. + + // TODO: If we min-sized cliques to visit, then theoretically, we + // should be able to stop recursing if the clique falls below that + // size - maybe? + + // otherwise, iterate over candidates and and test + // for maxmimal cliquiness. + typename Container::iterator i, j, end = cands.end(); + for(i = cands.begin(); i != cands.end(); ) { + Vertex candidate = *i; + + // add the candidate to the clique (keeping the iterator!) + // typename Clique::iterator ci = clique.insert(clique.end(), candidate); + clique.push_back(candidate); + + // remove it from the candidate set + i = cands.erase(i); + + // build new candidate and not sets by removing all vertices + // that are not connected to the current candidate vertex. + // these actually invert the operation, adding them to the new + // sets if the vertices are connected. its semantically the same. + Container new_cands, new_nots; + filter_unconnected_vertices(g, candidate, cands, new_cands); + filter_unconnected_vertices(g, candidate, nots, new_nots); + + if(new_cands.empty() && new_nots.empty()) { + // our current clique is maximal since there's nothing + // that's connected that we haven't already visited. If + // the clique is below our radar, then we won't visit it. + if(clique.size() >= min) { + vis.clique(clique, g); + } + } + else { + // recurse to explore the new candidates + extend_clique(g, clique, new_cands, new_nots, vis, min); + } + + // we're done with this vertex, so we need to move it + // to the nots, and remove the candidate from the clique. + nots.push_back(candidate); + clique.pop_back(); + } + } +} /* namespace detail */ + +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 + 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 >(); + + // 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. + + VertexIterator i, end; + tie(i, end) = vertices(g); + VertexSet cands(i, end); // start with all vertices as candidates + VertexSet nots; // start with no vertices visited + + Clique clique; // the first clique is an empty vertex set + detail::extend_clique(g, clique, cands, nots, vis, min); +} + +// NOTE: By default the minimum number of vertices per clique is set at 2 +// because singleton cliques aren't really very interesting. +template +inline void +bron_kerbosch_all_cliques(const Graph& g, Visitor vis) +{ bron_kerbosch_all_cliques(g, vis, 2); } + +template +inline std::size_t +bron_kerbosch_clique_number(const Graph& g) +{ + std::size_t ret = 0; + bron_kerbosch_all_cliques(g, find_max_clique(ret)); + return ret; +} + +} /* namespace boost */ + +#endif diff --git a/include/boost/graph/directed_graph.hpp b/include/boost/graph/directed_graph.hpp index 1b71f523..20eec653 100644 --- a/include/boost/graph/directed_graph.hpp +++ b/include/boost/graph/directed_graph.hpp @@ -16,21 +16,20 @@ namespace boost struct directed_graph_tag { }; /** -* 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 -* EdgeIndexGraph concepts. The graph is also fully mutable, supporting -* both insertions and removals. -* -* @note Special care must be taken when removing vertices or edges since -* those operations can invalidate the numbering of vertices. -*/ + * 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 + * EdgeIndexGraph concepts. The graph is also fully mutable, supporting + * both insertions and removals of vertices and edges. + * + * @note Special care must be taken when removing vertices or edges since + * those operations can invalidate the numbering of vertices. + */ template < typename VertexProperty = no_property, typename EdgeProperty = no_property, - typename GraphProperty = no_property -> + typename GraphProperty = no_property> class directed_graph { // Wrap the user-specified properties with an index. diff --git a/include/boost/graph/tiernan_all_cycles.hpp b/include/boost/graph/tiernan_all_cycles.hpp new file mode 100644 index 00000000..5465ba68 --- /dev/null +++ b/include/boost/graph/tiernan_all_cycles.hpp @@ -0,0 +1,373 @@ +// (C) Copyright 2007-2009 Andrew Sutton +// +// 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_CYCLE_HXX +#define BOOST_GRAPH_CYCLE_HXX + +#include + +#include +#include +#include + +#include +namespace boost { + namespace concepts { + BOOST_concept(CycleVisitor,(Visitor)(Path)(Graph)) + { + BOOST_CONCEPT_USAGE(CycleVisitor) + { + vis.cycle(p, g); + } + private: + Visitor vis; + Graph g; + Path p; + }; + } /* namespace concepts */ +using concepts::CycleVisitorConcept; +} /* namespace boost */ +#include + + +namespace boost +{ + +// The implementation of this algorithm is a reproduction of the Teirnan +// approach for directed graphs: bibtex follows +// +// @article{362819, +// author = {James C. Tiernan}, +// title = {An efficient search algorithm to find the elementary circuits of a graph}, +// journal = {Commun. ACM}, +// volume = {13}, +// number = {12}, +// year = {1970}, +// issn = {0001-0782}, +// pages = {722--726}, +// doi = {http://doi.acm.org/10.1145/362814.362819}, +// publisher = {ACM Press}, +// address = {New York, NY, USA}, +// } +// +// It should be pointed out that the author does not provide a complete analysis for +// either time or space. This is in part, due to the fact that it's a fairly input +// sensitive problem related to the density and construction of the graph, not just +// its size. +// +// I've also taken some liberties with the interpretation of the algorithm - I've +// basically modernized it to use real data structures (no more arrays and matrices). +// Oh... and there's explicit control structures - not just gotos. +// +// The problem is definitely NP-complete, an an unbounded implementation of this +// will probably run for quite a while on a large graph. The conclusions +// of this paper also reference a Paton algorithm for undirected graphs as being +// much more efficient (apparently based on spanning trees). Although not implemented, +// it can be found here: +// +// @article{363232, +// author = {Keith Paton}, +// title = {An algorithm for finding a fundamental set of cycles of a graph}, +// journal = {Commun. ACM}, +// volume = {12}, +// number = {9}, +// year = {1969}, +// issn = {0001-0782}, +// pages = {514--518}, +// doi = {http://doi.acm.org/10.1145/363219.363232}, +// publisher = {ACM Press}, +// address = {New York, NY, USA}, +// } + +/** + * The default cycle visitor providse an empty visit function for cycle + * visitors. + */ +struct cycle_visitor +{ + template + inline void cycle(const Path& p, const Graph& g) + { } +}; + +/** + * The min_max_cycle_visitor simultaneously records the minimum and maximum + * cycles in a graph. + */ +struct min_max_cycle_visitor +{ + min_max_cycle_visitor(std::size_t& min, std::size_t& max) + : minimum(min), maximum(max) + { } + + template + inline void cycle(const Path& p, const Graph& g) + { + std::size_t len = p.size(); + minimum = std::min(minimum, len); + maximum = std::max(maximum, len); + } + std::size_t& minimum; + std::size_t& maximum; +}; + +inline min_max_cycle_visitor +find_min_max_cycle(std::size_t& min, std::size_t& max) +{ return min_max_cycle_visitor(min, max); } + +namespace detail +{ + template + inline bool + is_vertex_in_path(const Graph&, + typename graph_traits::vertex_descriptor v, + const Path& p) + { + return (std::find(p.begin(), p.end(), v) != p.end()); + } + + template + inline bool + is_path_closed(const Graph& g, + typename graph_traits::vertex_descriptor u, + typename graph_traits::vertex_descriptor v, + const ClosedMatrix& closed) + { + // the path from u to v is closed if v can be found in the list + // of closed vertices associated with u. + typedef typename ClosedMatrix::const_reference Row; + Row r = closed[get(vertex_index, g, u)]; + if(find(r.begin(), r.end(), v) != r.end()) { + return true; + } + return false; + } + + template + inline bool + can_extend_path(const Graph& g, + typename graph_traits::edge_descriptor e, + const Path& p, + const ClosedMatrix& m) + { + function_requires< IncidenceGraphConcept >(); + function_requires< VertexIndexGraphConcept >(); + typedef typename graph_traits::vertex_descriptor Vertex; + + // get the vertices in question + Vertex + u = source(e, g), + v = target(e, g); + + // conditions for allowing a traversal along this edge are: + // 1. the index of v must be greater than that at which the + // the path is rooted (p.front()). + // 2. the vertex v cannot already be in the path + // 3. the vertex v cannot be closed to the vertex u + + bool indices = get(vertex_index, g, p.front()) < get(vertex_index, g, v); + bool path = !is_vertex_in_path(g, v, p); + bool closed = !is_path_closed(g, u, v, m); + return indices && path && closed; + } + + template + inline bool + can_wrap_path(const Graph& g, const Path& p) + { + function_requires< IncidenceGraphConcept >(); + typedef typename graph_traits::vertex_descriptor Vertex; + typedef typename graph_traits::out_edge_iterator OutIterator; + + // iterate over the out-edges of the back, looking for the + // front of the path. also, we can't travel along the same + // edge that we did on the way here, but we don't quite have the + // stringent requirements that we do in can_extend_path(). + Vertex + u = p.back(), + v = p.front(); + OutIterator i, end; + for(tie(i, end) = out_edges(u, g); i != end; ++i) { + if((target(*i, g) == v)) { + return true; + } + } + return false; + } + + template + inline typename graph_traits::vertex_descriptor + extend_path(const Graph& g, + Path& p, + ClosedMatrix& closed) + { + function_requires< 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 + Vertex u = p.back(); + Vertex ret = graph_traits::null_vertex(); + + // AdjacencyIterator i, end; + OutIterator i, end; + for(tie(i, end) = out_edges(u, g); i != end; ++i) { + Vertex v = target(*i, g); + + // if we can actually extend along this edge, + // then that's what we want to do + if(can_extend_path(g, *i, p, closed)) { + p.push_back(v); // add the vertex to the path + ret = v; + break; + } + } + return ret; + } + + template + inline bool + exhaust_paths(const Graph& g, Path& p, ClosedMatrix& closed) + { + function_requires< GraphConcept >(); + typedef typename graph_traits::vertex_descriptor Vertex; + + // if there's more than one vertex in the path, this closes + // of some possible routes and returns true. otherwise, if there's + // only one vertex left, the vertex has been used up + if(p.size() > 1) { + // get the last and second to last vertices, popping the last + // vertex off the path + Vertex last, prev; + last = p.back(); + p.pop_back(); + prev = p.back(); + + // reset the closure for the last vertex of the path and + // indicate that the last vertex in p is now closed to + // the next-to-last vertex in p + closed[get(vertex_index, g, last)].clear(); + closed[get(vertex_index, g, prev)].push_back(last); + return true; + } + else { + return false; + } + } + + template + inline void + all_cycles_from_vertex(const Graph& g, + typename graph_traits::vertex_descriptor v, + Visitor vis, + std::size_t minlen, + std::size_t maxlen) + { + function_requires< VertexListGraphConcept >(); + typedef typename graph_traits::vertex_descriptor Vertex; + typedef std::vector Path; + function_requires< CycleVisitorConcept >(); + typedef std::vector VertexList; + typedef std::vector ClosedMatrix; + + Path p; + ClosedMatrix closed(num_vertices(g), VertexList()); + Vertex null = graph_traits::null_vertex(); + + // each path investigation starts at the ith vertex + p.push_back(v); + + while(1) { + // extend the path until we've reached the end or the + // maxlen-sized cycle + Vertex j = null; + while(((j = detail::extend_path(g, p, closed)) != null) + && (p.size() < maxlen)) + ; // empty loop + + // if we're done extending the path and there's an edge + // connecting the back to the front, then we should have + // a cycle. + if(detail::can_wrap_path(g, p) && p.size() >= minlen) { + vis.cycle(p, g); + } + + if(!detail::exhaust_paths(g, p, closed)) { + break; + } + } + } + + // Select the minimum allowable length of a cycle based on the directedness + // of the graph - 2 for directed, 3 for undirected. + template struct min_cycles { enum { value = 2 }; }; + template <> struct min_cycles { enum { value = 3 }; }; +} /* namespace detail */ + +template +inline void +tiernan_all_cycles(const Graph& g, + Visitor vis, + std::size_t minlen, + std::size_t maxlen) +{ + function_requires< VertexListGraphConcept >(); + typedef typename graph_traits::vertex_iterator VertexIterator; + + VertexIterator i, end; + for(tie(i, end) = vertices(g); i != end; ++i) { + detail::all_cycles_from_vertex(g, *i, vis, minlen, maxlen); + } +} + +template +inline void +tiernan_all_cycles(const Graph& g, Visitor vis, std::size_t maxlen) +{ + typedef typename graph_traits::directed_category Dir; + tiernan_all_cycles(g, vis, detail::min_cycles
    ::value, maxlen); +} + +template +inline void +tiernan_all_cycles(const Graph& g, Visitor vis) +{ + typedef typename graph_traits::directed_category Dir; + tiernan_all_cycles(g, vis, detail::min_cycles::value, + std::numeric_limits::max()); +} + +template +inline std::pair +tiernan_girth_and_circumference(const Graph& g) +{ + std::size_t + min = std::numeric_limits::max(), + max = 0; + tiernan_all_cycles(g, find_min_max_cycle(min, max)); + + // if this is the case, the graph is acyclic... + if(max == 0) max = min; + + return std::make_pair(min, max); +} + +template +inline std::size_t +tiernan_girth(const Graph& g) +{ return tiernan_girth_and_circumference(g).first; } + +template +inline std::size_t +tiernan_circumference(const Graph& g) +{ return tiernan_girth_and_circumference(g).second; } + +} /* namespace boost */ + +#endif diff --git a/include/boost/graph/undirected_graph.hpp b/include/boost/graph/undirected_graph.hpp index b5261688..74f01a0c 100644 --- a/include/boost/graph/undirected_graph.hpp +++ b/include/boost/graph/undirected_graph.hpp @@ -13,11 +13,23 @@ namespace boost { - struct undirected_graph_tag { }; +struct undirected_graph_tag { }; - template +/** + * The undirected_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 VertexIndexGraph, and EdgeIndexGraph concepts. The + * graph is also fully mutable, supporting both insertions and removals of + * vertices and edges. + * + * @note Special care must be taken when removing vertices or edges since + * those operations can invalidate the numbering of vertices. + */ +template < + typename VertexProperty = no_property, + typename EdgeProperty = no_property, + typename GraphProperty = no_property> class undirected_graph { typedef property vertex_property; From 4f9ff683483a1ab9d0ab849e130ac0f2f9ae477d Mon Sep 17 00:00:00 2001 From: Andrew Sutton Date: Sun, 8 Feb 2009 14:52:35 +0000 Subject: [PATCH 085/224] Importing tests for all_cliques, all_cycles, and an eventual graph testing framework [SVN r51095] --- test/Jamfile.v2 | 7 ++- test/bron_kerbosch_all_cliques.cpp | 78 +++++++++++++++++++++++++++++ test/test_graphs.cpp | 1 - test/tiernan_all_cycles.cpp | 79 ++++++++++++++++++++++++++++++ 4 files changed, 163 insertions(+), 2 deletions(-) create mode 100644 test/bron_kerbosch_all_cliques.cpp create mode 100644 test/tiernan_all_cycles.cpp diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 64976454..181fc21f 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -21,6 +21,10 @@ if [ modules.peek : EXPAT_INCLUDE ] && [ modules.peek : EXPAT_LIBPATH ] } test-suite graph_test : + # test_graphs will eventually defined a framework for testing the structure + # and implementation of graph data structures and adaptors. + [ run test_graphs.cpp ] + [ run transitive_closure_test.cpp ] [ compile adj_list_cc.cpp ] @@ -93,8 +97,9 @@ test-suite graph_test : [ run is_straight_line_draw_test.cpp ] [ run metric_tsp_approx.cpp : metric_tsp_approx.txt ] [ compile dimacs.cpp ] + [ run bron_kerbosch_all_cliques.cpp ] + [ run tiernan_all_cycles.cpp ] - [ run test_graphs.cpp ] $(optional_tests) ; diff --git a/test/bron_kerbosch_all_cliques.cpp b/test/bron_kerbosch_all_cliques.cpp new file mode 100644 index 00000000..946f8432 --- /dev/null +++ b/test/bron_kerbosch_all_cliques.cpp @@ -0,0 +1,78 @@ +// (C) Copyright 2007-2009 Andrew Sutton +// +// 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 +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include + +using namespace std; +using namespace boost; + +// TODO: This is probably not a very good test. We should be able to define +// an identity test - something like find the clique of K5. + +struct clique_validator +{ + clique_validator() + { } + + template + inline void + clique(const Clique& c, Graph& g) + { + // Simply assert that each vertex in the clique is connected + // to all others in the clique. + typename Clique::const_iterator i, j, end = c.end(); + for(i = c.begin(); i != end; ++i) { + for(j = c.begin(); j != end; ++j) { + if(i != j) { + BOOST_ASSERT(edge(*i, *j, g).second); + } + } + } + } +}; + +template +void test() +{ + typedef erdos_renyi_iterator er; + + // Generate random graphs with 15 vertices and 15% probability + // of edge connection. + static const size_t N = 20; + static const float P = 0.1; + + boost::minstd_rand rng; + Graph g(er(rng, N, P), er(), N); + renumber_indices(g); + print_edges(g, get(vertex_index, g)); + + bron_kerbosch_all_cliques(g, clique_validator()); +} + +int +main(int argc, char *argv[]) +{ + typedef undirected_graph<> Graph; + typedef directed_graph<> DiGraph; + + std::cout << "*** undirected ***\n"; + test(); + + std::cout << "*** directed ***\n"; + test(); +} diff --git a/test/test_graphs.cpp b/test/test_graphs.cpp index 8333db76..5197d762 100644 --- a/test/test_graphs.cpp +++ b/test/test_graphs.cpp @@ -1,7 +1,6 @@ #include -#include #include #include diff --git a/test/tiernan_all_cycles.cpp b/test/tiernan_all_cycles.cpp new file mode 100644 index 00000000..3f3e96a6 --- /dev/null +++ b/test/tiernan_all_cycles.cpp @@ -0,0 +1,79 @@ +// (C) Copyright 2007-2009 Andrew Sutton +// +// 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 + +#include +#include +#include +#include +#include + +#include + +using namespace std; +using namespace boost; + +struct cycle_validator +{ + cycle_validator(size_t& c) + : cycles(c) + { } + + template + 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 + // 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); + } + + size_t& cycles; +}; + +template +void test() +{ + typedef erdos_renyi_iterator er; + + // Generate random graphs with 15 vertices and 15% probability + // of edge connection. + static const size_t N = 20; + static const float P = 0.1; + boost::minstd_rand rng; + + Graph g(er(rng, N, P), er(), N); + renumber_indices(g); + print_edges(g, get(vertex_index, g)); + + size_t cycles = 0; + cycle_validator vis(cycles); + tiernan_all_cycles(g, vis); + cout << "# cycles: " << vis.cycles << "\n"; +} + +int +main(int argc, char *argv[]) +{ + typedef undirected_graph<> Graph; + typedef directed_graph<> DiGraph; + + std::cout << "*** undirected ***\n"; + test(); + + std::cout << "*** directed ***\n"; + test(); +} From 6a7fc39328a89ce00e853d480779b559aa25dc91 Mon Sep 17 00:00:00 2001 From: Andrew Sutton Date: Sun, 8 Feb 2009 15:28:31 +0000 Subject: [PATCH 086/224] Importing exterior_property framework and associated property map helpers. Integrating closeness_centrality algorithm. [SVN r51097] --- .../boost/graph/bron_kerbosch_all_cliques.hpp | 4 +- include/boost/graph/closeness_centrality.hpp | 157 ++++++++++++++++++ include/boost/graph/detail/geodesic.hpp | 129 ++++++++++++++ include/boost/graph/detail/index.hpp | 74 +++++++++ include/boost/graph/exterior_property.hpp | 117 +++++++++++++ .../property_maps/constant_property_map.hpp | 59 +++++++ .../property_maps/container_property_map.hpp | 75 +++++++++ .../property_maps/matrix_property_map.hpp | 67 ++++++++ include/boost/graph/tiernan_all_cycles.hpp | 4 +- 9 files changed, 682 insertions(+), 4 deletions(-) create mode 100644 include/boost/graph/closeness_centrality.hpp create mode 100644 include/boost/graph/detail/geodesic.hpp create mode 100644 include/boost/graph/detail/index.hpp create mode 100644 include/boost/graph/exterior_property.hpp create mode 100644 include/boost/graph/property_maps/constant_property_map.hpp create mode 100644 include/boost/graph/property_maps/container_property_map.hpp create mode 100644 include/boost/graph/property_maps/matrix_property_map.hpp diff --git a/include/boost/graph/bron_kerbosch_all_cliques.hpp b/include/boost/graph/bron_kerbosch_all_cliques.hpp index b9d4f016..48579068 100644 --- a/include/boost/graph/bron_kerbosch_all_cliques.hpp +++ b/include/boost/graph/bron_kerbosch_all_cliques.hpp @@ -4,8 +4,8 @@ // 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_CLIQUE_HXX -#define BOOST_GRAPH_CLIQUE_HXX +#ifndef BOOST_GRAPH_CLIQUE_HPP +#define BOOST_GRAPH_CLIQUE_HPP #include #include diff --git a/include/boost/graph/closeness_centrality.hpp b/include/boost/graph/closeness_centrality.hpp new file mode 100644 index 00000000..77cea7b0 --- /dev/null +++ b/include/boost/graph/closeness_centrality.hpp @@ -0,0 +1,157 @@ +// (C) Copyright 2007-2009 Andrew Sutton +// +// 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_CLOSENESS_CENTRALITY_HPP +#define BOOST_GRAPH_CLOSENESS_CENTRALITY_HPP + +#include +#include + +namespace boost +{ +template > +struct closeness_measure + : public geodesic_measure +{ + typedef geodesic_measure< Graph, DistanceType, ResultType> base_type; + typedef typename base_type::distance_type distance_type; + typedef typename base_type::result_type result_type; + + result_type operator ()(distance_type d, const Graph&) + { + function_requires< NumericValueConcept >(); + function_requires< NumericValueConcept >(); + function_requires< AdaptableUnaryFunctionConcept >(); + return (d == base_type::infinite_distance()) + ? base_type::zero_result() + : rec(result_type(d)); + } + Reciprocal rec; +}; + +template +inline closeness_measure< + Graph, typename property_traits::value_type, double, + detail::reciprocal > +measure_closeness(const Graph&, DistanceMap) +{ + typedef typename property_traits::value_type Distance; + return closeness_measure >(); +} + +template +inline closeness_measure< + Graph, typename property_traits::value_type, T, + detail::reciprocal > +measure_closeness(const Graph&, DistanceMap) +{ + typedef typename property_traits::value_type Distance; + return closeness_measure >(); +} + +template +inline closeness_measure< + Graph, typename property_traits::value_type, T, + Reciprocal> +measure_closeness(const Graph&, DistanceMap) +{ + typedef typename property_traits::value_type Distance; + return closeness_measure(); +} + +template +inline typename Measure::result_type +closeness_centrality(const Graph& g, + DistanceMap dist, + Measure measure, + Combinator combine) +{ + function_requires< VertexListGraphConcept >(); + typedef typename graph_traits::vertex_descriptor Vertex; + function_requires< ReadablePropertyMapConcept >(); + typedef typename property_traits::value_type Distance; + function_requires< NumericValueConcept >(); + function_requires< DistanceMeasureConcept >(); + + Distance n = detail::combine_distances(g, dist, combine, Distance(0)); + return measure(n, g); +} + +template +inline typename Measure::result_type +closeness_centrality(const Graph& g, DistanceMap dist, Measure measure) +{ + function_requires< GraphConcept >(); + typedef typename graph_traits::vertex_descriptor Vertex; + function_requires< ReadablePropertyMapConcept >(); + typedef typename property_traits::value_type Distance; + + return closeness_centrality(g, dist, measure, std::plus()); +} + +template +inline double closeness_centrality(const Graph& g, DistanceMap dist) +{ return closeness_centrality(g, dist, measure_closeness(g, dist)); } + +template +inline T closeness_centrality(const Graph& g, DistanceMap dist) +{ return closeness_centrality(g, dist, measure_closeness(g, dist)); } + +template +inline void +all_closeness_centralities(const Graph& g, + DistanceMatrixMap dist, + CentralityMap cent, + Measure measure) +{ + function_requires< VertexListGraphConcept >(); + typedef typename graph_traits::vertex_descriptor Vertex; + function_requires< ReadablePropertyMapConcept >(); + typedef typename property_traits::value_type DistanceMap; + function_requires< ReadablePropertyMapConcept >(); + function_requires< WritablePropertyMapConcept >(); + typedef typename property_traits::value_type Distance; + typedef typename property_traits::value_type Centrality; + + typename graph_traits::vertex_iterator i, end; + for(tie(i, end) = vertices(g); i != end; ++i) { + DistanceMap dm = get(dist, *i); + Centrality c = closeness_centrality(g, dm, measure); + put(cent, *i, c); + } +} + +template +inline void +all_closeness_centralities(const Graph& g, + DistanceMatrixMap dist, + CentralityMap cent) +{ + function_requires< GraphConcept >(); + typedef typename graph_traits::vertex_descriptor Vertex; + function_requires< ReadablePropertyMapConcept >(); + typedef typename property_traits::value_type DistanceMap; + function_requires< 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())); +} + +} /* namespace boost */ + +#endif diff --git a/include/boost/graph/detail/geodesic.hpp b/include/boost/graph/detail/geodesic.hpp new file mode 100644 index 00000000..f61e8af7 --- /dev/null +++ b/include/boost/graph/detail/geodesic.hpp @@ -0,0 +1,129 @@ +// (C) Copyright 2007 Andrew Sutton +// +// 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_DETAIL_GEODESIC_HPP +#define BOOST_GRAPH_DETAIL_GEODESIC_HPP + +#include +#include +#include + +// TODO: Should this really be in detail? + +namespace boost +{ +// This is a very good discussion on centrality measures. While I can't +// say that this has been the motivating factor for the design and +// implementation of ths centrality framework, it does provide a single +// point of reference for defining things like degree and closeness +// centrality. Plus, the bibliography seems fairly complete. +// +// @article{citeulike:1144245, +// author = {Borgatti, Stephen P. and Everett, Martin G.}, +// citeulike-article-id = {1144245}, +// doi = {10.1016/j.socnet.2005.11.005}, +// journal = {Social Networks}, +// month = {October}, +// number = {4}, +// pages = {466--484}, +// priority = {0}, +// title = {A Graph-theoretic perspective on centrality}, +// url = {http://dx.doi.org/10.1016/j.socnet.2005.11.005}, +// volume = {28}, +// year = {2006} +// } +// } + +namespace detail { + // Note that this assumes T == property_traits::value_type + // and that the args and return of combine are also T. + template + inline Distance + combine_distances(const Graph& g, + DistanceMap dist, + Combinator combine, + Distance init) + { + function_requires< VertexListGraphConcept >(); + typedef typename graph_traits::vertex_descriptor Vertex; + typedef typename graph_traits::vertex_iterator VertexIterator; + function_requires< ReadablePropertyMapConcept >(); + function_requires< NumericValueConcept >(); + typedef numeric_values DistanceNumbers; + function_requires< AdaptableBinaryFunction >(); + + // If there's ever an infinite distance, then we simply return + // infinity. Note that this /will/ include the a non-zero + // distance-to-self in the combined values. However, this is usually + // zero, so it shouldn't be too problematic. + Distance ret = init; + VertexIterator i, end; + for(tie(i, end) = vertices(g); i != end; ++i) { + Vertex v = *i; + if(get(dist, v) != DistanceNumbers::infinity()) { + ret = combine(ret, get(dist, v)); + } + else { + ret = DistanceNumbers::infinity(); + break; + } + } + return ret; + } + + // Similar to std::plus, but maximizes parameters + // rather than adding them. + template + struct maximize : public std::binary_function + { + T operator ()(T x, T y) const + { return std::max(x, y); } + }; + + // Another helper, like maximize() to help abstract functional + // concepts. This is trivially instantiated for builtin numeric + // types, but should be specialized for those types that have + // discrete notions of reciprocals. + template + struct reciprocal : public std::unary_function + { + typedef std::unary_function function_type; + typedef typename function_type::result_type result_type; + typedef typename function_type::argument_type argument_type; + T operator ()(T t) + { return T(1) / t; } + }; +} /* namespace detail */ + +// This type defines the basic facilities used for computing values +// based on the geodesic distances between vertices. Examples include +// closeness centrality and mean geodesic distance. +template +struct geodesic_measure +{ + typedef DistanceType distance_type; + typedef ResultType result_type; + typedef typename graph_traits::vertices_size_type size_type; + + typedef numeric_values distance_values; + typedef numeric_values result_values; + + static inline distance_type infinite_distance() + { return distance_values::infinity(); } + + static inline result_type infinite_result() + { return result_values::infinity(); } + + static inline result_type zero_result() + { return result_values::zero(); } +}; + +} /* namespace boost */ + +#endif diff --git a/include/boost/graph/detail/index.hpp b/include/boost/graph/detail/index.hpp new file mode 100644 index 00000000..db1152f8 --- /dev/null +++ b/include/boost/graph/detail/index.hpp @@ -0,0 +1,74 @@ +// (C) Copyright 2007-2009 Andrew Sutton +// +// 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_DETAIL_INDEX_HPP +#define BOOST_GRAPH_DETAIL_INDEX_HPP + +#include + +// The structures in this module are responsible for selecting and defining +// types for accessing a builting index map. Note that the selection of these +// types requires the Graph parameter to model either VertexIndexGraph or +// EdgeIndexGraph. + +namespace boost +{ + namespace detail + { + template + struct vertex_indexer + { + typedef vertex_index_t index_type; + typedef typename property_map::type map_type; + typedef typename property_map::const_type const_map_type; + typedef typename property_traits::value_type value_type; + typedef typename graph_traits::vertex_descriptor key_type; + + static const_map_type index_map(const Graph& g) + { return get(vertex_index, g); } + + static map_type index_map(Graph& g) + { return get(vertex_index, g); } + + static value_type index(key_type k, const Graph& g) + { return get(vertex_index, g, k); } + }; + + template + struct edge_indexer + { + typedef edge_index_t index_type; + typedef typename property_map::type map_type; + typedef typename property_map::const_type const_map_type; + typedef typename property_traits::value_type value_type; + typedef typename graph_traits::edge_descriptor key_type; + + static const_map_type index_map(const Graph& g) + { return get(edge_index, g); } + + static map_type index_map(Graph& g) + { return get(edge_index, g); } + + static value_type index(key_type k, const Graph& g) + { return get(edge_index, g, k); } + }; + + // NOTE: The Graph parameter MUST be a model of VertexIndexGraph or + // VertexEdgeGraph - whichever type Key is selecting. + template + struct choose_indexer + { + typedef typename mpl::if_< + is_same::vertex_descriptor>, + vertex_indexer, + edge_indexer + >::type indexer_type; + typedef typename indexer_type::index_type index_type; + }; + } +} + +#endif diff --git a/include/boost/graph/exterior_property.hpp b/include/boost/graph/exterior_property.hpp new file mode 100644 index 00000000..af6df818 --- /dev/null +++ b/include/boost/graph/exterior_property.hpp @@ -0,0 +1,117 @@ +// (C) Copyright 2007-2009 Andrew Sutton +// +// 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_EXTERIOR_PROPERTY_HPP +#define BOOST_GRAPH_EXTERIOR_PROPERTY_HPP + +#include +#include +#include + +namespace boost { +namespace detail { + // The vector matrix provides a little abstraction over vector + // types that makes matrices easier to work with. Note that it's + // non-copyable, meaning you should be passing it by value. + template + struct vector_matrix + { + typedef std::vector container_type; + typedef std::vector matrix_type; + + typedef container_type value_type; + typedef container_type& reference; + typedef const container_type const_reference; + typedef container_type* pointer; + typedef typename matrix_type::size_type size_type; + + // Instantiate the matrix over n elements (creates an nxn matrix). + // The graph has to be passed in order to ensure the index maps + // are constructed correctly when returning indexible elements. + inline vector_matrix(size_type n) + : m_matrix(n, container_type(n)) + { } + + inline reference operator [](size_type n) + { return m_matrix[n]; } + + inline const_reference operator [](size_type n) const + { return m_matrix[n]; } + + matrix_type m_matrix; + }; +} /* namespace detail */ + +/** + * The exterior_property metafunction defines an appropriate set of types for + * creating an exterior property. An exterior property is comprised of a both + * a container and a property map that acts as its abstraction. An extension + * of this metafunction will select an appropriate "matrix" property that + * records values for pairs of vertices. + * + * @todo This does not currently support the ability to define exterior + * properties for graph types that do not model the IndexGraph concepts. A + * solution should not be especially difficult, but will require an extension + * of type traits to affect the type selection. + */ +template +struct exterior_property +{ + typedef Key key_type; + typedef Value value_type; + + typedef std::vector container_type; + typedef container_property_map map_type; + + typedef detail::vector_matrix matrix_type; + typedef matrix_property_map matrix_map_type; + +private: + exterior_property() { } + exterior_property(const exterior_property&) { } +}; + +/** + * Define a the container and property map types requried to create an exterior + * vertex property for the given value type. The Graph parameter is required to + * model the VertexIndexGraph concept. + */ +template +struct exterior_vertex_property +{ + typedef exterior_property< + Graph, typename graph_traits::vertex_descriptor, Value + > property_type; + typedef typename property_type::key_type key_type; + typedef typename property_type::value_type value_type; + typedef typename property_type::container_type container_type; + typedef typename property_type::map_type map_type; + typedef typename property_type::matrix_type matrix_type; + typedef typename property_type::matrix_map_type matrix_map_type; +}; + +/** + * Define a the container and property map types requried to create an exterior + * edge property for the given value type. The Graph parameter is required to + * model the EdgeIndexGraph concept. + */ +template +struct exterior_edge_property +{ + typedef exterior_property< + Graph, typename graph_traits::edge_descriptor, Value + > property_type; + typedef typename property_type::key_type key_type; + typedef typename property_type::value_type value_type; + typedef typename property_type::container_type container_type; + typedef typename property_type::map_type map_type; + typedef typename property_type::matrix_type matrix_type; + typedef typename property_type::matrix_map_type matrix_map_type; +}; + +} /* namespace boost */ + +#endif diff --git a/include/boost/graph/property_maps/constant_property_map.hpp b/include/boost/graph/property_maps/constant_property_map.hpp new file mode 100644 index 00000000..99ac72d8 --- /dev/null +++ b/include/boost/graph/property_maps/constant_property_map.hpp @@ -0,0 +1,59 @@ +// (C) Copyright 2007-2009 Andrew Sutton +// +// 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_CONSTANT_PROPERTY_HPP +#define BOOST_GRAPH_CONSTANT_PROPERTY_HPP + +#include + + +// TODO: This should really be part of the property maps library rather than +// the Boost.Graph library. + +namespace boost { + +/** + * A constant property is one, that regardless of the edge or vertex given, + * will always return a constant value. + */ +template +struct constant_property_map + : public boost::put_get_helper< + const Value&, + constant_property_map + > +{ + typedef Key key_type; + typedef Value value_type; + typedef const Value& reference; + typedef boost::readable_property_map_tag category; + + constant_property_map() + : m_value() + { } + + constant_property_map(const value_type &value) + : m_value(value) + { } + + constant_property_map(const constant_property_map& copy) + : m_value(copy.m_value) + { } + + inline reference operator [](const key_type& v) const + { return m_value; } + + value_type m_value; +}; + +template +inline constant_property_map +make_constant_property(const Value& value) +{ return constant_property_map(value); } + +} /* namespace boost */ + +#endif diff --git a/include/boost/graph/property_maps/container_property_map.hpp b/include/boost/graph/property_maps/container_property_map.hpp new file mode 100644 index 00000000..f29e28bb --- /dev/null +++ b/include/boost/graph/property_maps/container_property_map.hpp @@ -0,0 +1,75 @@ +// (C) Copyright 2007-2009 Andrew Sutton +// +// 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_CONTAINER_PROPERTY_MAP_HPP +#define BOOST_GRAPH_CONTAINER_PROPERTY_MAP_HPP + +#include +#include + +namespace boost +{ + // This is an adapter built over the iterator property map with + // more useful uniform construction semantics. Specifically, this + // requires the container rather than the iterator and the graph + // rather than the optional index map. + template + struct container_property_map + : public boost::put_get_helper< + typename iterator_property_map< + typename Container::iterator, + typename property_map< + Graph, + typename detail::choose_indexer::index_type + >::type + >::reference, + container_property_map + > + { + typedef typename detail::choose_indexer::indexer_type indexer_type; + typedef typename indexer_type::index_type index_type; + typedef iterator_property_map< + typename Container::iterator, + typename property_map::type + > map_type; + typedef typename map_type::key_type key_type; + typedef typename map_type::value_type value_type; + typedef typename map_type::reference reference; + typedef typename map_type::category category; + + // The default constructor will *probably* crash if its actually + // used for referencing vertices since the underlying iterator + // map points past the end of an unknown container. + inline container_property_map() + : m_map() + { } + + // This is the preferred constructor. It is invoked over the container + // and the graph explicitly. This requires that the underlying iterator + // map use the indices of the vertices in g rather than the default + // identity map. + // + // Note the const-cast this ensures the reference type of the + // vertex index map is non-const, which happens to be an + // artifact of passing const graph references. + inline container_property_map(Container& c, const Graph& g) + : m_map(c.begin(), indexer_type::index_map(const_cast(g))) + { } + + // Typical copy constructor. + inline container_property_map(const container_property_map& x) + : m_map(x.m_map) + { } + + // The [] operator delegates to the underlying map/ + inline reference operator [](const key_type& k) const + { return m_map[k]; } + + map_type m_map; + }; +} + +#endif diff --git a/include/boost/graph/property_maps/matrix_property_map.hpp b/include/boost/graph/property_maps/matrix_property_map.hpp new file mode 100644 index 00000000..bf4f2c9c --- /dev/null +++ b/include/boost/graph/property_maps/matrix_property_map.hpp @@ -0,0 +1,67 @@ +// (C) Copyright 2007-2009 Andrew Sutton +// +// 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_MATRIX_PROPERTY_MAP_HPP +#define BOOST_GRAPH_MATRIX_PROPERTY_MAP_HPP + +#include + +namespace boost +{ + // This property map is built specifically for property maps over + // matrices. Like the basic property map over a container, this builds + // the property abstraction over a matrix (usually a vector of vectors) + // and returns property maps over the nested containers. + template + struct matrix_property_map + : boost::put_get_helper< + container_property_map, + matrix_property_map > + { + // abstract the indexing keys + typedef typename detail::choose_indexer::indexer_type indexer_type; + + // aliases for the nested container and its corresponding map + typedef typename Matrix::value_type container_type; + typedef container_property_map map_type; + + typedef Key key_type; + + // This property map doesn't really provide access to nested containers, + // but returns property maps over them. Since property maps are all + // copy-constructible (or should be anyways), we never return references. + // As such, this property is only readable, but not writable. Curiously, + // the inner property map is actually an lvalue pmap. + typedef map_type value_type; + typedef map_type reference; + typedef readable_property_map_tag category; + + matrix_property_map() + : m_matrix(0), m_graph(0) + { } + + matrix_property_map(Matrix& m, const Graph& g) + : m_matrix(&m), m_graph(const_cast(&g)) + { } + + matrix_property_map(const matrix_property_map& x) + : m_matrix(x.m_matrix), m_graph(x.m_graph) + { } + + inline reference operator [](key_type k) const + { + typedef typename indexer_type::value_type Index; + Index x = indexer_type::index(k, *m_graph); + return map_type((*m_matrix)[x], *m_graph); + } + + private: + mutable Matrix* m_matrix; + mutable Graph* m_graph; + }; +} + +#endif diff --git a/include/boost/graph/tiernan_all_cycles.hpp b/include/boost/graph/tiernan_all_cycles.hpp index 5465ba68..6c1339c5 100644 --- a/include/boost/graph/tiernan_all_cycles.hpp +++ b/include/boost/graph/tiernan_all_cycles.hpp @@ -4,8 +4,8 @@ // 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_CYCLE_HXX -#define BOOST_GRAPH_CYCLE_HXX +#ifndef BOOST_GRAPH_CYCLE_HPP +#define BOOST_GRAPH_CYCLE_HPP #include From 4358d99cb0b1e293e80eaf35aacb49359f66b282 Mon Sep 17 00:00:00 2001 From: Andrew Sutton Date: Sun, 8 Feb 2009 15:28:54 +0000 Subject: [PATCH 087/224] Integrating exterior property maps and closeness centraility. [SVN r51098] --- test/Jamfile.v2 | 2 + test/closeness_centrality.cpp | 134 ++++++++++++++++++++++++++++++++++ test/index_graph.cpp | 61 ++++++++++++++++ 3 files changed, 197 insertions(+) create mode 100644 test/closeness_centrality.cpp create mode 100644 test/index_graph.cpp diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 181fc21f..de0cc6a8 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -24,6 +24,7 @@ test-suite graph_test : # test_graphs will eventually defined a framework for testing the structure # and implementation of graph data structures and adaptors. [ run test_graphs.cpp ] + [ run index_graph.cpp ] # TODO: Make this part of the test_graphs framework [ run transitive_closure_test.cpp ] [ compile adj_list_cc.cpp ] @@ -99,6 +100,7 @@ test-suite graph_test : [ compile dimacs.cpp ] [ run bron_kerbosch_all_cliques.cpp ] [ run tiernan_all_cycles.cpp ] + [ run closeness_centrality.cpp ] $(optional_tests) ; diff --git a/test/closeness_centrality.cpp b/test/closeness_centrality.cpp new file mode 100644 index 00000000..a59abfd5 --- /dev/null +++ b/test/closeness_centrality.cpp @@ -0,0 +1,134 @@ +// (C) Copyright Andrew Sutton 2007 +// +// 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 +#include + +#include +#include +#include +#include +#include +#include + +using namespace std; +using namespace boost; + +// number of vertices in the graph +static const unsigned N = 5; + +template +struct vertex_vector +{ + typedef graph_traits traits; + typedef vector type; +}; + +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); + } + + // add edges + add_edge(v[0], v[1], g); + add_edge(v[1], v[2], g); + add_edge(v[2], v[0], g); + add_edge(v[3], v[4], g); + add_edge(v[4], v[0], g); +}; + + +template +void test_undirected() +{ + typedef typename graph_traits::vertex_descriptor Vertex; + typedef typename graph_traits::edge_descriptor Edge; + + typedef exterior_vertex_property CentralityProperty; + typedef typename CentralityProperty::container_type CentralityContainer; + typedef typename CentralityProperty::map_type CentralityMap; + + typedef exterior_vertex_property DistanceProperty; + typedef typename DistanceProperty::matrix_type DistanceMatrix; + typedef typename DistanceProperty::matrix_map_type DistanceMatrixMap; + + typedef constant_property_map WeightMap; + + Graph g; + vector v(N); + build_graph(g, v); + + CentralityContainer centralities(num_vertices(g)); + DistanceMatrix distances(num_vertices(g)); + + CentralityMap cm(centralities, g); + DistanceMatrixMap dm(distances, g); + + WeightMap wm(1); + + floyd_warshall_all_pairs_shortest_paths(g, dm, weight_map(wm)); + all_closeness_centralities(g, dm, cm); + + BOOST_ASSERT(cm[v[0]] == float(1)/5); + BOOST_ASSERT(cm[v[1]] == float(1)/7); + BOOST_ASSERT(cm[v[2]] == float(1)/7); + BOOST_ASSERT(cm[v[3]] == float(1)/9); + BOOST_ASSERT(cm[v[4]] == float(1)/6); +} + +template +void test_directed() +{ + typedef typename graph_traits::vertex_descriptor Vertex; + typedef typename graph_traits::edge_descriptor Edge; + + typedef exterior_vertex_property CentralityProperty; + typedef typename CentralityProperty::container_type CentralityContainer; + typedef typename CentralityProperty::map_type CentralityMap; + + typedef exterior_vertex_property DistanceProperty; + typedef typename DistanceProperty::matrix_type DistanceMatrix; + typedef typename DistanceProperty::matrix_map_type DistanceMatrixMap; + + typedef constant_property_map WeightMap; + + Graph g; + vector v(N); + build_graph(g, v); + + CentralityContainer centralities(num_vertices(g)); + DistanceMatrix distances(num_vertices(g)); + + CentralityMap cm(centralities, g); + DistanceMatrixMap dm(distances, g); + + WeightMap wm(1); + + floyd_warshall_all_pairs_shortest_paths(g, dm, weight_map(wm)); + all_closeness_centralities(g, dm, cm); + + BOOST_ASSERT(cm[v[0]] == float(0)); + BOOST_ASSERT(cm[v[1]] == float(0)); + BOOST_ASSERT(cm[v[2]] == float(0)); + BOOST_ASSERT(cm[v[3]] == float(1)/10); + BOOST_ASSERT(cm[v[4]] == float(0)); +} + +int +main(int argc, char *argv[]) +{ + typedef undirected_graph<> Graph; + typedef directed_graph<> Digraph; + + test_undirected(); + test_directed(); +} diff --git a/test/index_graph.cpp b/test/index_graph.cpp new file mode 100644 index 00000000..eeafd20d --- /dev/null +++ b/test/index_graph.cpp @@ -0,0 +1,61 @@ +// (C) Copyright 2007-2009 Andrew Sutton +// +// 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 +#include + +using namespace std; +using namespace boost; + +typedef undirected_graph<> Graph; +typedef Graph::vertex_descriptor Vertex; +typedef property_map::type IndexMap; + +int main(int, char*[]) +{ + static const size_t N = 5; + Graph g; + Vertex v[N]; + + IndexMap x = get(vertex_index, g); + + // build up the graph + for(size_t i = 0; i < N; ++i) { + v[i] = add_vertex(g); + } + + // after the first build, we should have these conditions + BOOST_ASSERT(max_vertex_index(g) == N); + for(size_t i = 0; i < N; ++i) { + BOOST_ASSERT(get_vertex_index(v[i], g) == i); + } + + // remove some vertices and re-add them... + for(size_t i = 0; i < N; ++i) remove_vertex(v[i], g); + BOOST_ASSERT(num_vertices(g) == 0); + + for(size_t i = 0; i < N; ++i) { + v[i] = add_vertex(g); + } + + // before renumbering, our vertices should be off by + // about N... + BOOST_ASSERT(max_vertex_index(g) == 10); + for(size_t i = 0; i < N; ++i) { + BOOST_ASSERT(get_vertex_index(v[i], g) == N + i); + } + + // renumber vertices + renumber_vertex_indices(g); + + // and we should be back to the initial condition + BOOST_ASSERT(max_vertex_index(g) == N); + for(size_t i = 0; i < N; ++i) { + BOOST_ASSERT(get_vertex_index(v[i], g) == i); + } + + return 0; +} From 6f50bbc49dd388ce55ba9b20bb3077c021a3b9de Mon Sep 17 00:00:00 2001 From: Andrew Sutton Date: Sun, 8 Feb 2009 15:34:25 +0000 Subject: [PATCH 088/224] Integrated degree centrality and test. [SVN r51099] --- include/boost/graph/degree_centrality.hpp | 130 ++++++++++++++++++++++ test/Jamfile.v2 | 1 + test/closeness_centrality.cpp | 26 ++--- test/degree_centrality.cpp | 123 ++++++++++++++++++++ 4 files changed, 267 insertions(+), 13 deletions(-) create mode 100644 include/boost/graph/degree_centrality.hpp create mode 100644 test/degree_centrality.cpp diff --git a/include/boost/graph/degree_centrality.hpp b/include/boost/graph/degree_centrality.hpp new file mode 100644 index 00000000..24ecb6c5 --- /dev/null +++ b/include/boost/graph/degree_centrality.hpp @@ -0,0 +1,130 @@ +// (C) Copyright 2007-2009 Andrew Sutton +// +// 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_DEGREE_CENTRALITY_HPP +#define BOOST_GRAPH_DEGREE_CENTRALITY_HPP + +#include + +namespace boost { + +template +struct degree_centrality_measure +{ + typedef typename graph_traits::degree_size_type degree_type; + typedef typename graph_traits::vertex_descriptor vertex_type; +}; + +template +struct influence_measure + : public degree_centrality_measure +{ + typedef degree_centrality_measure base_type; + typedef typename base_type::degree_type degree_type; + typedef typename base_type::vertex_type vertex_type; + + inline degree_type operator ()(vertex_type v, const Graph& g) + { + function_requires< IncidenceGraphConcept >(); + return out_degree(v, g); + } +}; + +template +inline influence_measure +measure_influence(const Graph&) +{ return influence_measure(); } + + +template +struct prestige_measure + : public degree_centrality_measure +{ + typedef degree_centrality_measure base_type; + typedef typename base_type::degree_type degree_type; + typedef typename base_type::vertex_type vertex_type; + + inline degree_type operator ()(vertex_type v, const Graph& g) + { + function_requires< BidirectionalGraphConcept >(); + return in_degree(v, g); + } +}; + +template +inline prestige_measure +measure_prestige(const Graph&) +{ return prestige_measure(); } + + +template +inline typename Measure::degree_type +degree_centrality(const Graph& g, Vertex v, Measure measure) +{ + function_requires< DegreeMeasureConcept >(); + return measure(v, g); +} + +template +inline typename graph_traits::degree_size_type +degree_centrality(const Graph& g, Vertex v) +{ + return degree_centrality(g, v, measure_influence(g)); +} + + +// These are alias functions, intended to provide a more expressive interface. + +template +inline typename graph_traits::degree_size_type +influence(const Graph& g, Vertex v) +{ return degree_centrality(g, v, measure_influence(g)); } + + +template +inline typename graph_traits::degree_size_type +prestige(const Graph& g, Vertex v) +{ return degree_centrality(g, v, measure_prestige(g)); } + + +template +inline void +all_degree_centralities(const Graph& g, CentralityMap cent, Measure measure) +{ + function_requires< VertexListGraphConcept >(); + typedef typename graph_traits::vertex_descriptor Vertex; + typedef typename graph_traits::vertex_iterator VertexIterator; + function_requires< WritablePropertyMapConcept >(); + typedef typename property_traits::value_type Centrality; + + VertexIterator i, end; + for(tie(i, end) = vertices(g); i != end; ++i) { + Centrality c = degree_centrality(g, *i, measure); + put(cent, *i, c); + } +} + +template +inline void all_degree_centralities(const Graph& g, CentralityMap cent) +{ all_degree_centralities(g, cent, measure_influence(g)); } + +// More helper functions for computing influence and prestige. +// I hate the names of these functions, but influence and prestige +// don't pluralize too well. + +template +inline void all_influence_values(const Graph& g, CentralityMap cent) +{ all_degree_centralities(g, cent, measure_influence(g)); } + +template +inline void all_prestige_values(const Graph& g, CentralityMap cent) +{ all_degree_centralities(g, cent, measure_prestige(g)); } + +} /* namespace boost */ + +#endif + + diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index de0cc6a8..18a033ef 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -101,6 +101,7 @@ test-suite graph_test : [ run bron_kerbosch_all_cliques.cpp ] [ run tiernan_all_cycles.cpp ] [ run closeness_centrality.cpp ] + [ run degree_centrality.cpp ] $(optional_tests) ; diff --git a/test/closeness_centrality.cpp b/test/closeness_centrality.cpp index a59abfd5..846b5c1f 100644 --- a/test/closeness_centrality.cpp +++ b/test/closeness_centrality.cpp @@ -1,4 +1,4 @@ -// (C) Copyright Andrew Sutton 2007 +// (C) Copyright 2007-2009 Andrew Sutton // // Use, modification and distribution are subject to the // Boost Software License, Version 1.0 (See accompanying file @@ -53,7 +53,7 @@ void test_undirected() typedef typename graph_traits::vertex_descriptor Vertex; typedef typename graph_traits::edge_descriptor Edge; - typedef exterior_vertex_property CentralityProperty; + typedef exterior_vertex_property CentralityProperty; typedef typename CentralityProperty::container_type CentralityContainer; typedef typename CentralityProperty::map_type CentralityMap; @@ -78,11 +78,11 @@ void test_undirected() floyd_warshall_all_pairs_shortest_paths(g, dm, weight_map(wm)); all_closeness_centralities(g, dm, cm); - BOOST_ASSERT(cm[v[0]] == float(1)/5); - BOOST_ASSERT(cm[v[1]] == float(1)/7); - BOOST_ASSERT(cm[v[2]] == float(1)/7); - BOOST_ASSERT(cm[v[3]] == float(1)/9); - BOOST_ASSERT(cm[v[4]] == float(1)/6); + BOOST_ASSERT(cm[v[0]] == double(1)/5); + BOOST_ASSERT(cm[v[1]] == double(1)/7); + BOOST_ASSERT(cm[v[2]] == double(1)/7); + BOOST_ASSERT(cm[v[3]] == double(1)/9); + BOOST_ASSERT(cm[v[4]] == double(1)/6); } template @@ -91,7 +91,7 @@ void test_directed() typedef typename graph_traits::vertex_descriptor Vertex; typedef typename graph_traits::edge_descriptor Edge; - typedef exterior_vertex_property CentralityProperty; + typedef exterior_vertex_property CentralityProperty; typedef typename CentralityProperty::container_type CentralityContainer; typedef typename CentralityProperty::map_type CentralityMap; @@ -116,11 +116,11 @@ void test_directed() floyd_warshall_all_pairs_shortest_paths(g, dm, weight_map(wm)); all_closeness_centralities(g, dm, cm); - BOOST_ASSERT(cm[v[0]] == float(0)); - BOOST_ASSERT(cm[v[1]] == float(0)); - BOOST_ASSERT(cm[v[2]] == float(0)); - BOOST_ASSERT(cm[v[3]] == float(1)/10); - BOOST_ASSERT(cm[v[4]] == float(0)); + BOOST_ASSERT(cm[v[0]] == double(0)); + BOOST_ASSERT(cm[v[1]] == double(0)); + BOOST_ASSERT(cm[v[2]] == double(0)); + BOOST_ASSERT(cm[v[3]] == double(1)/10); + BOOST_ASSERT(cm[v[4]] == double(0)); } int diff --git a/test/degree_centrality.cpp b/test/degree_centrality.cpp new file mode 100644 index 00000000..eb13c491 --- /dev/null +++ b/test/degree_centrality.cpp @@ -0,0 +1,123 @@ +// (C) Copyright 2007-2009 Andrew Sutton +// +// 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 + +#include +#include +#include +#include + +using namespace std; +using namespace boost; + +// useful types +// number of vertices in the graph +static const unsigned N = 5; + +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); + } + + // add edges + add_edge(v[0], v[1], g); + add_edge(v[1], v[2], g); + add_edge(v[2], v[0], g); + add_edge(v[3], v[4], g); + add_edge(v[4], v[0], g); +}; + +template +void test_undirected() +{ + typedef typename graph_traits::vertex_descriptor Vertex; + + typedef exterior_vertex_property CentralityProperty; + typedef typename CentralityProperty::container_type CentralityContainer; + typedef typename CentralityProperty::map_type CentralityMap; + + Graph g; + vector v(N); + build_graph(g, v); + + CentralityContainer cents(num_vertices(g)); + CentralityMap cm(cents, g); + all_degree_centralities(g, cm); + + BOOST_ASSERT(cm[v[0]] == 3); + BOOST_ASSERT(cm[v[1]] == 2); + BOOST_ASSERT(cm[v[2]] == 2); + BOOST_ASSERT(cm[v[3]] == 1); + BOOST_ASSERT(cm[v[4]] == 2); +} + +template +void test_influence() +{ + typedef typename graph_traits::vertex_descriptor Vertex; + + typedef exterior_vertex_property CentralityProperty; + typedef typename CentralityProperty::container_type CentralityContainer; + typedef typename CentralityProperty::map_type CentralityMap; + + Graph g; + + vector v(N); + build_graph(g, v); + + CentralityContainer cents(num_vertices(g)); + CentralityMap cm(cents, g); + all_influence_values(g, cm); + + BOOST_ASSERT(cm[v[0]] == 1); + BOOST_ASSERT(cm[v[1]] == 1); + BOOST_ASSERT(cm[v[2]] == 1); + BOOST_ASSERT(cm[v[3]] == 1); + BOOST_ASSERT(cm[v[4]] == 1); +} + +template +void test_prestige() +{ + typedef typename graph_traits::vertex_descriptor Vertex; + + typedef exterior_vertex_property CentralityProperty; + typedef typename CentralityProperty::container_type CentralityContainer; + typedef typename CentralityProperty::map_type CentralityMap; + + Graph g; + + vector v(N); + build_graph(g, v); + + CentralityContainer cents(num_vertices(g)); + CentralityMap cm(cents, g); + all_prestige_values(g, cm); + + BOOST_ASSERT(cm[v[0]] == 2); + BOOST_ASSERT(cm[v[1]] == 1); + BOOST_ASSERT(cm[v[2]] == 1); + BOOST_ASSERT(cm[v[3]] == 0); + BOOST_ASSERT(cm[v[4]] == 1); +} + +int +main(int argc, char *argv[]) +{ + typedef undirected_graph<> Graph; + typedef directed_graph<> Digraph; + + test_undirected(); + test_influence(); + test_prestige(); +} From 288af2017ab120bc30c4a90ee2c1d35601138939 Mon Sep 17 00:00:00 2001 From: Andrew Sutton Date: Sun, 8 Feb 2009 15:40:33 +0000 Subject: [PATCH 089/224] Importing geodesic distance module from SOC. [SVN r51100] --- include/boost/graph/geodesic_distance.hpp | 210 ++++++++++++++++++++++ test/Jamfile.v2 | 1 + test/mean_geodesic.cpp | 142 +++++++++++++++ 3 files changed, 353 insertions(+) create mode 100644 include/boost/graph/geodesic_distance.hpp create mode 100644 test/mean_geodesic.cpp diff --git a/include/boost/graph/geodesic_distance.hpp b/include/boost/graph/geodesic_distance.hpp new file mode 100644 index 00000000..619ca164 --- /dev/null +++ b/include/boost/graph/geodesic_distance.hpp @@ -0,0 +1,210 @@ +// (C) Copyright Andrew Sutton 2007 +// +// 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_GEODESIC_DISTANCE_HPP +#define BOOST_GRAPH_GEODESIC_DISTANCE_HPP + +#include +#include + +namespace boost +{ +template > +struct mean_geodesic_measure + : public geodesic_measure +{ + typedef geodesic_measure base_type; + typedef typename base_type::distance_type distance_type; + typedef typename base_type::result_type result_type; + + result_type operator ()(distance_type d, const Graph& g) + { + function_requires< VertexListGraphConcept >(); + function_requires< NumericValueConcept >(); + function_requires< NumericValueConcept >(); + function_requires< AdaptableBinaryFunctionConcept >(); + + return (d == base_type::infinite_distance()) + ? base_type::infinite_result() + : div(result_type(d), result_type(num_vertices(g) - 1)); + } + Divides div; +}; + +template +inline mean_geodesic_measure::value_type, float> +measure_mean_geodesic(const Graph&, DistanceMap) +{ + return mean_geodesic_measure::value_type, float>(); +} + +template +inline mean_geodesic_measure::value_type, T> +measure_mean_geodesic(const Graph&, DistanceMap) +{ + return mean_geodesic_measure::value_type, T>(); +} + +// This is a little different because it's expected that the result type +// should (must?) be the same as the distance type. There's a type of +// transitivity in this thinking... If the average of distances has type +// X then the average of x's should also be type X. Is there a case where this +// is not true? +// +// This type is a little under-genericized... It needs generic parameters +// for addition and division. +template +struct mean_graph_distance_measure + : public geodesic_measure +{ + typedef geodesic_measure base_type; + typedef typename base_type::distance_type distance_type; + typedef typename base_type::result_type result_type; + + inline result_type operator ()(distance_type d, const Graph& g) + { + function_requires< VertexListGraphConcept >(); + function_requires< NumericValueConcept >(); + + if(d == base_type::infinite_distance()) { + return base_type::infinite_result(); + } + else { + return d / result_type(num_vertices(g)); + } + } +}; + +template +inline mean_graph_distance_measure::value_type> +measure_graph_mean_geodesic(const Graph& g, DistanceMap dist) +{ + typedef typename property_traits::value_type T; + return mean_graph_distance_measure(); +} + +template +inline typename Measure::result_type +mean_geodesic(const Graph& g, + DistanceMap dist, + Measure measure, + Combinator combine) +{ + function_requires< DistanceMeasureConcept >(); + typedef typename Measure::distance_type Distance; + + Distance n = detail::combine_distances(g, dist, combine, Distance(0)); + return measure(n, g); +} + +template +inline typename Measure::result_type +mean_geodesic(const Graph& g, DistanceMap dist, Measure measure) +{ + function_requires< DistanceMeasureConcept >(); + typedef typename Measure::distance_type Distance; + + return mean_geodesic(g, dist, measure, std::plus()); +} + +template +inline float +mean_geodesic(const Graph& g, DistanceMap dist) +{ return mean_geodesic(g, dist, measure_mean_geodesic(g, dist)); } + +template +inline T +mean_geodesic(const Graph& g, DistanceMap dist) +{ return mean_geodesic(g, dist, measure_mean_geodesic(g, dist)); } + + +template +inline typename property_traits::value_type +all_mean_geodesics(const Graph& g, + DistanceMatrixMap dist, + GeodesicMap geo, + Measure measure) +{ + function_requires< VertexListGraphConcept >(); + typedef typename graph_traits::vertex_descriptor Vertex; + typedef typename graph_traits::vertex_iterator VertexIterator; + function_requires< ReadablePropertyMapConcept >(); + typedef typename property_traits::value_type DistanceMap; + function_requires< DistanceMeasureConcept >(); + typedef typename Measure::result_type Result; + function_requires< WritablePropertyMapConcept >(); + function_requires< NumericValueConcept >(); + + // NOTE: We could compute the mean geodesic here by performing additional + // computations (i.e., adding and dividing). However, I don't really feel + // like fully genericizing the entire operation yet so I'm not going to. + + Result inf = numeric_values::infinity(); + Result sum = numeric_values::zero(); + VertexIterator i, end; + for(tie(i, end) = vertices(g); i != end; ++i) { + DistanceMap dm = get(dist, *i); + Result r = mean_geodesic(g, dm, measure); + put(geo, *i, r); + + // compute the sum along with geodesics + if(r == inf) { + sum = inf; + } + else if(sum != inf) { + sum += r; + } + } + + // return the average of averages. + return sum / Result(num_vertices(g)); +} + +template +inline typename property_traits::value_type +all_mean_geodesics(const Graph& g, DistanceMatrixMap dist, GeodesicMap geo) +{ + function_requires< GraphConcept >(); + typedef typename graph_traits::vertex_descriptor Vertex; + function_requires< ReadablePropertyMapConcept >(); + typedef typename property_traits::value_type DistanceMap; + function_requires< WritablePropertyMapConcept >(); + typedef typename property_traits::value_type Result; + + return all_mean_geodesics(g, dist, geo, measure_mean_geodesic(g, DistanceMap())); +} + + +template +inline typename Measure::result_type +small_world_distance(const Graph& g, GeodesicMap geo, Measure measure) +{ + function_requires< DistanceMeasureConcept >(); + typedef typename Measure::result_type Result; + + Result sum = detail::combine_distances(g, geo, std::plus(), Result(0)); + return measure(sum, g); +} + +template +inline typename property_traits::value_type +small_world_distance(const Graph& g, GeodesicMap geo) +{ return small_world_distance(g, geo, measure_graph_mean_geodesic(g, geo)); } + +} + +#endif diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 18a033ef..e8922038 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -102,6 +102,7 @@ test-suite graph_test : [ run tiernan_all_cycles.cpp ] [ run closeness_centrality.cpp ] [ run degree_centrality.cpp ] + [ run mean_geodesic.cpp ] $(optional_tests) ; diff --git a/test/mean_geodesic.cpp b/test/mean_geodesic.cpp new file mode 100644 index 00000000..7c2f9cca --- /dev/null +++ b/test/mean_geodesic.cpp @@ -0,0 +1,142 @@ +// (C) Copyright 2007-2009 Andrew Sutton +// +// 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 + +#include +#include +#include +#include + +#include +#include + +using namespace std; +using namespace boost; + +// useful types +// number of vertices in the graph +static const unsigned N = 5; + +template +struct vertex_vector +{ + typedef graph_traits traits; + typedef vector type; +}; + +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); + } + + // add edges + add_edge(v[0], v[1], g); + add_edge(v[1], v[2], g); + add_edge(v[2], v[0], g); + add_edge(v[3], v[4], g); + add_edge(v[4], v[0], g); +}; + + +template +void test_undirected() +{ + typedef typename graph_traits::vertex_descriptor Vertex; + typedef typename graph_traits::edge_descriptor Edge; + + typedef exterior_vertex_property CentralityProperty; + typedef typename CentralityProperty::container_type CentralityContainer; + typedef typename CentralityProperty::map_type CentralityMap; + + typedef exterior_vertex_property DistanceProperty; + typedef typename DistanceProperty::matrix_type DistanceMatrix; + typedef typename DistanceProperty::matrix_map_type DistanceMatrixMap; + + typedef constant_property_map WeightMap; + + Graph g; + vector v(N); + build_graph(g, v); + + CentralityContainer centralities(num_vertices(g)); + DistanceMatrix distances(num_vertices(g)); + + CentralityMap cm(centralities, g); + DistanceMatrixMap dm(distances, g); + + WeightMap wm(1); + + floyd_warshall_all_pairs_shortest_paths(g, dm, weight_map(wm)); + double geo1 = all_mean_geodesics(g, dm, cm); + double geo2 = small_world_distance(g, cm); + + BOOST_ASSERT(cm[v[0]] == double(5)/4); + BOOST_ASSERT(cm[v[1]] == double(7)/4); + BOOST_ASSERT(cm[v[2]] == double(7)/4); + BOOST_ASSERT(cm[v[3]] == double(9)/4); + BOOST_ASSERT(cm[v[4]] == double(6)/4); + BOOST_ASSERT(geo1 == double(34)/20); + BOOST_ASSERT(geo1 == geo2); +} + +template +void test_directed() +{ + typedef typename graph_traits::vertex_descriptor Vertex; + typedef typename graph_traits::edge_descriptor Edge; + + typedef exterior_vertex_property CentralityProperty; + typedef typename CentralityProperty::container_type CentralityContainer; + typedef typename CentralityProperty::map_type CentralityMap; + + typedef exterior_vertex_property DistanceProperty; + typedef typename DistanceProperty::matrix_type DistanceMatrix; + typedef typename DistanceProperty::matrix_map_type DistanceMatrixMap; + + typedef constant_property_map WeightMap; + + Graph g; + vector v(N); + build_graph(g, v); + + CentralityContainer centralities(num_vertices(g)); + DistanceMatrix distances(num_vertices(g)); + + CentralityMap cm(centralities, g); + DistanceMatrixMap dm(distances, g); + + WeightMap wm(1); + + floyd_warshall_all_pairs_shortest_paths(g, dm, weight_map(wm)); + double geo1 = all_mean_geodesics(g, dm, cm); + double geo2 = small_world_distance(g, cm); + + double inf = numeric_values::infinity(); + BOOST_ASSERT(cm[v[0]] == inf); + BOOST_ASSERT(cm[v[1]] == inf); + BOOST_ASSERT(cm[v[2]] == inf); + BOOST_ASSERT(cm[v[3]] == double(10)/4); + BOOST_ASSERT(cm[v[4]] == inf); + BOOST_ASSERT(geo1 == inf); + BOOST_ASSERT(geo1 == geo2); +} + + +int +main(int argc, char *argv[]) +{ + typedef undirected_graph<> Graph; + typedef directed_graph<> Digraph; + + test_undirected(); + test_directed(); +} From 0767d8a8bb5f9ea3bf6408e2b036550e909b62ba Mon Sep 17 00:00:00 2001 From: Andrew Sutton Date: Sun, 8 Feb 2009 15:57:41 +0000 Subject: [PATCH 090/224] Imported clustering coefficient, eccentricity and core numbers algorithms. There is no test for core_numbers yet. [SVN r51101] --- .../boost/graph/clustering_coefficient.hpp | 157 +++++++++++ include/boost/graph/core_numbers.hpp | 260 ++++++++++++++++++ include/boost/graph/eccentricity.hpp | 108 ++++++++ include/boost/graph/geodesic_distance.hpp | 6 +- test/Jamfile.v2 | 2 + test/clustering_coefficient.cpp | 105 +++++++ test/eccentricity.cpp | 144 ++++++++++ 7 files changed, 779 insertions(+), 3 deletions(-) create mode 100644 include/boost/graph/clustering_coefficient.hpp create mode 100644 include/boost/graph/core_numbers.hpp create mode 100644 include/boost/graph/eccentricity.hpp create mode 100644 test/clustering_coefficient.cpp create mode 100644 test/eccentricity.cpp diff --git a/include/boost/graph/clustering_coefficient.hpp b/include/boost/graph/clustering_coefficient.hpp new file mode 100644 index 00000000..b314b1cb --- /dev/null +++ b/include/boost/graph/clustering_coefficient.hpp @@ -0,0 +1,157 @@ +// (C) Copyright 2007-2009 Andrew Sutton +// +// 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_CLUSTERING_COEFFICIENT_HPP +#define BOOST_GRAPH_CLUSTERING_COEFFICIENT_HPP + +#include +#include +#include + +namespace boost +{ +namespace detail +{ + template + inline typename graph_traits::degree_size_type + possible_edges(const Graph& g, std::size_t k, directed_tag) + { + function_requires< GraphConcept >(); + typedef typename graph_traits::degree_size_type T; + return T(k) * (T(k) - 1); + } + + template + inline typename graph_traits::degree_size_type + possible_edges(const Graph& g, size_t k, undirected_tag) + { + // dirty little trick... + return possible_edges(g, k, directed_tag()) / 2; + } + + // This template matches directedS and bidirectionalS. + template + inline typename graph_traits::degree_size_type + count_edges(const Graph& g, + typename Graph::vertex_descriptor u, + typename Graph::vertex_descriptor v, + directed_tag) + + { + function_requires< AdjacencyMatrixConcept >(); + return (edge(u, v, g).second ? 1 : 0) + + (edge(v, u, g).second ? 1 : 0); + } + + // This template matches undirectedS + template + inline typename graph_traits::degree_size_type + count_edges(const Graph& g, + typename Graph::vertex_descriptor u, + typename Graph::vertex_descriptor v, + undirected_tag) + { + function_requires< AdjacencyMatrixConcept >(); + return edge(u, v, g).second ? 1 : 0; + } +} + +template +inline typename graph_traits::degree_size_type +num_paths_through_vertex(const Graph& g, Vertex v) +{ + function_requires< AdjacencyGraphConcept >(); + typedef typename graph_traits::directed_category Directed; + typedef typename graph_traits::adjacency_iterator AdjacencyIterator; + + // TODO: There should actually be a set of neighborhood functions + // for things like this (num_neighbors() would be great). + + AdjacencyIterator i, end; + tie(i, end) = adjacent_vertices(v, g); + std::size_t k = std::distance(i, end); + return detail::possible_edges(g, k, Directed()); +} + +template +inline typename graph_traits::degree_size_type +num_triangles_on_vertex(const Graph& g, Vertex v) +{ + function_requires< IncidenceGraphConcept >(); + function_requires< AdjacencyGraphConcept >(); + typedef typename graph_traits::degree_size_type Degree; + typedef typename graph_traits::directed_category Directed; + typedef typename graph_traits::adjacency_iterator AdjacencyIterator; + + // TODO: I might be able to reduce the requirement from adjacency graph + // to incidence graph by using out edges. + + Degree count(0); + AdjacencyIterator i, j, end; + for(tie(i, end) = adjacent_vertices(v, g); i != end; ++i) { + for(j = next(i); j != end; ++j) { + count += detail::count_edges(g, *i, *j, Directed()); + } + } + return count; +} /* namespace detail */ + +template +inline T +clustering_coefficient(const Graph& g, Vertex v) +{ + T zero(0); + T routes = T(num_paths_through_vertex(g, v)); + return (routes > zero) ? + T(num_triangles_on_vertex(g, v)) / routes : zero; +} + +template +inline double +clustering_coefficient(const Graph& g, Vertex v) +{ return clustering_coefficient(g, v); } + +template +inline typename property_traits::value_type +all_clustering_coefficients(const Graph& g, ClusteringMap cm) +{ + function_requires< VertexListGraphConcept >(); + typedef typename graph_traits::vertex_descriptor Vertex; + typedef typename graph_traits::vertex_iterator VertexIterator; + function_requires< WritablePropertyMapConcept >(); + typedef typename property_traits::value_type Coefficient; + + Coefficient sum(0); + VertexIterator i, end; + for(tie(i, end) = vertices(g); i != end; ++i) { + Coefficient cc = clustering_coefficient(g, *i); + put(cm, *i, cc); + sum += cc; + } + return sum / Coefficient(num_vertices(g)); +} + +template +inline typename property_traits::value_type +mean_clustering_coefficient(const Graph& g, ClusteringMap cm) +{ + function_requires< VertexListGraphConcept >(); + typedef typename graph_traits::vertex_descriptor Vertex; + typedef typename graph_traits::vertex_iterator VertexIterator; + function_requires< ReadablePropertyMapConcept >(); + typedef typename property_traits::value_type Coefficient; + + Coefficient cc(0); + VertexIterator i, end; + for(tie(i, end) = vertices(g); i != end; ++i) { + cc += get(cm, *i); + } + return cc / Coefficient(num_vertices(g)); +} + +} /* namespace boost */ + +#endif diff --git a/include/boost/graph/core_numbers.hpp b/include/boost/graph/core_numbers.hpp new file mode 100644 index 00000000..8f75e978 --- /dev/null +++ b/include/boost/graph/core_numbers.hpp @@ -0,0 +1,260 @@ +// Copyright 2007 Stanford University +// Authors: David Gleich +// +// 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_CORE_NUMBERS_HPP +#define BOOST_GRAPH_CORE_NUMBERS_HPP + +#include + +/* + * KCore + * + * Requirement: IncidenceGraph + */ + +namespace boost { + +// A linear time O(m) algorithm to compute the in-degree core number +// of a graph for unweighted graphs. +// +// and a O((n+m) log n) algorithm to compute the in-edge-weight core +// numbers of a weighted graph. +// +// The linear algorithm comes from: +// @article{DBLP:journals/corr/cs-DS-0310049, +// author = {Vladimir Batagelj and Matjaz Zaversnik}, +// title = {An O(m) Algorithm for Cores Decomposition of Networks}, +// journal = {The Computing Research Repository (CoRR)}, +// volume = {cs.DS/0310049}, +// year = {2003}, +// ee = {http://arxiv.org/abs/cs.DS/0310049}, +// bibsource = {DBLP, http://dblp.uni-trier.de} +// } + +namespace detail { + // implement a constant_property_map to simplify compute_in_degree + // for the weighted and unweighted case + // this is based on dummy property map + // TODO: This is virtually the same as constant_property_map in + // graph/property_maps. Perhaps we should be using that instead of this.. + template + class constant_value_property_map + : public boost::put_get_helper + > + { + public: + typedef void key_type; + typedef ValueType value_type; + typedef const ValueType& reference; + typedef boost::readable_property_map_tag category; + inline constant_value_property_map(ValueType cc) : c(cc) { } + inline constant_value_property_map(const constant_value_property_map& x) + : c(x.c) { } + template + inline reference operator[](Vertex) const { return c; } + protected: + ValueType c; + }; + + // the core numbers start as the indegree or inweight. This function + // will initialize these values + template + void compute_in_degree_map(Graph& g, CoreMap d, EdgeWeightMap wm) + { + typename graph_traits::vertex_iterator vi,vi_end; + typename graph_traits::out_edge_iterator ei,ei_end; + for (tie(vi,vi_end) = vertices(g); vi!=vi_end; ++vi) { + put(d,*vi,0); + } + for (tie(vi,vi_end) = vertices(g); vi!=vi_end; ++vi) { + for (tie(ei,ei_end) = out_edges(*vi,g); ei!=ei_end; ++ei) { + put(d,target(*ei,g),get(d,target(*ei,g))+get(wm,*ei)); + } + } + } + + // the version for weighted graphs is a little different + template + typename property_traits::value_type + core_numbers_impl(Graph& g, CoreMap c, EdgeWeightMap wm, MutableQueue& Q) + { + typename property_traits::value_type v_cn = 0; + typedef typename graph_traits::vertex_descriptor vertex; + while (!Q.empty()) + { + // remove v from the Q, and then decrease the core numbers + // of its successors + vertex v = Q.top(); + Q.pop(); + v_cn = get(c,v); + typename graph_traits::out_edge_iterator oi,oi_end; + for (tie(oi,oi_end) = out_edges(v,g); oi!=oi_end; ++oi) { + vertex u = target(*oi,g); + // if c[u] > c[v], then u is still in the graph, + if (get(c,u) > v_cn) { + // remove the edge + put(c,u,get(c,u)-get(wm,*oi)); + Q.update(u); + } + } + } + return (v_cn); + } + + template + typename property_traits::value_type + core_numbers_dispatch(Graph&g, CoreMap c, EdgeWeightMap wm, IndexMap im) + { + 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); + typename graph_traits::vertex_iterator vi,vi_end; + for (tie(vi,vi_end) = vertices(g); vi!=vi_end; ++vi) { + Q.push(*vi); + } + return core_numbers_impl(g, c, wm, Q); + } + + // the version for the unweighted case + // for this functions CoreMap must be initialized + // with the in degree of each vertex + template + typename property_traits::value_type + core_numbers_impl(Graph& g, CoreMap c, PositionMap pos) + { + typedef typename graph_traits::vertices_size_type size_type; + typedef typename graph_traits::degree_size_type degree_type; + typedef typename graph_traits::vertex_descriptor vertex; + typename graph_traits::vertex_iterator vi,vi_end; + + // store the vertex core numbers + typename property_traits::value_type v_cn = 0; + + // compute the maximum degree (degrees are in the coremap) + typename graph_traits::degree_size_type max_deg = 0; + for (tie(vi,vi_end) = vertices(g); vi!=vi_end; ++vi) { + max_deg = (std::max)(max_deg, get(c,*vi)); + } + // store the vertices in bins by their degree + // allocate two extra locations to ease boundary cases + std::vector bin(max_deg+2); + for (tie(vi,vi_end) = vertices(g); vi!=vi_end; ++vi) { + ++bin[get(c,*vi)]; + } + // this loop sets bin[d] to the starting position of vertices + // with degree d in the vert array for the bucket sort + size_type cur_pos = 0; + for (degree_type cur_deg = 0; cur_deg < max_deg+2; ++cur_deg) { + degree_type tmp = bin[cur_deg]; + bin[cur_deg] = cur_pos; + cur_pos += tmp; + } + // perform the bucket sort with pos and vert so that + // pos[0] is the vertex of smallest degree + std::vector vert(num_vertices(g)); + for (tie(vi,vi_end) = vertices(g); vi!=vi_end; ++vi) { + vertex v=*vi; + size_type p=bin[get(c,v)]; + put(pos,v,p); + vert[p]=v; + ++bin[get(c,v)]; + } + // we ``abused'' bin while placing the vertices, now, + // we need to restore it + std::copy(boost::make_reverse_iterator(bin.end()-2), + boost::make_reverse_iterator(bin.begin()), + boost::make_reverse_iterator(bin.end()-1)); + // now simulate removing the vertices + for (size_type i=0; i < num_vertices(g); ++i) { + vertex v = vert[i]; + v_cn = get(c,v); + typename graph_traits::out_edge_iterator oi,oi_end; + for (tie(oi,oi_end) = out_edges(v,g); oi!=oi_end; ++oi) { + vertex u = target(*oi,g); + // if c[u] > c[v], then u is still in the graph, + if (get(c,u) > v_cn) { + degree_type deg_u = get(c,u); + degree_type pos_u = get(pos,u); + // w is the first vertex with the same degree as u + // (this is the resort operation!) + degree_type pos_w = bin[deg_u]; + vertex w = vert[pos_w]; + if (u!=v) { + // swap u and w + put(pos,u,pos_w); + put(pos,w,pos_u); + vert[pos_w] = u; + vert[pos_u] = w; + } + // now, the vertices array is sorted assuming + // we perform the following step + // start the set of vertices with degree of u + // one into the future (this now points at vertex + // w which we swapped with u). + ++bin[deg_u]; + // we are removing v from the graph, so u's degree + // decreases + put(c,u,get(c,u)-1); + } + } + } + return v_cn; + } + +} // namespace detail + +template +typename property_traits::value_type +core_numbers(Graph& g, CoreMap c) +{ + typedef typename graph_traits::vertices_size_type size_type; + detail::compute_in_degree_map(g,c, + detail::constant_value_property_map< + typename property_traits::value_type>(1) ); + return detail::core_numbers_impl(g,c, + make_iterator_property_map( + std::vector(num_vertices(g)).begin(),get(vertex_index, g)) + ); +} + +template +typename property_traits::value_type +core_numbers(Graph& g, CoreMap c, EdgeWeightMap wm, VertexIndexMap vim) +{ + 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); +} + +template +typename property_traits::value_type +core_numbers(Graph& g, CoreMap c, EdgeWeightMap wm) +{ + 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,get(vertex_index,g)); +} + +template +typename property_traits::value_type +weighted_core_numbers(Graph& g, CoreMap c) +{ return core_numbers(g,c,get(edge_weight,g)); } + +} // namespace boost + +#endif // BOOST_GRAPH_CORE_NUMBERS_HPP + diff --git a/include/boost/graph/eccentricity.hpp b/include/boost/graph/eccentricity.hpp new file mode 100644 index 00000000..49e75d2e --- /dev/null +++ b/include/boost/graph/eccentricity.hpp @@ -0,0 +1,108 @@ +// (C) Copyright 2007-2009 Andrew Sutton +// +// 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_ECCENTRICITY_HPP +#define BOOST_GRAPH_ECCENTRICITY_HPP + +#include +#include + +namespace boost +{ +template +inline typename property_traits::value_type +eccentricity(const Graph& g, DistanceMap dist, Combinator combine) +{ + function_requires< GraphConcept >(); + typedef typename graph_traits::vertex_descriptor Vertex; + function_requires< ReadablePropertyMapConcept >(); + typedef typename property_traits::value_type Distance; + + return detail::combine_distances(g, dist, combine, Distance(0)); +} + +template +inline typename property_traits::value_type +eccentricity(const Graph& g, DistanceMap dist) +{ + function_requires< GraphConcept >(); + typedef typename graph_traits::vertex_descriptor Vertex; + function_requires< ReadablePropertyMapConcept >(); + typedef typename property_traits::value_type Distance; + + return eccentricity(g, dist, detail::maximize()); +} + +template +inline std::pair::value_type, + typename property_traits::value_type> +all_eccentricities(const Graph& g, const DistanceMatrix& dist, EccentricityMap ecc) +{ + function_requires< VertexListGraphConcept >(); + typedef typename graph_traits::vertex_descriptor Vertex; + typedef typename graph_traits::vertex_iterator VertexIterator; + function_requires< ReadablePropertyMapConcept >(); + typedef typename property_traits::value_type DistanceMap; + function_requires< WritablePropertyMapConcept >(); + typedef typename property_traits::value_type Eccentricity; + + Eccentricity + r = numeric_values::infinity(), + d = numeric_values::zero(); + VertexIterator i, end; + tie(i, end) = vertices(g); + for(tie(i, end) = vertices(g); i != end; ++i) { + DistanceMap dm = get(dist, *i); + Eccentricity e = eccentricity(g, dm); + put(ecc, *i, e); + + // track the radius and diameter at the same time + r = std::min(r, e); + d = std::max(d, e); + } + return make_pair(r, d); +} + +template +inline std::pair::value_type, + typename property_traits::value_type> +radius_and_diameter(const Graph& g, EccentricityMap ecc) +{ + function_requires< VertexListGraphConcept >(); + typedef typename graph_traits::vertex_descriptor Vertex; + typedef typename graph_traits::vertex_iterator VertexIterator; + function_requires< ReadablePropertyMapConcept >(); + typedef typename property_traits::value_type Eccentricity; + + VertexIterator i, end; + tie(i, end) = vertices(g); + Eccentricity radius = get(ecc, *i); + Eccentricity diameter = get(ecc, *i); + for(i = next(i); i != end; ++i) { + Eccentricity cur = get(ecc, *i); + radius = std::min(radius, cur); + diameter = std::max(diameter, cur); + } + return std::make_pair(radius, diameter); +} + + +template +inline typename property_traits::value_type +radius(const Graph& g, EccentricityMap ecc) +{ return radius_and_diameter(g, ecc).first; } + + +template +inline typename property_traits::value_type +diameter(const Graph& g, EccentricityMap ecc) +{ return radius_and_diameter(g, ecc).second; } + +} /* namespace boost */ + +#endif diff --git a/include/boost/graph/geodesic_distance.hpp b/include/boost/graph/geodesic_distance.hpp index 619ca164..042d39e4 100644 --- a/include/boost/graph/geodesic_distance.hpp +++ b/include/boost/graph/geodesic_distance.hpp @@ -38,10 +38,10 @@ struct mean_geodesic_measure }; template -inline mean_geodesic_measure::value_type, float> +inline mean_geodesic_measure::value_type, double> measure_mean_geodesic(const Graph&, DistanceMap) { - return mean_geodesic_measure::value_type, float>(); + return mean_geodesic_measure::value_type, double>(); } template @@ -119,7 +119,7 @@ mean_geodesic(const Graph& g, DistanceMap dist, Measure measure) } template -inline float +inline double mean_geodesic(const Graph& g, DistanceMap dist) { return mean_geodesic(g, dist, measure_mean_geodesic(g, dist)); } diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index e8922038..e1cee11e 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -103,6 +103,8 @@ test-suite graph_test : [ run closeness_centrality.cpp ] [ run degree_centrality.cpp ] [ run mean_geodesic.cpp ] + [ run eccentricity.cpp ] + [ run clustering_coefficient.cpp ] $(optional_tests) ; diff --git a/test/clustering_coefficient.cpp b/test/clustering_coefficient.cpp new file mode 100644 index 00000000..d13ba5bd --- /dev/null +++ b/test/clustering_coefficient.cpp @@ -0,0 +1,105 @@ +// (C) Copyright 2007-2009 Andrew Sutton +// +// 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 + +#include +#include +#include +#include + +using namespace std; +using namespace boost; + +// number of vertices in the graph +static const unsigned N = 5; + +template +struct vertex_vector +{ + typedef graph_traits traits; + typedef vector type; +}; + +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); + } + + // add edges + add_edge(v[0], v[1], g); + add_edge(v[1], v[2], g); + add_edge(v[2], v[0], g); + add_edge(v[3], v[4], g); + add_edge(v[4], v[0], g); +}; + +template +void test_undirected() +{ + typedef typename graph_traits::vertex_descriptor Vertex; + + typedef exterior_vertex_property ClusteringProperty; + typedef typename ClusteringProperty::container_type ClusteringContainer; + typedef typename ClusteringProperty::map_type ClusteringMap; + + Graph g; + vector v(N); + build_graph(g, v); + + ClusteringContainer cc(num_vertices(g)); + ClusteringMap cm(cc, g); + + BOOST_ASSERT(num_paths_through_vertex(g, v[0]) == 3); + BOOST_ASSERT(num_paths_through_vertex(g, v[1]) == 1); + BOOST_ASSERT(num_paths_through_vertex(g, v[2]) == 1); + BOOST_ASSERT(num_paths_through_vertex(g, v[3]) == 0); + BOOST_ASSERT(num_paths_through_vertex(g, v[4]) == 1); + + BOOST_ASSERT(num_triangles_on_vertex(g, v[0]) == 1); + BOOST_ASSERT(num_triangles_on_vertex(g, v[1]) == 1); + BOOST_ASSERT(num_triangles_on_vertex(g, v[2]) == 1); + BOOST_ASSERT(num_triangles_on_vertex(g, v[3]) == 0); + BOOST_ASSERT(num_triangles_on_vertex(g, v[4]) == 0); + + BOOST_ASSERT(clustering_coefficient(g, v[0]) == double(1)/3); + BOOST_ASSERT(clustering_coefficient(g, v[1]) == 1); + BOOST_ASSERT(clustering_coefficient(g, v[2]) == 1); + BOOST_ASSERT(clustering_coefficient(g, v[3]) == 0); + BOOST_ASSERT(clustering_coefficient(g, v[4]) == 0); + + all_clustering_coefficients(g, cm); + + BOOST_ASSERT(cm[v[0]] == double(1)/3); + BOOST_ASSERT(cm[v[1]] == 1); + BOOST_ASSERT(cm[v[2]] == 1); + BOOST_ASSERT(cm[v[3]] == 0); + BOOST_ASSERT(cm[v[4]] == 0); + + // I would have used check_close, but apparently, that requires + // me to link this against a library - which I don't really want + // to do. Basically, this makes sure that that coefficient is + // within some tolerance (like 1/10 million). + double coef = mean_clustering_coefficient(g, cm); + BOOST_ASSERT((coef - (7.0f / 15.0f)) < 1e-7f); +} + +int +main(int argc, char *argv[]) +{ + typedef undirected_graph<> Graph; + typedef directed_graph<> Digraph; + + // TODO: write a test for directed clustering coefficient. + + test_undirected(); + // test(); +} diff --git a/test/eccentricity.cpp b/test/eccentricity.cpp new file mode 100644 index 00000000..8ce0fbfd --- /dev/null +++ b/test/eccentricity.cpp @@ -0,0 +1,144 @@ +// (C) Copyright 2007-2009 Andrew Sutton +// +// 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 + +#include +#include +#include +#include +#include +#include + + +using namespace std; +using namespace boost; + +// number of vertices in the graph +static const unsigned N = 5; + +template +struct vertex_vector +{ + typedef graph_traits traits; + typedef vector type; +}; + +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); + } + + // add edges + add_edge(v[0], v[1], g); + add_edge(v[1], v[2], g); + add_edge(v[2], v[0], g); + add_edge(v[3], v[4], g); + add_edge(v[4], v[0], g); +}; + + +template +void test_undirected() +{ + typedef typename graph_traits::vertex_descriptor Vertex; + typedef typename graph_traits::edge_descriptor Edge; + + typedef exterior_vertex_property EccentricityProperty; + typedef typename EccentricityProperty::container_type EccentricityContainer; + typedef typename EccentricityProperty::map_type EccentricityMap; + + typedef exterior_vertex_property DistanceProperty; + typedef typename DistanceProperty::matrix_type DistanceMatrix; + typedef typename DistanceProperty::matrix_map_type DistanceMatrixMap; + + typedef constant_property_map WeightMap; + + Graph g; + vector v(N); + build_graph(g, v); + + EccentricityContainer eccs(num_vertices(g)); + DistanceMatrix distances(num_vertices(g)); + + EccentricityMap em(eccs, g); + DistanceMatrixMap dm(distances, g); + + WeightMap wm(1); + + floyd_warshall_all_pairs_shortest_paths(g, dm, weight_map(wm)); + all_eccentricities(g, dm, em); + int rad = radius(g, em); + int dia = diameter(g, em); + + BOOST_ASSERT(em[v[0]] == 2); + BOOST_ASSERT(em[v[1]] == 3); + BOOST_ASSERT(em[v[2]] == 3); + BOOST_ASSERT(em[v[3]] == 3); + BOOST_ASSERT(em[v[4]] == 2); + BOOST_ASSERT(rad == 2); + BOOST_ASSERT(dia == 3); +} + +template +void test_directed() +{ + typedef typename graph_traits::vertex_descriptor Vertex; + typedef typename graph_traits::edge_descriptor Edge; + + typedef exterior_vertex_property EccentricityProperty; + typedef typename EccentricityProperty::container_type EccentricityContainer; + typedef typename EccentricityProperty::map_type EccentricityMap; + + typedef exterior_vertex_property DistanceProperty; + typedef typename DistanceProperty::matrix_type DistanceMatrix; + typedef typename DistanceProperty::matrix_map_type DistanceMatrixMap; + + typedef constant_property_map WeightMap; + + Graph g; + vector v(N); + build_graph(g, v); + + EccentricityContainer eccs(num_vertices(g)); + DistanceMatrix distances(num_vertices(g)); + + EccentricityMap em(eccs, g); + DistanceMatrixMap dm(distances, g); + + WeightMap wm(1); + + floyd_warshall_all_pairs_shortest_paths(g, dm, weight_map(wm)); + all_eccentricities(g, dm, em); + int rad = radius(g, em); + int dia = diameter(g, em); + + int inf = numeric_values::infinity(); + BOOST_ASSERT(em[v[0]] == inf); + BOOST_ASSERT(em[v[1]] == inf); + BOOST_ASSERT(em[v[2]] == inf); + BOOST_ASSERT(em[v[3]] == 4); + BOOST_ASSERT(em[v[4]] == inf); + BOOST_ASSERT(rad == 4); + BOOST_ASSERT(dia == inf); +} + + +int +main(int argc, char *argv[]) +{ + typedef undirected_graph<> Graph; + typedef directed_graph<> Digraph; + + test_undirected(); + test_directed(); +} From b9d82621534bb3508907f5d21cc3b27d3d04b916 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Tue, 10 Feb 2009 22:08:39 +0000 Subject: [PATCH 091/224] Fixed error when popping the last element from the heap [SVN r51190] --- include/boost/graph/detail/d_ary_heap.hpp | 40 +++++++++++++++++++---- 1 file changed, 33 insertions(+), 7 deletions(-) diff --git a/include/boost/graph/detail/d_ary_heap.hpp b/include/boost/graph/detail/d_ary_heap.hpp index 72981642..18f5f631 100644 --- a/include/boost/graph/detail/d_ary_heap.hpp +++ b/include/boost/graph/detail/d_ary_heap.hpp @@ -33,6 +33,27 @@ namespace boost { put(prop_map, kb, va); } + namespace detail { + template + class fixed_max_size_vector { + boost::shared_array m_data; + std::size_t m_size; + + public: + typedef std::size_t size_type; + fixed_max_size_vector(std::size_t max_size) + : m_data(new Value[max_size]), m_size(0) {} + std::size_t size() const {return m_size;} + bool empty() const {return m_size == 0;} + Value& operator[](std::size_t i) {return m_data[i];} + const Value& operator[](std::size_t i) const {return m_data[i];} + void push_back(Value v) {m_data[m_size++] = v;} + void pop_back() {--m_size;} + Value& back() {return m_data[m_size - 1];} + const Value& back() const {return m_data[m_size - 1];} + }; + } + // D-ary heap using an indirect compare operator (use identity_property_map // as DistanceMap to get a direct compare operator). This heap appears to be // commonly used for Dijkstra's algorithm for its good practical performance @@ -73,8 +94,9 @@ namespace boost { d_ary_heap_indirect(DistanceMap distance, IndexInHeapPropertyMap index_in_heap, - const Compare& compare = Compare()) - : compare(compare), data(), distance(distance), + const Compare& compare = Compare(), + const Container& data = Container()) + : compare(compare), data(data), distance(distance), index_in_heap(index_in_heap) {} /* Implicit copy constructor */ /* Implicit assignment operator */ @@ -105,11 +127,15 @@ namespace boost { void pop() { put(index_in_heap, data[0], (size_type)(-1)); - data[0] = data.back(); - put(index_in_heap, data[0], 0); - data.pop_back(); - preserve_heap_property_down(); - verify_heap(); + if (data.size() != 1) { + data[0] = data.back(); + put(index_in_heap, data[0], 0); + data.pop_back(); + preserve_heap_property_down(); + verify_heap(); + } else { + data.pop_back(); + } } // This function assumes the key has been updated (using an external write From e26020a7827b497857476c71c5bf73996d6e7591 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=BCrgen=20Hunold?= Date: Wed, 11 Feb 2009 08:18:06 +0000 Subject: [PATCH 092/224] Fix: add missing #include [SVN r51192] --- include/boost/graph/detail/d_ary_heap.hpp | 1 + 1 file changed, 1 insertion(+) diff --git a/include/boost/graph/detail/d_ary_heap.hpp b/include/boost/graph/detail/d_ary_heap.hpp index 18f5f631..94ad2a60 100644 --- a/include/boost/graph/detail/d_ary_heap.hpp +++ b/include/boost/graph/detail/d_ary_heap.hpp @@ -17,6 +17,7 @@ #include #include #include +#include #include namespace boost { From 7a9822f533d4cd5d226b3c4578dfd94f8a146723 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=BCrgen=20Hunold?= Date: Wed, 11 Feb 2009 08:27:58 +0000 Subject: [PATCH 093/224] Fix: gcc -pedantic -Werror: remove extra ";". [SVN r51193] --- include/boost/graph/numeric_values.hpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/include/boost/graph/numeric_values.hpp b/include/boost/graph/numeric_values.hpp index 84d170cc..002620b9 100644 --- a/include/boost/graph/numeric_values.hpp +++ b/include/boost/graph/numeric_values.hpp @@ -42,9 +42,9 @@ namespace boost // Specializations for floating point types refer to 0.0 and their infinity // value defined by numeric_limits. - BOOST_GRAPH_SPECIALIZE_NUMERIC_FLOAT(float); - BOOST_GRAPH_SPECIALIZE_NUMERIC_FLOAT(double); - BOOST_GRAPH_SPECIALIZE_NUMERIC_FLOAT(long double); + BOOST_GRAPH_SPECIALIZE_NUMERIC_FLOAT(float) + BOOST_GRAPH_SPECIALIZE_NUMERIC_FLOAT(double) + BOOST_GRAPH_SPECIALIZE_NUMERIC_FLOAT(long double) #undef BOOST_GRAPH_SPECIALIZE_NUMERIC_VALUE } From 670d4d5029a1d62ab84eab6435efdff04cfa0af7 Mon Sep 17 00:00:00 2001 From: Andrew Sutton Date: Sat, 14 Feb 2009 13:29:07 +0000 Subject: [PATCH 094/224] Updating core_numbers from David Gleich. [SVN r51249] --- include/boost/graph/core_numbers.hpp | 524 ++++++++++++++++----------- test/Jamfile.v2 | 1 + test/core_numbers_test.cpp | 149 ++++++++ 3 files changed, 457 insertions(+), 217 deletions(-) create mode 100644 test/core_numbers_test.cpp diff --git a/include/boost/graph/core_numbers.hpp b/include/boost/graph/core_numbers.hpp index 8f75e978..743c81f9 100644 --- a/include/boost/graph/core_numbers.hpp +++ b/include/boost/graph/core_numbers.hpp @@ -1,258 +1,348 @@ +// +//======================================================================= // Copyright 2007 Stanford University // Authors: David Gleich // // 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_CORE_NUMBERS_HPP #define BOOST_GRAPH_CORE_NUMBERS_HPP #include +#include +#include +#include /* - * KCore + * core_numbers * * Requirement: IncidenceGraph */ +// History +// +// 30 July 2007 +// Added visitors to the implementation +// +// 8 February 2008 +// Fixed headers and missing typename + namespace boost { -// A linear time O(m) algorithm to compute the in-degree core number -// of a graph for unweighted graphs. -// -// and a O((n+m) log n) algorithm to compute the in-edge-weight core -// numbers of a weighted graph. -// -// The linear algorithm comes from: -// @article{DBLP:journals/corr/cs-DS-0310049, -// author = {Vladimir Batagelj and Matjaz Zaversnik}, -// title = {An O(m) Algorithm for Cores Decomposition of Networks}, -// journal = {The Computing Research Repository (CoRR)}, -// volume = {cs.DS/0310049}, -// year = {2003}, -// ee = {http://arxiv.org/abs/cs.DS/0310049}, -// bibsource = {DBLP, http://dblp.uni-trier.de} -// } + // A linear time O(m) algorithm to compute the indegree core number + // of a graph for unweighted graphs. + // + // and a O((n+m) log n) algorithm to compute the in-edge-weight core + // numbers of a weighted graph. + // + // The linear algorithm comes from: + // Vladimir Batagelj and Matjaz Zaversnik, "An O(m) Algorithm for Cores + // Decomposition of Networks." Sept. 1 2002. -namespace detail { - // implement a constant_property_map to simplify compute_in_degree - // for the weighted and unweighted case - // this is based on dummy property map - // TODO: This is virtually the same as constant_property_map in - // graph/property_maps. Perhaps we should be using that instead of this.. - template - class constant_value_property_map - : public boost::put_get_helper - > - { - public: - typedef void key_type; - typedef ValueType value_type; - typedef const ValueType& reference; - typedef boost::readable_property_map_tag category; - inline constant_value_property_map(ValueType cc) : c(cc) { } - inline constant_value_property_map(const constant_value_property_map& x) - : c(x.c) { } - template - inline reference operator[](Vertex) const { return c; } - protected: - ValueType c; + template + struct CoreNumbersVisitorConcept { + void constraints() + { + function_requires< CopyConstructibleConcept >(); + vis.examine_vertex(u,g); + vis.finish_vertex(u,g); + vis.examine_edge(e,g); + } + Visitor vis; + Graph g; + typename graph_traits::vertex_descriptor u; + typename graph_traits::edge_descriptor e; }; - // the core numbers start as the indegree or inweight. This function - // will initialize these values - template - void compute_in_degree_map(Graph& g, CoreMap d, EdgeWeightMap wm) - { - typename graph_traits::vertex_iterator vi,vi_end; - typename graph_traits::out_edge_iterator ei,ei_end; - for (tie(vi,vi_end) = vertices(g); vi!=vi_end; ++vi) { - put(d,*vi,0); - } - for (tie(vi,vi_end) = vertices(g); vi!=vi_end; ++vi) { - for (tie(ei,ei_end) = out_edges(*vi,g); ei!=ei_end; ++ei) { - put(d,target(*ei,g),get(d,target(*ei,g))+get(wm,*ei)); - } - } - } + template + class core_numbers_visitor : public bfs_visitor { + public: + core_numbers_visitor() {} + core_numbers_visitor(Visitors vis) + : bfs_visitor(vis) {} - // the version for weighted graphs is a little different - template - typename property_traits::value_type - core_numbers_impl(Graph& g, CoreMap c, EdgeWeightMap wm, MutableQueue& Q) - { - typename property_traits::value_type v_cn = 0; - typedef typename graph_traits::vertex_descriptor vertex; - while (!Q.empty()) + private: + template + void initialize_vertex(Vertex, Graph&) {} + + template + void discover_vertex(Vertex , Graph&) {} + + template + void gray_target(Vertex, Graph&) {} + + template + void black_target(Vertex, Graph&) {} + + template + void tree_edge(Edge, Graph&) {} + + template + void non_tree_edge(Edge, Graph&) {} + }; + + template + core_numbers_visitor make_core_numbers_visitor(Visitors vis) + { return core_numbers_visitor(vis); }; + + typedef core_numbers_visitor<> default_core_numbers_visitor; + + namespace detail { + + // implement a constant_property_map to simplify compute_in_degree + // for the weighted and unweighted case + // this is based on dummy property map + template + class constant_value_property_map + : public boost::put_get_helper > { - // remove v from the Q, and then decrease the core numbers - // of its successors - vertex v = Q.top(); - Q.pop(); - v_cn = get(c,v); - typename graph_traits::out_edge_iterator oi,oi_end; - for (tie(oi,oi_end) = out_edges(v,g); oi!=oi_end; ++oi) { - vertex u = target(*oi,g); - // if c[u] > c[v], then u is still in the graph, - if (get(c,u) > v_cn) { - // remove the edge - put(c,u,get(c,u)-get(wm,*oi)); - Q.update(u); + public: + typedef void key_type; + typedef ValueType value_type; + typedef const ValueType& reference; + typedef boost::readable_property_map_tag category; + inline constant_value_property_map(ValueType cc) : c(cc) { } + inline constant_value_property_map(const constant_value_property_map& x) + : c(x.c) { } + template + inline reference operator[](Vertex) const { return c; } + protected: + ValueType c; + }; + + + // the core numbers start as the indegree or inweight. This function + // will initialize these values + template + void compute_in_degree_map(Graph& g, CoreMap d, EdgeWeightMap wm) + { + typename graph_traits::vertex_iterator vi,vi_end; + typename graph_traits::out_edge_iterator ei,ei_end; + for (tie(vi,vi_end) = vertices(g); vi!=vi_end; ++vi) { + put(d,*vi,0); + } + for (tie(vi,vi_end) = vertices(g); vi!=vi_end; ++vi) { + for (tie(ei,ei_end) = out_edges(*vi,g); ei!=ei_end; ++ei) { + put(d,target(*ei,g),get(d,target(*ei,g))+get(wm,*ei)); } } } - return (v_cn); - } - template - typename property_traits::value_type - core_numbers_dispatch(Graph&g, CoreMap c, EdgeWeightMap wm, IndexMap im) - { - 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); - typename graph_traits::vertex_iterator vi,vi_end; - for (tie(vi,vi_end) = vertices(g); vi!=vi_end; ++vi) { - Q.push(*vi); + // the version for weighted graphs is a little different + template + typename property_traits::value_type + core_numbers_impl(Graph& g, CoreMap c, EdgeWeightMap wm, + MutableQueue& Q, Visitor vis) + { + typename property_traits::value_type v_cn = 0; + typedef typename graph_traits::vertex_descriptor vertex; + while (!Q.empty()) + { + // remove v from the Q, and then decrease the core numbers + // of its successors + vertex v = Q.top(); + vis.examine_vertex(v,g); + Q.pop(); + v_cn = get(c,v); + typename graph_traits::out_edge_iterator oi,oi_end; + for (tie(oi,oi_end) = out_edges(v,g); oi!=oi_end; ++oi) { + vis.examine_edge(*oi,g); + vertex u = target(*oi,g); + // if c[u] > c[v], then u is still in the graph, + if (get(c,u) > v_cn) { + // remove the edge + put(c,u,get(c,u)-get(wm,*oi)); + Q.update(u); + } + } + vis.finish_vertex(v,g); + } + return (v_cn); } - return core_numbers_impl(g, c, wm, Q); - } - // the version for the unweighted case - // for this functions CoreMap must be initialized - // with the in degree of each vertex - template + template + typename property_traits::value_type + core_numbers_dispatch(Graph&g, CoreMap c, EdgeWeightMap wm, + IndexMap im, CoreNumVisitor vis) + { + 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); + typename graph_traits::vertex_iterator vi,vi_end; + for (tie(vi,vi_end) = vertices(g); vi!=vi_end; ++vi) { + Q.push(*vi); + } + return core_numbers_impl(g, c, wm, Q, vis); + } + + // the version for the unweighted case + // for this functions CoreMap must be initialized + // with the in degree of each vertex + template + typename property_traits::value_type + core_numbers_impl(Graph& g, CoreMap c, PositionMap pos, Visitor vis) + { + typedef typename graph_traits::vertices_size_type size_type; + typedef typename graph_traits::degree_size_type degree_type; + typedef typename graph_traits::vertex_descriptor vertex; + typename graph_traits::vertex_iterator vi,vi_end; + + // store the vertex core numbers + typename property_traits::value_type v_cn = 0; + + // compute the maximum degree (degrees are in the coremap) + typename graph_traits::degree_size_type max_deg = 0; + for (tie(vi,vi_end) = vertices(g); vi!=vi_end; ++vi) { + max_deg = (std::max::degree_size_type>)(max_deg, get(c,*vi)); + } + + // store the vertices in bins by their degree + // allocate two extra locations to ease boundary cases + std::vector bin(max_deg+2); + for (tie(vi,vi_end) = vertices(g); vi!=vi_end; ++vi) { + ++bin[get(c,*vi)]; + } + + // this loop sets bin[d] to the starting position of vertices + // with degree d in the vert array for the bucket sort + size_type cur_pos = 0; + for (degree_type cur_deg = 0; cur_deg < max_deg+2; ++cur_deg) { + degree_type tmp = bin[cur_deg]; + bin[cur_deg] = cur_pos; + cur_pos += tmp; + } + + // perform the bucket sort with pos and vert so that + // pos[0] is the vertex of smallest degree + std::vector vert(num_vertices(g)); + for (tie(vi,vi_end) = vertices(g); vi!=vi_end; ++vi) { + vertex v=*vi; + size_type p=bin[get(c,v)]; + put(pos,v,p); + vert[p]=v; + ++bin[get(c,v)]; + } + // we ``abused'' bin while placing the vertices, now, + // we need to restore it + std::copy(boost::make_reverse_iterator(bin.end()-2), + boost::make_reverse_iterator(bin.begin()), + boost::make_reverse_iterator(bin.end()-1)); + // now simulate removing the vertices + for (size_type i=0; i < num_vertices(g); ++i) { + vertex v = vert[i]; + vis.examine_vertex(v,g); + v_cn = get(c,v); + typename graph_traits::out_edge_iterator oi,oi_end; + for (tie(oi,oi_end) = out_edges(v,g); oi!=oi_end; ++oi) { + vis.examine_edge(*oi,g); + vertex u = target(*oi,g); + // if c[u] > c[v], then u is still in the graph, + if (get(c,u) > v_cn) { + degree_type deg_u = get(c,u); + degree_type pos_u = get(pos,u); + // w is the first vertex with the same degree as u + // (this is the resort operation!) + degree_type pos_w = bin[deg_u]; + vertex w = vert[pos_w]; + if (u!=v) { + // swap u and w + put(pos,u,pos_w); + put(pos,w,pos_u); + vert[pos_w] = u; + vert[pos_u] = w; + } + // now, the vertices array is sorted assuming + // we perform the following step + // start the set of vertices with degree of u + // one into the future (this now points at vertex + // w which we swapped with u). + ++bin[deg_u]; + // we are removing v from the graph, so u's degree + // decreases + put(c,u,get(c,u)-1); + } + } + vis.finish_vertex(v,g); + } + return v_cn; + } + + } // namespace detail + + // non-named parameter version for the unweighted case + template typename property_traits::value_type - core_numbers_impl(Graph& g, CoreMap c, PositionMap pos) + core_numbers(Graph& g, CoreMap c, CoreNumVisitor vis) { typedef typename graph_traits::vertices_size_type size_type; - typedef typename graph_traits::degree_size_type degree_type; - typedef typename graph_traits::vertex_descriptor vertex; - typename graph_traits::vertex_iterator vi,vi_end; - - // store the vertex core numbers - typename property_traits::value_type v_cn = 0; - - // compute the maximum degree (degrees are in the coremap) - typename graph_traits::degree_size_type max_deg = 0; - for (tie(vi,vi_end) = vertices(g); vi!=vi_end; ++vi) { - max_deg = (std::max)(max_deg, get(c,*vi)); - } - // store the vertices in bins by their degree - // allocate two extra locations to ease boundary cases - std::vector bin(max_deg+2); - for (tie(vi,vi_end) = vertices(g); vi!=vi_end; ++vi) { - ++bin[get(c,*vi)]; - } - // this loop sets bin[d] to the starting position of vertices - // with degree d in the vert array for the bucket sort - size_type cur_pos = 0; - for (degree_type cur_deg = 0; cur_deg < max_deg+2; ++cur_deg) { - degree_type tmp = bin[cur_deg]; - bin[cur_deg] = cur_pos; - cur_pos += tmp; - } - // perform the bucket sort with pos and vert so that - // pos[0] is the vertex of smallest degree - std::vector vert(num_vertices(g)); - for (tie(vi,vi_end) = vertices(g); vi!=vi_end; ++vi) { - vertex v=*vi; - size_type p=bin[get(c,v)]; - put(pos,v,p); - vert[p]=v; - ++bin[get(c,v)]; - } - // we ``abused'' bin while placing the vertices, now, - // we need to restore it - std::copy(boost::make_reverse_iterator(bin.end()-2), - boost::make_reverse_iterator(bin.begin()), - boost::make_reverse_iterator(bin.end()-1)); - // now simulate removing the vertices - for (size_type i=0; i < num_vertices(g); ++i) { - vertex v = vert[i]; - v_cn = get(c,v); - typename graph_traits::out_edge_iterator oi,oi_end; - for (tie(oi,oi_end) = out_edges(v,g); oi!=oi_end; ++oi) { - vertex u = target(*oi,g); - // if c[u] > c[v], then u is still in the graph, - if (get(c,u) > v_cn) { - degree_type deg_u = get(c,u); - degree_type pos_u = get(pos,u); - // w is the first vertex with the same degree as u - // (this is the resort operation!) - degree_type pos_w = bin[deg_u]; - vertex w = vert[pos_w]; - if (u!=v) { - // swap u and w - put(pos,u,pos_w); - put(pos,w,pos_u); - vert[pos_w] = u; - vert[pos_u] = w; - } - // now, the vertices array is sorted assuming - // we perform the following step - // start the set of vertices with degree of u - // one into the future (this now points at vertex - // w which we swapped with u). - ++bin[deg_u]; - // we are removing v from the graph, so u's degree - // decreases - put(c,u,get(c,u)-1); - } - } - } - return v_cn; + detail::compute_in_degree_map(g,c, + detail::constant_value_property_map< + typename property_traits::value_type>(1) ); + return detail::core_numbers_impl(g,c, + make_iterator_property_map( + std::vector(num_vertices(g)).begin(),get(vertex_index, g)), + vis + ); } -} // namespace detail + // non-named paramter version for the unweighted case + template + typename property_traits::value_type + core_numbers(Graph& g, CoreMap c) + { + return core_numbers(g, c, make_core_numbers_visitor(null_visitor())); + } -template -typename property_traits::value_type -core_numbers(Graph& g, CoreMap c) -{ - typedef typename graph_traits::vertices_size_type size_type; - detail::compute_in_degree_map(g,c, - detail::constant_value_property_map< - typename property_traits::value_type>(1) ); - return detail::core_numbers_impl(g,c, - make_iterator_property_map( - std::vector(num_vertices(g)).begin(),get(vertex_index, g)) - ); -} + // non-named parameter version for the weighted case + template + typename property_traits::value_type + 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); + } -template -typename property_traits::value_type -core_numbers(Graph& g, CoreMap c, EdgeWeightMap wm, VertexIndexMap vim) -{ - 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); -} + // non-named parameter version for the weighted case +// template +// typename property_traits::value_type +// core_numbers(Graph& g, CoreMap c, EdgeWeightMap wm) +// { +// 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,get(vertex_index,g), +// make_core_numbers_visitor(null_visitor())); +// } -template -typename property_traits::value_type -core_numbers(Graph& g, CoreMap c, EdgeWeightMap wm) -{ - 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,get(vertex_index,g)); -} + template + typename property_traits::value_type + weighted_core_numbers(Graph& g, CoreMap c) + { + return weighted_core_numbers( + g,c, make_core_numbers_visitor(null_visitor()) + ); + } -template -typename property_traits::value_type -weighted_core_numbers(Graph& g, CoreMap c) -{ return core_numbers(g,c,get(edge_weight,g)); } + template + typename property_traits::value_type + weighted_core_numbers(Graph& g, CoreMap c, CoreNumVisitor vis) + { return core_numbers(g,c,get(edge_weight,g),get(vertex_index,g),vis); } } // namespace boost diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index e1cee11e..fd1b3ce4 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -105,6 +105,7 @@ test-suite graph_test : [ run mean_geodesic.cpp ] [ run eccentricity.cpp ] [ run clustering_coefficient.cpp ] + [ run core_numbers_test.cpp ] $(optional_tests) ; diff --git a/test/core_numbers_test.cpp b/test/core_numbers_test.cpp new file mode 100644 index 00000000..337c285c --- /dev/null +++ b/test/core_numbers_test.cpp @@ -0,0 +1,149 @@ + +#include +#include +#include +#include + +using namespace boost; + +const char* errstr = ""; + +int test_1() { + // core numbers of sample graph + typedef adjacency_list Graph; + + Graph G(21); + add_edge(0,1,G); + add_edge(1,2,G); + add_edge(1,3,G); + add_edge(2,3,G); + add_edge(1,4,G); + add_edge(3,4,G); + add_edge(4,5,G); + add_edge(4,6,G); + add_edge(5,6,G); + add_edge(4,7,G); + add_edge(5,7,G); + add_edge(6,7,G); + add_edge(7,8,G); + add_edge(3,9,G); + add_edge(8,9,G); + add_edge(8,10,G); + add_edge(9,10,G); + add_edge(10,11,G); + add_edge(10,12,G); + add_edge(3,13,G); + add_edge(9,13,G); + add_edge(3,14,G); + add_edge(9,14,G); + add_edge(13,14,G); + add_edge(16,17,G); + add_edge(16,18,G); + add_edge(17,19,G); + add_edge(18,19,G); + add_edge(19,20,G); + + std::vector core_nums(num_vertices(G)); + core_numbers(G, + make_iterator_property_map(core_nums.begin(), get(vertex_index,G))); + + for (size_t i=0; i > graph_t; + int num_nodes = 3; + typedef std::pair Edge; + + Edge edge_array[] = { Edge(0,1), Edge(0,2), Edge(1,2) }; + int weights[] = {-1, -2, -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, + make_iterator_property_map(core_nums.begin(), get(vertex_index,G))); + + for (size_t i=0; i graph_t; + int num_nodes = 5; + typedef std::pair Edge; + + Edge edge_array[] = { Edge(0,1),Edge(1,2),Edge(2,3),Edge(3,4),Edge(4,0) }; + int num_arcs = sizeof(edge_array) / sizeof(Edge); + + graph_t G(edge_array, edge_array + num_arcs, num_nodes); + + std::vector core_nums(num_vertices(G)); + core_numbers(G, + make_iterator_property_map(core_nums.begin(), get(vertex_index,G))); + + for (size_t i=0; i Date: Sat, 14 Feb 2009 13:53:55 +0000 Subject: [PATCH 095/224] Importing quickbook docs from SOC 2007 [SVN r51250] --- quickbook/Jamfile.v2 | 84 ++ quickbook/bibliography.qbk | 19 + quickbook/boost_concepts.qbk | 49 ++ quickbook/boost_reference.qbk | 154 ++++ quickbook/concepts/a_star_visitor.qbk | 72 ++ quickbook/concepts/adjacency_graph.qbk | 69 ++ quickbook/concepts/adjacency_matrix.qbk | 50 ++ quickbook/concepts/bellman_ford_visitor.qbk | 70 ++ quickbook/concepts/bfs_visitor.qbk | 105 +++ quickbook/concepts/bidirectional_graph.qbk | 76 ++ quickbook/concepts/clique_visitor.qbk | 53 ++ quickbook/concepts/concepts.qbk | 37 + quickbook/concepts/cycle_visitor.qbk | 53 ++ quickbook/concepts/degree_measure.qbk | 62 ++ quickbook/concepts/descriptor.qbk | 28 + quickbook/concepts/dfs_visitor.qbk | 99 +++ quickbook/concepts/dijkstra_visitor.qbk | 87 ++ quickbook/concepts/distance_measure.qbk | 78 ++ quickbook/concepts/edge_index_graph.qbk | 115 +++ quickbook/concepts/edge_list_graph.qbk | 98 +++ quickbook/concepts/event_visitor.qbk | 175 ++++ quickbook/concepts/event_visitor_list.qbk | 70 ++ quickbook/concepts/graph.qbk | 72 ++ quickbook/concepts/graphs.qbk | 241 ++++++ quickbook/concepts/incidence_graph.qbk | 95 +++ quickbook/concepts/mutable_graph.qbk | 174 ++++ quickbook/concepts/mutable_property_graph.qbk | 64 ++ quickbook/concepts/numeric_value.qbk | 77 ++ quickbook/concepts/property_graph.qbk | 86 ++ quickbook/concepts/utility.qbk | 17 + quickbook/concepts/vertex_index_graph.qbk | 115 +++ quickbook/concepts/vertex_list_graph.qbk | 75 ++ quickbook/concepts/visitor.qbk | 20 + quickbook/concepts/visitors.qbk | 30 + quickbook/graph.qbk | 55 ++ quickbook/guide/adjacency_list.qbk | 480 +++++++++++ quickbook/guide/directed_graph.qbk | 371 +++++++++ quickbook/guide/guide.qbk | 14 + quickbook/guide/undirected_graph.qbk | 473 +++++++++++ quickbook/history.qbk | 110 +++ quickbook/images/eq/Makefile | 36 + quickbook/images/eq/betweenness.tex | 15 + .../images/eq/central_point_dominance.tex | 16 + quickbook/images/eq/closeness.tex | 15 + quickbook/images/eq/clustering_coef.tex | 14 + quickbook/images/eq/mean_geodesic.tex | 15 + quickbook/images/eq/num_paths_directed.tex | 14 + quickbook/images/eq/num_paths_undirected.tex | 16 + quickbook/images/eq/num_triangles.tex | 14 + quickbook/images/eq/relative_betweenness.tex | 16 + quickbook/images/eq/scaled_closeness.tex | 15 + quickbook/images/eq/small_world.tex | 20 + quickbook/images/reference/Makefile | 46 ++ quickbook/images/reference/comm_network.neato | 17 + .../reference/connected_components_after.dot | 12 + .../reference/connected_components_before.dot | 5 + .../reference/distribution_directed.circo | 11 + .../reference/distribution_undirected.circo | 11 + quickbook/images/reference/geodesic.dot | 15 + quickbook/images/reference/info_network.dot | 13 + quickbook/images/reference/prism_3_2.circo | 7 + quickbook/images/reference/social_network.fdp | 14 + quickbook/images/reference/triangle.circo | 3 + quickbook/introduction.qbk | 214 +++++ quickbook/reference/adjacency_list.qbk | 411 +++++++++ .../reference/betweenness_centrality.qbk | 185 +++++ quickbook/reference/breadth_first_search.qbk | 153 ++++ .../reference/bron_kerbosch_all_cliques.qbk | 191 +++++ quickbook/reference/closeness_centrality.qbk | 302 +++++++ .../reference/clustering_coefficient.qbk | 199 +++++ quickbook/reference/connected_components.qbk | 94 +++ quickbook/reference/degree_centrality.qbk | 440 ++++++++++ quickbook/reference/depth_first_search.qbk | 161 ++++ quickbook/reference/directed_graph.qbk | 779 ++++++++++++++++++ quickbook/reference/distance_recorder.qbk | 99 +++ quickbook/reference/eccentricity.qbk | 337 ++++++++ quickbook/reference/edge_list.qbk | 10 + .../reference/exterior_vertex_property.qbk | 106 +++ quickbook/reference/mean_geodesic.qbk | 361 ++++++++ quickbook/reference/predecessor_recorder.qbk | 103 +++ quickbook/reference/property_writer.qbk | 103 +++ quickbook/reference/reference.qbk | 79 ++ quickbook/reference/strong_components.qbk | 116 +++ quickbook/reference/tiernan_all_cycles.qbk | 299 +++++++ quickbook/reference/time_stamper.qbk | 104 +++ quickbook/reference/undirected_graph.qbk | 743 +++++++++++++++++ quickbook/sgi_concepts.qbk | 41 + quickbook/theory.qbk | 252 ++++++ quickbook/tour.qbk | 508 ++++++++++++ quickbook/tutorial.qbk | 17 + 90 files changed, 11039 insertions(+) create mode 100644 quickbook/Jamfile.v2 create mode 100644 quickbook/bibliography.qbk create mode 100644 quickbook/boost_concepts.qbk create mode 100644 quickbook/boost_reference.qbk create mode 100644 quickbook/concepts/a_star_visitor.qbk create mode 100644 quickbook/concepts/adjacency_graph.qbk create mode 100644 quickbook/concepts/adjacency_matrix.qbk create mode 100644 quickbook/concepts/bellman_ford_visitor.qbk create mode 100644 quickbook/concepts/bfs_visitor.qbk create mode 100644 quickbook/concepts/bidirectional_graph.qbk create mode 100644 quickbook/concepts/clique_visitor.qbk create mode 100644 quickbook/concepts/concepts.qbk create mode 100644 quickbook/concepts/cycle_visitor.qbk create mode 100644 quickbook/concepts/degree_measure.qbk create mode 100644 quickbook/concepts/descriptor.qbk create mode 100644 quickbook/concepts/dfs_visitor.qbk create mode 100644 quickbook/concepts/dijkstra_visitor.qbk create mode 100644 quickbook/concepts/distance_measure.qbk create mode 100644 quickbook/concepts/edge_index_graph.qbk create mode 100644 quickbook/concepts/edge_list_graph.qbk create mode 100644 quickbook/concepts/event_visitor.qbk create mode 100644 quickbook/concepts/event_visitor_list.qbk create mode 100644 quickbook/concepts/graph.qbk create mode 100644 quickbook/concepts/graphs.qbk create mode 100644 quickbook/concepts/incidence_graph.qbk create mode 100644 quickbook/concepts/mutable_graph.qbk create mode 100644 quickbook/concepts/mutable_property_graph.qbk create mode 100644 quickbook/concepts/numeric_value.qbk create mode 100644 quickbook/concepts/property_graph.qbk create mode 100644 quickbook/concepts/utility.qbk create mode 100644 quickbook/concepts/vertex_index_graph.qbk create mode 100644 quickbook/concepts/vertex_list_graph.qbk create mode 100644 quickbook/concepts/visitor.qbk create mode 100644 quickbook/concepts/visitors.qbk create mode 100644 quickbook/graph.qbk create mode 100644 quickbook/guide/adjacency_list.qbk create mode 100644 quickbook/guide/directed_graph.qbk create mode 100644 quickbook/guide/guide.qbk create mode 100644 quickbook/guide/undirected_graph.qbk create mode 100644 quickbook/history.qbk create mode 100644 quickbook/images/eq/Makefile create mode 100644 quickbook/images/eq/betweenness.tex create mode 100644 quickbook/images/eq/central_point_dominance.tex create mode 100644 quickbook/images/eq/closeness.tex create mode 100644 quickbook/images/eq/clustering_coef.tex create mode 100644 quickbook/images/eq/mean_geodesic.tex create mode 100644 quickbook/images/eq/num_paths_directed.tex create mode 100644 quickbook/images/eq/num_paths_undirected.tex create mode 100644 quickbook/images/eq/num_triangles.tex create mode 100644 quickbook/images/eq/relative_betweenness.tex create mode 100644 quickbook/images/eq/scaled_closeness.tex create mode 100644 quickbook/images/eq/small_world.tex create mode 100644 quickbook/images/reference/Makefile create mode 100644 quickbook/images/reference/comm_network.neato create mode 100644 quickbook/images/reference/connected_components_after.dot create mode 100644 quickbook/images/reference/connected_components_before.dot create mode 100644 quickbook/images/reference/distribution_directed.circo create mode 100644 quickbook/images/reference/distribution_undirected.circo create mode 100644 quickbook/images/reference/geodesic.dot create mode 100644 quickbook/images/reference/info_network.dot create mode 100644 quickbook/images/reference/prism_3_2.circo create mode 100644 quickbook/images/reference/social_network.fdp create mode 100644 quickbook/images/reference/triangle.circo create mode 100644 quickbook/introduction.qbk create mode 100644 quickbook/reference/adjacency_list.qbk create mode 100644 quickbook/reference/betweenness_centrality.qbk create mode 100644 quickbook/reference/breadth_first_search.qbk create mode 100644 quickbook/reference/bron_kerbosch_all_cliques.qbk create mode 100644 quickbook/reference/closeness_centrality.qbk create mode 100644 quickbook/reference/clustering_coefficient.qbk create mode 100644 quickbook/reference/connected_components.qbk create mode 100644 quickbook/reference/degree_centrality.qbk create mode 100644 quickbook/reference/depth_first_search.qbk create mode 100644 quickbook/reference/directed_graph.qbk create mode 100644 quickbook/reference/distance_recorder.qbk create mode 100644 quickbook/reference/eccentricity.qbk create mode 100644 quickbook/reference/edge_list.qbk create mode 100644 quickbook/reference/exterior_vertex_property.qbk create mode 100644 quickbook/reference/mean_geodesic.qbk create mode 100644 quickbook/reference/predecessor_recorder.qbk create mode 100644 quickbook/reference/property_writer.qbk create mode 100644 quickbook/reference/reference.qbk create mode 100644 quickbook/reference/strong_components.qbk create mode 100644 quickbook/reference/tiernan_all_cycles.qbk create mode 100644 quickbook/reference/time_stamper.qbk create mode 100644 quickbook/reference/undirected_graph.qbk create mode 100644 quickbook/sgi_concepts.qbk create mode 100644 quickbook/theory.qbk create mode 100644 quickbook/tour.qbk create mode 100644 quickbook/tutorial.qbk diff --git a/quickbook/Jamfile.v2 b/quickbook/Jamfile.v2 new file mode 100644 index 00000000..ddc0aeb0 --- /dev/null +++ b/quickbook/Jamfile.v2 @@ -0,0 +1,84 @@ + +# Copyright John Maddock 2005. Use, modification, and distribution are +# 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) + +using quickbook ; + +xml graph : graph.qbk ; + +boostbook standalone + : + graph + : + # HTML options first: + # Use graphics not text for navigation: + navig.graphics=1 + # How far down we chunk nested sections, basically all of them: + # Setting this to 4 will put all reference functions into the + # same page... and make all external links to those pages bounce + # to the top of them. + chunk.section.depth=5 + # Don't put the first section on the same page as the TOC: + chunk.first.sections=1 + # How far down sections get TOC's + toc.section.depth=5 + # Max depth in each TOC: + # I could increase this, but that makes the top-level ToC + # extremely long. + toc.max.depth=3 + # How far down we go with TOC's + generate.section.toc.level=5 + # Logo location: + boost.logo=../boost.png + annotation.support=1 + + # The page style + page.style="'website'" + # Show chapters select box + grouped.links.chapters.show="'true'" + # GroupedLinks xml definition chapters location + grouped.links.chapters.xml="'boost_libs_grouped_links.xml'" + # Select the base url for the chapters GroupedLinks + grouped.links.chapters.url="'http://www.boost.org/libs/'" + # Show sections select box + grouped.links.sections.show="'true'" + # GroupedLinks xml definition sections location + grouped.links.sections.xml="'sections_grouped_links.xml'" + # Select the base url for the chapters GroupedLinks + grouped.links.sections.url="'./'" + # Show the Google Search Box + search.box.show="'true'" + # Location of the cse defintion + search.box.cse.definition.src="'http://www.drivehq.com/web/matias.capeletto/bimap/doc/html/context8.xml'" + + # PDF Options: + # TOC Generation: this is needed for FOP-0.9 and later: + # fop1.extensions=1 + xep.extensions=1 + # TOC generation: this is needed for FOP 0.2, but must not be set to zero for FOP-0.9! + fop.extensions=0 + # No indent on body text: + body.start.indent=0pt + # Margin size: + page.margin.inner=0.5in + # Margin size: + page.margin.outer=0.5in + # Yes, we want graphics for admonishments: + admon.graphics=1 + # Set this one for PDF generation *only*: + # default pnd graphics are awful in PDF form, + # better use SVG's instead: + #admon.graphics.extension=".svg" + ; + + + + + + + + + + + diff --git a/quickbook/bibliography.qbk b/quickbook/bibliography.qbk new file mode 100644 index 00000000..99cdd913 --- /dev/null +++ b/quickbook/bibliography.qbk @@ -0,0 +1,19 @@ +[/ + / Copyright (c) 2007 Andrew Sutton + / + / 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) + /] + +[bibliography] + +[bibentry + [authors [Sutter, Herb], [Alexandrescu, Andrei]] + [title C++ Coding Standards: 101 Rules, Guidelines, and Best Practices] + [book + [publisher Addison Wesley] + [copyright 1985 Pearson Education, Inc.] + [pages 220] +] + +[endbib] \ No newline at end of file diff --git a/quickbook/boost_concepts.qbk b/quickbook/boost_concepts.qbk new file mode 100644 index 00000000..0023af28 --- /dev/null +++ b/quickbook/boost_concepts.qbk @@ -0,0 +1,49 @@ +[/ + / Copyright (C) 2007-2009 Andrew Sutton + / + / 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) + /] + +[/ Iterator concepts /] +[template MultiPassInputIterator[] [@http://www.boost.org/libs/utility/MultiPassInputIterator.html MultipPassInputIterator]] + +[/ Property map concpepts /] +[template ReadablePropertyMap[] [@http://www.boost.org/libs/property_map/ReadablePropertyMap.html [^ReadablePropertyMap]]] +[template WritablePropertyMap[] [@http://www.boost.org/libs/property_map/WritablePropertyMap.html [^WritablePropertyMap]]] +[template ReadWritePropertyMap[] [@http://www.boost.org/libs/property_map/ReadWritePropertyMap.html [^ReadWritePropertyMap]]] + +[/ Boost Graph concepts /] +[template Graph[] [link boost_graph.concepts.graph_concepts.graph [^Graph]]] +[template IncidenceGraph[] [link boost_graph.concepts.graph_concepts.incidence_graph [^IncidenceGraph]]] +[template BidirectionalGraph[] [link boost_graph.concepts.graph_concepts.bidirectional_graph [^BidirectionalGraph]]] +[template VertexListGraph[] [link boost_graph.concepts.graph_concepts.vertex_list_graph [^VertexListGraph]]] +[template EdgeListGraph[] [link boost_graph.concepts.graph_concepts.edge_list_graph [^EdgeListGraph]]] +[template AdjacencyGraph[] [link boost_graph.concepts.graph_concepts.adjacency_graph [^AdjacencyGraph]]] +[template AdjacencyMatrix[] [link boost_graph.concepts.graph_concepts.adjacency_matrix [^AdjacencyMatrix]]] +[template MutableGraph[] [link boost_graph.concepts.graph_concepts.mutable_graph [^MutableGraph]]] +[template PropertyGraph[] [link boost_graph.concepts.graph_concepts.property_graph [^PropertyGraph]]] +[template MutablePropertyGraph[] [link boost_graph.concepts.graph_concepts.mutable_property_graph [^MutablePropertyGraph]]] +[template VertexIndexGraph[] [link boost_graph.concepts.graph_concepts.vertex_index_graph [^VertexIndexGraph]]] +[template EdgeIndexGraph[] [link boost_graph.concepts.graph_concepts.edge_index_graph [^EdgeIndexGraph]]] + +[/ Boost Graph Visitor concepts /] +[template Visitor[] [link boost_graph.concepts.visitor_concepts.visitor Visitor]] +[template BFSVisitor[] [link boost_graph.concepts.visitor_concepts.breadth_first_search_visitor BreadthFirstSearchVisitor]] +[template DFSVisitor[] [link boost_graph.concepts.visitor_concepts.depth_first_search_visitor DepthFirstSearchVisitor]] +[template DijkstraVisitor[] [link boost_graph.concepts.visitor_concepts.dijksta_visitor DijkstraVisitor]] +[template BellmanfordVisitor[] [link boost_graph.concepts.visitor_concepts.bellmanford_visitor BellmanFordVisitor]] +[template AStarVisitor[] [link boost_graph.concepts.visitor_concepts.a_star_visitor A\*Visitor]] +[template CliqueVisitor[] [link boost_graph.concepts.visitor_concepts.clique_visitor [^CliqueVisitor]]] +[template CycleVisitor[] [link boost_graph.concepts.visitor_concepts.cycle_visitor [^CycleVisitor]]] +[template EventVisitor[] [link boost_graph.concepts.visitor_concepts.event_visitor EventVisitor]] +[template EventVisitorList[] [link boost_graph.concepts.visitor_concepts.event_visitor_list EventVisitorList]] + +[/ A bunch of miscellaneus graph-related concepts /] +[template ColorValue[] [link boost_graph.concepts.miscellaneous_concepts.color_value ColorValue]] +[template Descriptor[] [link boost_graph.concepts.graph_concepts.descriptor [^Descriptor]]] +[template NumericValue[] [link boost_graph.concepts.general_concepts.numeric_value [^NumericValue]]] +[template PropertyMap[] [link boost_graph.concepts.general_concepts.property_map [^PropertyMap]]] +[template PropertyMatrix[] [link boost_graph.concepts.general_concepts.property_matrix [^PropertyMatrix]]] +[template DegreeMeasure[] [link boost_graph.concepts.general_concepts.degree_measure [^DegreeMeasure]]] +[template DistanceMeasure[] [link boost_graph.concepts.general_concepts.distance_measure [^DistanceMeasure]]] diff --git a/quickbook/boost_reference.qbk b/quickbook/boost_reference.qbk new file mode 100644 index 00000000..500acecf --- /dev/null +++ b/quickbook/boost_reference.qbk @@ -0,0 +1,154 @@ +[/ + / Copyright (C) 2007-2009 Andrew Sutton + / + / 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 contains macros that links against the reference section. /] + +[template constant_property_map[] [link graph [^constant_property_map]]] + +[/ Graph traits and types /] +[template graph_traits[] [link boost_graph.reference.traits_classes.graph_traits [^graph_traits]]] +[template undirected_graph[] [link boost_graph.reference.graph_types.undirected_graph [^undirected_graph]]] +[template directed_graph[] [link boost_graph.reference.graph_types.directed_graph [^directed_graph]]] +[template adjacency_list[] [link boost_graph.reference.graph_types.adjacency_list [^adjacecncy_list]]] +[template edge_list[] [link boost_graph.reference.graph_types.edge_list [^edge_list]]] + +[/ Visitor types /] +[template null_visitor[] [link boost_graph.reference.visitor_types.null_visitor [^null_visitor]]] +[template bfs_visitor[] [link boost_graph.reference.visitor_types.bfs_visitor [^bfs_visitor]]] +[template dfs_visitor[] [link boost_graph.reference.visitor_types.dfs_visitor [^dfs_visitor]]] +[template predecessor_recorder[] [link boost_graph.reference.event_visitors.predecessor_recorder [^predecessor_recorder]]] +[template distance_recorder[] [link boost_graph.reference.event_visitors.distance_recorder [^distance_recorder]]] +[template time_stamper[] [link boost_graph.reference.event_visitors.time_stamper [^time_stamper]]] +[template property_writer[] [link boost_graph.reference.event_visitors.property_writer [^property_writer]]] + +[/ Fundamental /] +[template breadth_first_search[] [link + boost_graph.reference.algorithms.fundamental.breadth_first_search + [^breadth_first_search()]]] +[template depth_first_search[] [link + boost_graph.reference.algorithms.fundamental.depth_first_search + [^depth_first_search()]]] + +[/ Shortest Path /] +[template dijkstra_shortest_paths[] [link + boost_graph.reference.algorithms.shortest_paths.dijkstra_shortest_paths + [^dijkstra_shortest_paths()]]] +[template bellman_ford_shortest_paths[] [link + boost_graph.reference.algorithms.shortest_paths.bellman_ford_shortest_paths + [^bellman_ford_shortest_paths()]]] +[template floyd_warshall_all_pairs_shortest_paths[] [link + boost_graph.reference.algorithms.shortest_paths.floyd_warshall_all_pairs_shortest_paths + [^floyd_warshall_all_pairs_shortest_paths()]]] +[template johnson_all_pairs_shortest_paths[] [link + boost_graph.reference.algorithms.shortest_paths.johnson_all_pairs_shortest_paths + [^johnson_all_pairs_shortest_paths()]]] + +[/ Connectivity /] +[template connected_components[] [link + boost_graph.reference.algorithms.connectivity.connected_components + [^connected_components()]]] +[template strong_connected_components[] [link + boost_graph.reference.algorithms.connectivity.strongly_connected_components + [^strongly_connected_components]]] + +[/ Subgraph/ ] +[template bron_kerbosch_visit_cliques[] [link + boost_graph.reference.algorithms.subgraph.bron_kerbosch_all_cliques + [^bron_kerbosch_all_cliques()]]] + +[template tiernan_all_cycles[] [link + boost_graph.reference.algorithms.subgraph.tiernan_all_cycles.__tiernan_all_cycles___ + [^tiernan_all_cycles()]]] +[template tiernan_girth[] [link + boost_graph.reference.algorithms.subgraph.tiernan_all_cycles.__tiernan_girth___ + [^tiernan_girth()]]] +[template tiernan_circumference[] [link + boost_graph.reference.algorithms.subgraph.tiernan_all_cycles.__tiernan_circumference___ + [^tiernan_circumference()]]] +[template tiernan_girth_and_circumference[] [link + boost_graph.reference.algorithms.subgraph.tiernan_all_cycles.__tiernan_girth_and_circumference___ + [^tiernan_girth_and_circumference()]]] + +[template bron_kerbosch_all_cliques[] [link + boost_graph.reference.algorithms.subgraph.bron_kerbosch_all_cliques.__bron_kerbosch_all_cliques___ + [^bron_kerbosch_all_cliques()]]] +[template bron_kerbosch_clique_number[] [link + boost_graph.reference.algorithms.subgraph.bron_kerbosch_all_cliques.__bron_kerbosch_clique_number___ + [^bron_kerbosch_clique_number()]]] + + +[/ Measures /] +[template degree_centrality[] [link + boost_graph.reference.algorithms.measures.degree_centrality.__degree_centrality___ + [^degree_centrality()]]] +[template all_degree_centralities[] [link + boost_graph.reference.algorithms.measures.degree_centrality.__all_degree_centralities___ + [^all_degree_centralities()]]] +[template closeness_centrality[] [link + boost_graph.reference.algorithms.measures.closeness_centrality.__closeness_centrality___ + [^closeness_centrality()]]] +[template all_closeness_centralities[] [link + boost_graph.reference.algorithms.measures.closeness_centrality.__all_closeness_centralities___ + [^all_closeness_centralities()]]] +[template mean_geodesic[] [link + boost_graph.reference.algorithms.measures.mean_geodesic.__mean_geodesic___ + [^mean_geodesic()]]] +[template all_mean_geodesics[] [link + boost_graph.reference.algorithms.measures.mean_geodesic.__all_mean_geodesics___ + [^all_mean_geodesics()]]] +[template small_world_distance[] [link + boost_graph.reference.algorithms.measures.mean_geodesic.__small_world_distance___ + [^small_world_distance()]]] +[template eccentricity[] [link + boost_graph.reference.algorithms.measures.eccentricity.__eccentricity___ + [^eccentricity()]]] +[template eccentricities[] [link + boost_graph.reference.algorithms.measures.eccentricity.__eccentricities___ + [^eccentricities()]]] +[template radius[] [link + boost_graph.reference.algorithms.measures.eccentricity.__radius___ + [^radius()]]] +[template diameter[] [link + boost_graph.reference.algorithms.measures.eccentricity.__diameter___ + [^diameter()]]] +[template radius_and_diameter[] [link + boost_graph.reference.algorithms.measures.eccentricity.__radius_and_diameter___ + [^radius_and_diameter()]]] +[template clustering_coefficient[] [link + boost_graph.reference.algorithms.measures.clustering_coefficient.__clustering_coefficient___ + [^clustering_coefficient()]]] +[template all_clustering_coefficients[] [link + boost_graph.reference.algorithms.measures.clustering_coefficient.__all_clustering_coefficients___ + [^all_clustering_coefficients()]]] +[template num_paths_through_vertex[] [link + boost_graph.reference.algorithms.measures.clustering_coefficient.__num_paths_through_vertex___ + [^num_paths_through_vertex()]]] +[template num_triangles_on_vertex[] [link + boost_graph.reference.algorithms.measures.clustering_coefficient.__num_triangles_on_vertex___ + [^num_triangles_on_vertex()]]] + + +[template exterior_vertex_property[] [link + graph + [^exterior_vertex_property]]] +[template exterior_edge_property[] [link + graph + [^exterior_edge_property]]] + +[/ Import lots of examples to build code templates] +[import ../examples/degree_centrality.cpp] +[import ../examples/influence_prestige.cpp] +[import ../examples/closeness_centrality.cpp] +[import ../examples/scaled_closeness_centrality.cpp] +[import ../examples/mean_geodesic.cpp] +[import ../examples/inclusive_mean_geodesic.cpp] +[import ../examples/eccentricity.cpp] +[import ../examples/clustering_coefficient.cpp] +[import ../examples/tiernan_print_cycles.cpp] +[import ../examples/tiernan_girth_circumference.cpp] +[import ../examples/bron_kerbosch_print_cliques.cpp] +[import ../examples/bron_kerbosch_clique_number.cpp] diff --git a/quickbook/concepts/a_star_visitor.qbk b/quickbook/concepts/a_star_visitor.qbk new file mode 100644 index 00000000..3c5fdeb2 --- /dev/null +++ b/quickbook/concepts/a_star_visitor.qbk @@ -0,0 +1,72 @@ +[/ + / Copyright (c) 2007 Andrew Sutton + / + / 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) + /] + +[section Graph] +The Graph concept contains a few requirements that are common to all the graph concepts. +These include some associated types for vertex_descriptor, edge_descriptor, etc. One +should note that a model of Graph is not required to be a model of Assignable, so algorithms +should pass graph objects by reference (or `const` reference). + +[h4 Associated Types] +[table + [[Type] [Description]] + [ + [`graph_traits::vertex_descriptor`] + [ + A vertex descriptor corresponds to a unique vertex in a graph. A vertex descriptor + must be DefaultConstructible, Assignable, and EqualityComparable. Vertex + descriptors are almost always passed by value. + ] + ] + [ + [`graph_traits::edge_descriptor`] + [ + An edge descriptor corresponds to a unqie edge /(u,v)/ in a graph. An edge descriptor + must be DefaultConstructible, Assignable, and EqualityComparable. Edge descriptors + are almost always passed by value. + ] + ] + [ + [`graph_traits::directed_category`] + [ + This type shall be convertible to `directed_tag` or `undirected_tag`. + ] + ] + [ + [`graph_traits::edge_parallel_category`] + [ + This describes whether the graph class allows the insertion of parallel edges + (multiple edges between the same source and target vertices). The two tags are + `allow_parallel_edge_tag` and `disallow_parallel_edge_tag`. + ] + ] + [ + [`graph_traits::traversal_category`] + [ + This describes the ways in which the vertices and edge of the graph can be visited. + The choices are `incidence_graph_tag`, `adjacency_graph_tag`, `bidirectional_graph_tag`, + `vertex_list_graph_tag`, `edge_list_graph_tag`, and `adjacency_matrix_tag`. + ] + ] +] + +[h4 Valid Expressions] +[table + [[Expression] [Description]] + [ + [`graph_traits::null_vertex()`] + [ + Returns a special `vertex_descriptor` which does not refer to any vertex for graphs + of type `G`. Note that default initialization of `vertex_descriptors` are /not/ + guaranteed to be equal to then `null_vertex()`. + + *Returns* `vertex_descriptor` + ] + ] +] + +[endsect] diff --git a/quickbook/concepts/adjacency_graph.qbk b/quickbook/concepts/adjacency_graph.qbk new file mode 100644 index 00000000..50369665 --- /dev/null +++ b/quickbook/concepts/adjacency_graph.qbk @@ -0,0 +1,69 @@ +[/ + / Copyright (c) 2007 Andrew Sutton + / + / 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) + /] + +[section Adjacency Graph] +The AdjacencyGraph concept provides and interface for efficient access of the adjacent vertices +to a vertex in a graph. This is quite similar to the IncidenceGraph concept (the target of an +out-edge is an adjacent vertex). Both concepts are provided because in some contexts there is only +concern for the vertices, whereas in other contexts the edges are also important. + +[h4 Refinement Of] +[Graph] + +[h4 Associated Types] +[table + [[Type] [Description]] + [ + [`graph_traits::traversal_category`] + [ + This tag type must be convertible to `adjacency_graph_tag`. + ] + ] + [ + [`graph_traits::adjacency_iterator`] + [ + An adjacency iterator for a vertex v provides access to the vertices adjacent to v. + As such, the value type of an adjacency iterator is the vertex descriptor type of its + graph. An adjacency iterator must meet the requirements of [MultiPassInputIterator]. + ] + ] +] + +[h4 Valid Expressions] +[table + [[Expression] [Description]] + [ + [`adjacent_vertices(v,g)`] + [ + Returns an iterator-range providing access to the vertices adjacent to vertex `v` in + the graph `g`. + + *Returns* `std::pair` + ] + ] +] + +[h4 Complexity Guarantees] +The `adjacent_vertices(v,g)` function must return in constant time. + +[h4 Design Rationale] +The AdjacencyGraph concept is somewhat frivolous since [IncidenceGraph] really covers the same +functionality (and more). The AdjacencyGraph concept exists because there are situations when +`adjacent_vertices()` is more convenient to use than `out_edges()`. If you are constructing a graph +class and do not want to put in the extra work of creating an adjacency iterator, have no fear. There +is an adaptor class named `adjacency_iterator` that you can use to create an adjacency iterator out +of an out-edge iterator. + +[h4 Notes] +The case of a /multigraph/ (where multiple edges can connect the same two vertices) brings up an issue +as to whether the iterators returned by the `adjacent_vertices()` function access a range that includes +each adjacent vertex once, or whether it should match the behavior of the `out_edges()` function, and +access a range that may include an adjacent vertex more than once. For now the behavior is defined to +match that of `out_edges()`, though this decision may need to be reviewed in light of more experience +with graph algorithm implementations. + +[endsect] diff --git a/quickbook/concepts/adjacency_matrix.qbk b/quickbook/concepts/adjacency_matrix.qbk new file mode 100644 index 00000000..17f64da9 --- /dev/null +++ b/quickbook/concepts/adjacency_matrix.qbk @@ -0,0 +1,50 @@ +[/ + / Copyright (c) 2007 Andrew Sutton + / + / 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) + /] + +[section Adjacency Matrix] +The AdjacencyMatrix concept refines `Graph` concept and adds the requirement for efficient access +to any edge in the graph given the source and target vertices. No Boost.Graph algorithms currently +use this concept. However there are algorithms not yet implemented such as Floyd-Warshall that +would require this concept. + +[h4 Refinement Of] +[Graph] + +[h4 Associated Types] +[table + [[Type] [Description]] + [ + [`graph_traits::traversal_category`] + [ + This tag type must be convertible to `adjacency_matrix_tag`. + ] + ] +] + +[h4 Valid Expressions] +[table + [[Expression] [Description]] + [ + [`edge(u,v,g)`] + [ + Returns a pair consisting of a flag saying whether there exists an edge between `u` and + `v` in graph g, and consisting of the edge descriptor if the edge was found. + + *Returns* `std::pair` + ] + ] +] + +[h4 Complexity Guarantees] +The `edge(u,v,g)` function must return in constant time. + +[h4 Notes] +A number of graph classes (notably [undirected_graph], [directed_graph] and +[adjacency_list]) provide non-constant time implementations of this interface. Although +the function exists, none of these classes are documented as modeling this concept. + +[endsect] diff --git a/quickbook/concepts/bellman_ford_visitor.qbk b/quickbook/concepts/bellman_ford_visitor.qbk new file mode 100644 index 00000000..fc3cbed5 --- /dev/null +++ b/quickbook/concepts/bellman_ford_visitor.qbk @@ -0,0 +1,70 @@ +[/ + / Copyright (c) 2007 Andrew Sutton + / + / 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) + /] + +[section Bellman Ford Visitor] +This concept defines the visitor interface for [bellman_ford_shortest_paths]. Users +can define a class with the Bellman Ford Visitor interface and pass and object of the +class to [bellman_ford_shortest_paths], thereby augmenting the actions taken during the +graph search. + +[h4 Refinement Of] +[Visitor] + +[h4 Valid Expressions] +[table + [[Expression] [Description]] + [ + [`vis.examine_edge(v,g)`] + [ + This is invoked on every out-edge of each vertex after it is discovered. + + *Returns* `void` + ] + ] + [ + [`vis.edge_relaxed(e,g)`] + [ + If the relaxation predicate holds for this given edge then this method is invoked. + See [dijkstra_shortest_paths] for more information on relaxation. + + *Returns* `void` + ] + ] + [ + [`vis.edge_not_relaxed(e,g)`] + [ + If the relaxation predicate does not hold for this edge, then this method is invoked. + See [dijkstra_shortest_paths] for more information on relaxation. + + *Returns* `void` + ] + ] + [ + [`vis.edge_minimized(e,g)`] + [ + After the `num_vertices(g)` iterators through the edge det of the graph is complete, + one last iteration is made to test whether each edge was minimized. If the edge is + minimized then this function is invoked. + + *Returns* `void` + ] + ] + [ + [`vis.edge_relaxed(e,g)`] + [ + If the edge is not minimized then this function is invoked. This happens when there + is a negative weight cycle in the graph. + + *Returns* `void` + ] + ] +] + +[h4 Models] +* [bellman_ford_visitor] + +[endsect] diff --git a/quickbook/concepts/bfs_visitor.qbk b/quickbook/concepts/bfs_visitor.qbk new file mode 100644 index 00000000..a4e5a308 --- /dev/null +++ b/quickbook/concepts/bfs_visitor.qbk @@ -0,0 +1,105 @@ +[/ + / Copyright (c) 2007 Andrew Sutton + / + / 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) + /] + +[section Breadth-First Search Visitor] +This concept defines the visitor interface for [booost_breadth_first_search] algorithm. Users +can define a class with the BFS Visitor interface and pass and object of the class to +[breadth_first_search], thereby augmenting the actions taken during the graph search. + +[h4 Refinement Of] +[Visitor] + +[h4 Valid Expressions] +[table + [[Expression] [Description]] + [ + [`vis.initialize_vertex(v,g)`] + [ + This is invoked on every vertex of the graph before the start of the graph search. + + *Returns* `void` + ] + ] + [ + [`vis.discover_vertex(v,g)`] + [ + This is invoked when a vertex is encountered for the first time. + + *Returns* `void` + ] + ] + [ + [`vis.examine_vertex(v,g)`] + [ + This is invoked on a vertex as it is popped from the queue. This happens immediately + before `examine_edge(v,g)` s invoked on each of the out-edges of vertex `v`. + + *Returns* `void` + ] + ] + [ + [`vis.examine_edge(e,g)`] + [ + This is invoked on every out-edge of each vertex after it is discovered. + + *Returns* `void` + ] + ] + [ + [`vis.tree_edge(e,g)`] + [ + This is invoked on each edge as it becomes a member of the eges that the form the + search tree. + + *Returns* `void` + ] + ] + [ + [`vis.non_tree_edge(v,g)`] + [ + This is invoked on back or cross edges for directed graphs and cross edges + for undirected graphs. + + *Returns* `void` + ] + ] + [ + [`vis.gray_target(e,g)`] + [ + This is invoked on the subset of non-tree-edges who's target vertex is colored gray + at the time of examination. The color gray indicates that the vertex is currently + in the queue. + + *Returns* `void` + ] + ] + [ + [`vis.black_target(v,g)`] + [ + This is invoked on the subset of non-tree edges who's target vertex is colored black + at the time of examination. The color black indicates that the vertex has been removed + from the queue. + + *Returns* `void` + ] + ] + [ + [`vis.finish_vertex(v,g)`] + [ + This is invoked on a vertex after all of its out edges have been added to the search + tree and all of the adjacenct vertices have been discovered, but before the out-edges + of the adjacent vertices have been examined. + + *Returns* `void` + ] + ] +] + +[h4 Models] +* [bfs_visitor] + +[endsect] diff --git a/quickbook/concepts/bidirectional_graph.qbk b/quickbook/concepts/bidirectional_graph.qbk new file mode 100644 index 00000000..a645c3f4 --- /dev/null +++ b/quickbook/concepts/bidirectional_graph.qbk @@ -0,0 +1,76 @@ +[/ + / Copyright (c) 2007 Andrew Sutton + / + / 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) + /] + +[section Bidirectional Graph] +The BidirectionalGraph concept refines IncidenceGraph and adds the requirement for efficient +access to the in-edges of each vertex. This concept is separated from IncidenceGraph because for +directed graphs efficient access to in-edges typically requires more storage space, and many +algorithms do not require access to in-edges. For undirected graphs this is not an issue, since +the in_edges() and out_edges() functions are the same, they both return the edges incident to +the vertex. + +[heading Refinement Of] +[IncidenceGraph] + +[h4 Associated Types] +[table + [[Type] [Description]] + [ + [`graph_traits::traversal_category`] + [ + This tag type must be convertible to `bidirectional_graph_tag`. + ] + ] + [ + [`graph_traits::in_edge_iterator`] + [ + An in-edge iterator for a vertex v provides access to the in-edges of a vertex. As + such, the value type of an in-edge iterator is the edge descriptor type of its graph. + An in-edge iterator must meet the requirements of MultiPassInputIterator. + ] + ] +] + +[h4 Valid Expressions] +[table + [[Expression] [Description]] + [ + [`in_edges(v,g)`] + [ + Returns an iterator range providing access to the in-edges (for directed graphs) + or the incident edges (for undirected graphs). The target vertex of an edge obtained + via an in-edge iterator is guaranteed to be the vertex `v` in the call to + `in_edges(v,g)`, and the source vertex must be adjacenct to `v`. + + *Returns* `std::pair` + ] + ] + [ + [`in_degree(v,g)`] + [ + Returns the number of in-edges (for directed graphs) or the number of incident + edges (for undirected graphs) of the vertex `v`. + + *Returns* `degree_size_type`. + ] + ] +] + +[h4 Models] +* [undirected_graph] +* [directed_graph] +* [adjacency_list] with the `Directed` template parameter as `bidirectionalS` or +`undirectedS`. + +[h4 Complexity Guarantees] +The `in_edges(g)` function is required to return in constant time. + +The `in_degree()` and `degree()` functions must be linear in the number of in-edges (for +directed graph) or incident edges (for undirected graphs). + + +[endsect] diff --git a/quickbook/concepts/clique_visitor.qbk b/quickbook/concepts/clique_visitor.qbk new file mode 100644 index 00000000..00bc977a --- /dev/null +++ b/quickbook/concepts/clique_visitor.qbk @@ -0,0 +1,53 @@ +[/ + / Copyright (c) 2007 Andrew Sutton + / + / 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) + /] + +[section Clique Visitor] +The clique visitor concept defines requirements for types that act as visitors +of clique-detection algorithms. Objects of this type are passed to these +algorithms and are invoked when a clique is found within a graph. + +[heading Refinement Of] +[Visitor] + +[heading Expressions] +[table + [[Name] [Expression] [Result Type] [Description]] + [ + [Visit Clique] + [`vis.clique(vs,g)`] + [`void`] + [ + The `clique()` member function of the visitor is invoked when a fully + connected subgraph is identified in the graph `g`. + + *Requirements:* `g` is an object whose type `G` is a refinement of the + [Graph] concept. + + *Requirements:* `vs` is an object whose type `VS` is a refinement of the + [SgiContainer] concept. The `value_type` of `VS` must be the `vertex_descriptor` + of `G`. + + *Precondition:* All vertices in the [SgiContainer] `vs` are connected. + If `g` is a directed graph, then all vertices, /u/ and /v/, are connected + by edges /(u,v)/ and /(v,u)/. + ] + ] +] + +[heading C++0x] +This concept is defined as: + + concept CliqueVisitor + { + Graph graph_type; + + template + requires SameType + void T::clique(const VertexSet&, graph_type&); + }; + +[endsect] diff --git a/quickbook/concepts/concepts.qbk b/quickbook/concepts/concepts.qbk new file mode 100644 index 00000000..f4a39927 --- /dev/null +++ b/quickbook/concepts/concepts.qbk @@ -0,0 +1,37 @@ +[/ + / Copyright (c) 2007 Andrew Sutton + / + / 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) + /] + +[section Concepts] +This section provides a detailed listing of the type concepts in the Boost.Graph +library. + +[heading Notation] +For the following sections, we use the following notional convents: + +[table + [[Object] [Type]] + [[G] [A type that is a model of a [Graph] (or refinement thereof)]] + [[g] [An object of type G]] + [[u,v] [Objects of type `graph_traits::vertex_descriptor`]] + [[e] [An object of type `graph_traits::edge_descriptor`]] + [[vi] [An object of type `graph_traits::vertex_iterator`]] + [[ei] [An object of type `graph_traits::edge_iterator`]] + [[vp] [An object of type `G::vertex_property_type`]] + [[ep] [An object of type `G::edge_property_type`]] + [[Property] [A type used to specify a vertex or edge property. Also called a /tag/.]] + [[p] [An object of type Property]] + [[Predicate] [A function that, given an argument, returns true or false]] + [[pred] [An object of type [SgiPredicate]]] + [[V] [A type that is a model of a [Visitor] (or refinement thereof)]] + [[vis] [An object of type V]] +] + +[include utility.qbk] +[include graphs.qbk] +[include visitors.qbk] + +[endsect] diff --git a/quickbook/concepts/cycle_visitor.qbk b/quickbook/concepts/cycle_visitor.qbk new file mode 100644 index 00000000..4511d836 --- /dev/null +++ b/quickbook/concepts/cycle_visitor.qbk @@ -0,0 +1,53 @@ +[/ + / Copyright (c) 2007 Andrew Sutton + / + / 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) + /] + +[section Cycle Visitor] +The cycle visitor concept defines requirements for types that act as visitors +of cycle-detection algorithms. Objects of this type are passed to these +algorithms and are invoked when a cycle is found within a graph. + +[heading Refinement Of] +[Visitor] + +[heading Valid Expressions] +[table + [[Name] [Expression] [Result Type] [Description]] + [ + [Visit Cycle] + [`vis.cycle(vs,g)`] + [`void`] + [ + The `vis.cycle()` member function of the visitor is invoked when a + cycle is identified in the graph `g`. The vertices in `vs` are arranged + such that first vertex is connected to the second, and that is connected + to the third, etc. The `back()` vertex is connected to the `front()` + to form a cycle. + + *Requirements:* `g` is an object whose type `G` is a model of the + [Graph] concept. + + *Requirements:* `vs` is an object whose type `VertexSet` is a model + of the [SgiContainer] concept. The `value_type` of `VS` must be the + the same as the `vertex_descriptor` of `G`. + ] + ] +] + +[heading C++0x] +This concept is defined as: + + concept CliqueVisitor + { + Graph graph_type; + + template + requires SameType + void T::cycle(const VertexSet&, graph_type&); + }; + + +[endsect] diff --git a/quickbook/concepts/degree_measure.qbk b/quickbook/concepts/degree_measure.qbk new file mode 100644 index 00000000..1b59b14d --- /dev/null +++ b/quickbook/concepts/degree_measure.qbk @@ -0,0 +1,62 @@ +[/ + / Copyright (c) 2007 Andrew Sutton + / + / 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) + /] + +[section Degree Measure] +The [DegreeMeasure] concept defines requirements for function objects +that are used in computations on the degree of a vertex. + +[heading Notation] +The following expressions are used within this document: +[table + [[Expression] [Description]] + [[M] [A type modeling the [DegreeMeasure] concept.]] + [[m] [An object of type `M`.]] + [[G] [A type modeling the [Graph] concept.]] + [[g] [An object of type `G`.]] + [[v] [An object of type `graph_traits::vertex_descriptor`.]] +] + +[heading Associated Types] +[table + [[Name] [Type] [Description]] + [ + [Degree Type] + [`M::degree_type`] + [ + The result type of the computation. Note that unlike + `graph_traits::degree_size_type`, the `degree_type` is not + required to be numeric. + ] + ] +] + +[heading Expressions] +[table + [[Name] [Expression] [Result Type] [Description]] + [ + [Function Call] + [`m(v, g)`] + [`M::degree_type`] + [ + Invoke the measure on the vertex `v`, with respect + to the graph `g`. This returns the result as type `degree_type`. + ] + ] +] + +[heading C++0x] + + concept DegreeMeasure + { + typename Graph; + typename Vertex; + typename M::degree_type; + + degree_type M::operator(Vertex v, const Graph& g) + }; + +[endsect] diff --git a/quickbook/concepts/descriptor.qbk b/quickbook/concepts/descriptor.qbk new file mode 100644 index 00000000..fa79cd89 --- /dev/null +++ b/quickbook/concepts/descriptor.qbk @@ -0,0 +1,28 @@ +[/ + / Copyright (c) 2007 Andrew Sutton + / + / 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) + /] + +[section Descriptor] +The Descriptor concept describes requirements common to vertex and edge descriptors of +all graph types. + +[heading Refinement Of] +[SgiDefaultConstructible], [SgiCopyConstructible], [SgiAssignable], [SgiEqualityComparable], +and [SgiLessThanComparable]. + +[heading Associated Types] +There are no associated types of a Descriptor. + +[heading Valid Expressions] +Beyond the requirements of the refined concepts, the descriptor does not require any +additional valid expressions. + +[heading Notes] +Note that because both model the [SgiLessThanComparable] concept, they can be used as +keys in any associative container modeling the [SgiAssociativeContainer] concept +(e.g., `std::map`, `std::set`, etc). + +[endsect] diff --git a/quickbook/concepts/dfs_visitor.qbk b/quickbook/concepts/dfs_visitor.qbk new file mode 100644 index 00000000..487abd9d --- /dev/null +++ b/quickbook/concepts/dfs_visitor.qbk @@ -0,0 +1,99 @@ +[/ + / Copyright (c) 2007 Andrew Sutton + / + / 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) + /] + +[section Depth-First Search Visitor] +This concept defines the visitor interface for [booost_depth_first_search] algorithm. Users +can define a class with the DFS Visitor interface and pass and object of the class to +[boost_depth_first_search], thereby augmenting the actions taken during the graph search. + +[h4 Refinement Of] +[BoostVisitor] + +[h4 Valid Expressions] +[table + [[Expression] [Description]] + [ + [`vis.initialize_vertex(v,g)`] + [ + This is invoked on every vertex of the graph before the start of the graph search. + + *Returns* `void` + ] + ] + [ + [`vis.start_vertex(v,g)`] + [ + This is invoked on the source veretx once before the start of the search. + + *Returns* `void` + ] + ] + [ + [`vis.discover_vertex(v,g)`] + [ + This is invoked when a vertex is encountered for the first time. + + *Returns* `void` + ] + ] + [ + [`vis.examine_edge(e,g)`] + [ + This is invoked on every out-edge of each vertex after it is discovered. + + *Returns* `void` + ] + ] + [ + [`vis.tree_edge(e,g)`] + [ + This is invoked on each edge as it becomes a member of the eges that the form the + search tree. + + *Returns* `void` + ] + ] + [ + [`vis.back_edge(v,g)`] + [ + This is invoked on the back edges of the graph. For an unidrected graph there + is some ambiguity between tree edges and back edges since the edge /(u,v)/ + and /(v,u)/ are the same edge, but both `tree_edge(v,g)` and `back_edge(v,g)` + will be invoked. One way to resolve this ambiguity is to record the tree + edges and then disregard the back edges that are already marked as tree edges. + An easy way to record tree edges is to record predecessors at the `tree_edge` + event point. + + *Returns* `void` + ] + ] + [ + [`vis.forward_or_cross_edge(e,g)`] + [ + This is invoked on forward or cross edges in the graph. In an undirected graph, + this method is never called. + + *Returns* `void` + ] + ] + [ + [`vis.finish_vertex(v,g)`] + [ + This is invoked on a vertex after all `finish_vertex(x,g)` has been invoked for + all vertices in the search tree rooted at `v` (i.e., after all its children + have finished). If `v` is a leaf in the search tree, `finish_vertex(v,g)` is + called after all its out-edges have been examined. + + *Returns* `void` + ] + ] +] + +[h4 Models] +* [boost_dfs_visitor] + +[endsect] diff --git a/quickbook/concepts/dijkstra_visitor.qbk b/quickbook/concepts/dijkstra_visitor.qbk new file mode 100644 index 00000000..09b03639 --- /dev/null +++ b/quickbook/concepts/dijkstra_visitor.qbk @@ -0,0 +1,87 @@ +[/ + / Copyright (c) 2007 Andrew Sutton + / + / 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) + /] + +[section Dijkstra Visitor] +This concept defines the visitor interface for [dijkstra_shortest_paths] and related +algorithms. The user can create a class that matches this interface, and then pass objects +of the class into [dijkstra_shortest_paths] to augment the actions taken during the +search. + +[h4 Refinement Of] +[Visitor] + +[h4 Valid Expressions] +[table + [[Expression] [Description]] + [ + [`vis.initialize_vertex(v,g)`] + [ + This is invoked on every vertex of the graph before the start of the graph search. + + *Returns* `void` + ] + ] + [ + [`vis.discover_vertex(v,g)`] + [ + This is invoked when a vertex is encountered for the first time. This happens immediately + before `examine_edge()` is invoked on each of the out-edges of `v`. + + *Returns* `void` + ] + ] + [ + [`vis.examine_vertex(v,g)`] + [ + This is invoked on a vertex as it is popped from the queue. This happens immediately + before `examine_edge(v,g)` s invoked on each of the out-edges of vertex `v`. + + *Returns* `void` + ] + ] + [ + [`vis.examine_edge(v,g)`] + [ + This is invoked on every out-edge of each vertex after it is discovered. + + *Returns* `void` + ] + ] + [ + [`vis.edge_relaxed(e,g)`] + [ + If the relaxation predicate holds for this given edge then this method is invoked. + See [dijkstra_shortest_paths] for more information on relaxation. + + *Returns* `void` + ] + ] + [ + [`vis.edge_not_relaxed(e,g)`] + [ + If the relaxation predicate does not hold for this edge, then this method is invoked. + See [dijkstra_shortest_paths] for more information on relaxation. + + *Returns* `void` + ] + ] + [ + [`vis.finish_vertex(v,g)`] + [ + This 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 out edgs) + have been examined). + + *Returns* `void` + ] + ] +] + +[h4 Models] +* [dijkstra_visitor] + +[endsect] diff --git a/quickbook/concepts/distance_measure.qbk b/quickbook/concepts/distance_measure.qbk new file mode 100644 index 00000000..a5232e2a --- /dev/null +++ b/quickbook/concepts/distance_measure.qbk @@ -0,0 +1,78 @@ +[/ + / Copyright (c) 2007 Andrew Sutton + / + / 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) + /] + +[section Distance Measure] +The [DistanceMeasure] concept defines requirements for function objects +that are used in computations of distances. + +[heading Notation] +The following expressions are used within this document: +[table + [[Expression] [Description]] + [[M] [A type modeling the [DistanceMeasure] concept.]] + [[m] [An object of type `M`.]] + [[d] [An object of type `M::distance_type`.]] + [[G] [A type modeling the [Graph] concept.]] + [[g] [An object of type `G`.]] +] + +[heading Associated Types] +[table + [[Name] [Type] [Description]] + [ + [Distance Type] + [`M::distance_type`] + [ + The type used to measure distances in graphs. The `distance_type` + is typically derived from the value type of a distance map or + the edge-weight type of a graph type `G`. However, this is not + required. + + *Requirements:* The `distance_type` must be a model of the + [NumericValue] concept. + ] + ] + [ + [Result Type] + [`M::result_type`] + [ + The type being computed as the measure. + + *Requirements:* The `result_type` must be a model of the + [NumericValue] concept. + ] + ] +] + +[heading Expressions] +[table + [[Name] [Expression] [Result Type] [Description]] + [ + [Function Call] + [`m(d, g)`] + [`M::result_type`] + [ + Invoke the measure on the sum distance `d`, with respect + to the graph `g`. This returns the result as type `result_type`. + Note that in many computations `d` is given as the sum of distances + from one vertex to all others in the graph and may be infinite. + ] + ] +] + +[heading C++0x] + + concept DistanceMeasure + { + typename Graph; + typename M::distance_type; + typename M::result_type; + + result_type M::operator(distance_type, const Graph&); + }; + +[endsect] diff --git a/quickbook/concepts/edge_index_graph.qbk b/quickbook/concepts/edge_index_graph.qbk new file mode 100644 index 00000000..d736f2f6 --- /dev/null +++ b/quickbook/concepts/edge_index_graph.qbk @@ -0,0 +1,115 @@ +[/ + / Copyright (c) 2007 Andrew Sutton + / + / 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) + /] + +[section Edge Index Graph] +The [EdgeIndexGraph] concept requires that a graph type `G` provide edge indices +for each edge in the graph, and that those indices are ordered in the range +\[0, `num_edges(g)`). + +Because the removal of edges causes "gaps" in the index space, graphs that model +this concept must also provide functions that allow them to re-index the edges. + +[heading Refinement Of] +[MutablePropertyGraph] + +[heading Notation] +[table + [[Expression] [Description]] + [[`G`] [A type that models the [Graph] concept.]] + [[`g`] [An object of type `G`.]] + [ + [`P`] + [A synonym for `property_map`.] + ] +] + +[heading Associated Types] +[table + [[Name] [Expression] [Result Type] [Description]] + [ + [Edge Index Type] + [`property_traits::value_type`] + [An unsigned integer type] + [ + The unsigned integral type representing edge indices. + + *Requirements:* `T` must model the [NoConcept UnsignedIntegral] concept. + ] + ] + [ + [Edge Index Property Type] + [ + `P::type` + ] + [A mutable property map] + [ + The type of property map through which edge indices are readable and + writable. + + *Requirements:* This type must be a model of the [ReadWritePropertyMap] + concept. The `value_type` of the `property_traits` of this type must + be the same as `edge_index_type`. + ] + ] + [ + [Edge Index Property Type] + [ + `P::const_type` + ] + [ A `const` property map] + [ + The type of property map through which edge indices are readable. + + *Requirements:* This type must be a model of the [ReadablePropertyMap] + concept. The `value_type` of the `property_traits` of this type must + be the same as `edge_index_type`. + ] + ] +] + +[heading Requirements] +[table + [[Name] [Expression] [Result Type] [Description]] + [ + [Edge Index Property] + [`get(edge_index,g)`] + [ + `P::type` or[br] + `P::const_type` + ] + [ + Returns the property map that provides read/write access to the + edge indices of the graph. + + *Complexity:* Constant. + ] + ] + [ + [Edge Index] + [`get(edge_index,g,v)`] + [`G::edge_index_type`] + [ + Returns the index of the given edge within the graph. This is + equvalent to `get(get(edge_index, g), v)`. + + *Complexity:* Amortized constant. + ] + ] + [ + [Renumber Edge Indices] + [`renumber_edge_indices(g)`] + [] + [ + Renumbers all vertices in the graph such that each edge is in the + range \[0, `num_vertices(g)`). + + *Complexity:* Linear in `num_vertices(g)`. + ] + ] +] + +[endsect] diff --git a/quickbook/concepts/edge_list_graph.qbk b/quickbook/concepts/edge_list_graph.qbk new file mode 100644 index 00000000..2d0de24b --- /dev/null +++ b/quickbook/concepts/edge_list_graph.qbk @@ -0,0 +1,98 @@ +[/ + / Copyright (c) 2007 Andrew Sutton + / + / 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) + /] + +[section Edge List Graph] +The EdgeListGraph concept refines the [Graph] concept, and adds the requirement +for efficient access to all the edges in a graph. + +[h4 Refinement Of] +[Graph] + +[h4 Associated Types] +[table + [[Type] [Description]] + [ + [`graph_traits::traversal_category`] + [ + This tag type must be convertible to `edge_list_graph_tag`. + ] + ] + [ + [`graph_traits::edge_iterator`] + [ + An edge iterator (obtained via edges(g)) provides access to all of the edges + in a graph. An edge iterator type must meet the requirements of + [MultiPassInputIterator]. The value type of the edge iterator must be the + same as the edge descriptor of the graph. + ] + ] + [ + [`graph_traits::edges_size_type`] + [ + The unsigned integer type used to represent the number of edges in the graph. + ] + ] +] + +[h4 Valid Expressions] +[table + [[Expression] [Description]] + [ + [`edges(g)`] + [ + Returns an iterator range providing access to all the edges in the graph `g`. + + *Returns* `std::pair` + ] + ] + [ + [`num_edges(g)`] + [ + Returns the number of edges in the graph `g`. + + *Returns* `edges_size_type` + ] + ] + [ + [`source(e,g)`] + [ + If `e` is an edge /(u,v)/ in `g`, this function returns the source vertex `u`. + + *Returns* `vertex_descriptor` + ] + ] + [ + [`target(e,g)`] + [ + If `e` is an edge /(u,v)/ in `g`, this function returns the target vertex `v`. + + *Returns* `vertex_descriptor` + ] + ] +] + +[h4 Models] +* [undirected_graph] +* [directed_graph] +* [adjacency_list] +* [edge_list] + +[h4 Complexity Guarantees] +The `edges(g)`, `source(e,g)`, and `target(e,g)` functions must return in constant time. + +[h4 Design Rationale] +One issue in the design of this concept is whether to include the refinement from the +[IncidenceGraph] and [AdjacencyGraph] concepts. The ability to traverse the vertices +of a graph is orthogonal to traversing out-edges, so it would make sense to have a edgeListGraph +concept that only includes edge traversal. However, such a concept would no longer really be a +graph, but would just be a set, and the STL already has concepts for dealing with such things. +However, there are many BGL algorithms that need to traverse the vertices and out-edges of a graph, +so for convenience a concept is needed that groups these requirements together, hence the edgeListGraph +concept. + + +[endsect] diff --git a/quickbook/concepts/event_visitor.qbk b/quickbook/concepts/event_visitor.qbk new file mode 100644 index 00000000..f623362e --- /dev/null +++ b/quickbook/concepts/event_visitor.qbk @@ -0,0 +1,175 @@ +[/ + / Copyright (c) 2007 Andrew Sutton + / + / 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) + /] + +[section Event Visitor] +This concept defines the interface for single-event visitors. An EventVisitor has an +/apply/ member function (`operator()`) which is invoked within the graph algorithm +at the event-point specified by the `event_filter` typedef within the type modeling +the EventVisitor concept. EventVisitors can be combined into an [EventVistorList]. + +The following is the list of event tags that can be invoked in Boost.Graph algorithms. +Each tag corresponds to a member function of the visitor for an algorithm. For example, +the [BFSVisitor] of [[breadth_first_search] has a `cycle_edge()` member function. +The corresponding tag is `on_cycle_edge`. The first argument in the event visitor's +`operator()` must be either an edge or vertex depending on the event tag. + +[h4 Event Tags] +[table + [[Type] [Description]] + [ + [on_initialize_vertex] + [ + An event tag corresponding to the initialization of a vertex. The parameter + type associated with this event is `vertex_descriptor`. + ] + ] + [ + [on_start_vertex] + [ + In algorithms that without explicit starting points, this event tag + corresponds to the selection of a starting vertex. The parameter + type associated with this event is `vertex_descriptor`. + ] + ] + [ + [on_discover_vertex] + [ + An event tag that corresponds to a vertex that is being used for + the first time. The parameter type associated with this event is + `vertex_descriptor`. + ] + ] + [ + [on_examine_edge] + [ + An event tag that corresponds to the examination of edges for recently + discovered vertices. The parameter type associated with this event + is `edge_descriptor`. + ] + ] + [ + [on_tree_edge] + [ + For algorithms whose iterations of a vertex set implicitly define a + tree (such as [[breadth_first_search] or [[depth_first_search]), + this event tag corresponds to the identification of an edge that acts + as an edge in the search tree. The parameter type associated with this + event is `edge_descriptor`. + ] + ] + [ + [on_cycle_edge] + [ + For algorithms capable of detecting cycles in graphs such as + [[depth_first_search], this event tag is associated with discovery + of an edge that creates a cycle within the graph. The parameter type + associated with this event is `edge_descriptor`. + ] + ] + [ + [on_forward_or_cross_edge] + [ + Forward and cross edges refer to types of edges that can be found by + different types of searches on graph (e.g., [[depth_first_search]). + This event tag corresponds to the identification of such an edge by + the algorithm. The parameter type associated with this event is + `edge_descriptor`. + ] + ] + [ + [on_back_edge] + [ + Back edges refer to types of edges that can be found by different types + of searches on a graph (e.g., [[breadth_first_search] and + [[depth_first_search]). This event tag corresponds to the identification + of such an edge by the algorithm. The parameter type associated with this + event is `edge_descriptor`. + ] + ] + [ + [on_finish_vertex] + [ + The inverse event of `on_discover_vertex`, this event tag corresponds to + the completion of an iteration of an algorithm that is operating on a + vertex. The parametet type associated with this event is `edge_descriptor`. + ] + ] + [ + [on_edge_relaxed] + [ + For algorithms implementing edge relaxation (e.g., + [[dijkstra_shortest_paths]), this event corresponds to the case + where an edge is relaxed. The parameter type associated with this event + is `edge_descriptor`. + ] + ] + [ + [on_edge_not_relaxed] + [ + For algorithms implementing edge relaxation (e.g., + [[dijkstra_shortest_paths]), this event corresponds to the case + where an edge is not relaxed. The parameter type associated with this + event is `edge_descriptor`. + ] + ] + [ + [on_edge_minimized] + [ + For algorithms implementing edge minimization (e.g., + [[bellman_ford_shortest_paths]), this event corresponds to the case + where an edge is minimized. The parameter type associated with this event + is `edge_descriptor`. + ] + ] + [ + [on_edge_not_minimized] + [ + For algorithms implementing edge minimization (e.g., + [[bellman_ford_shortest_paths]), this event corresponds to the case + where an edge is not minimized. The parameter type associated with this + event is `edge_descriptor`. + ] + ] +] + +[h4 Refinement Of] +[Visitor] + +[h4 Associated Types] +[table + [[Type] [Description]] + [ + [`V::event_filter`] + [ + A tag to specify on which even the visitor should be invoked. + ] + ] +] + +[h4 Valid Expressions] +[table + [[Expression] [Description]] + [ + [`vis(x,g)`] + [ + Invokes the `operator()` member function of an object `vis` of type + `V`. The parameter `x` is either a vertex or edge of the graph `g`. The + specific type of parameter depends on `V::event_filter`. + + *Returns* `void` + ] + ] +] + +[h4 Models] +* [[predecessor_recorder] +* [[distance_recorder] +* [[time_stamper] +* [[property_writer] +* [[null_visitor] + +[endsect] diff --git a/quickbook/concepts/event_visitor_list.qbk b/quickbook/concepts/event_visitor_list.qbk new file mode 100644 index 00000000..0846cdfc --- /dev/null +++ b/quickbook/concepts/event_visitor_list.qbk @@ -0,0 +1,70 @@ +[/ + / Copyright (c) 2007 Andrew Sutton + / + / 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) + /] + +[section Event Visitor List] +An EventVisitorList is either an [EventVisitor], or a list of [EventVisitor] +combined using `std::pair`. Each graph algorithm defines visitor adaptors that convert an +EventVisitorList into the particular kind of visitor needed by the algorithm. In the +following example we will show how to combine event visitors into a list using `std::pair` +and how to use an algorithm's visitor adaptor class. + +Suppose we would like to print out the parenthesis structure of the discover/finish times +of vertices in a depth-first search. We can use the Boost.Graph algorithm [depth_first_search] +and two event visitors to accomplish this. The complete source code for the following example +is in `examples/dfs_parenthesis.cpp`. First we define the two event visitors. We use +`on_discover_vertex` and `on_finish_vertex` as the event points, selected from the list of +event points specified in [DFSVisitor]. + + struct open_paren : public base_visitor + { + typedef on_discover_vertex event_filter; + + template + void operator ()(Vertex v, Graph& G) + { + cout << "(" << v; + } + }; + + + struct close_paren : public base_visitor + { + typedef on_discover_vertex event_filter; + + template + void operator ()(Vertex v, Graph& G) + { + cout << v << ")"; + } + }; + +Next, we create two event visitor objects and combine them so the resultant type models +the EventVisitorList concept. + + make_pair(open_paren(), close_paren()); + +Next we want to pass this list into [[depth_first_search], but it is +expecting a [DFSVisitor], not a [EventVisitorList]. We therefore use the [[dfs_visitor] +adaptor which turns an [EventVisitor] list into a [DFSVisitor]. Like all of the visitor +adaptors, [dfs_visitor] has a creation function called [[make_dfs_visitor]. + + make_dfs_visitor((open_paren(), close_paren())); + +Now we can pass the resulting visitor object into [[depth_first_search] as follows. + + depth_first_search( + G, + make_dfs_visitor(make_pair(open_paren(), close_paren()))); + +For creating a list of more than two event visitors, nest calls to `make_pair` in the following way +to recursively produce an EventVisitorList. + + make_pair(visitor1, + make_pair(visitor2, ... + make_pair(visitorN - 1, visitorN)...)) + +[endsect] diff --git a/quickbook/concepts/graph.qbk b/quickbook/concepts/graph.qbk new file mode 100644 index 00000000..3c5fdeb2 --- /dev/null +++ b/quickbook/concepts/graph.qbk @@ -0,0 +1,72 @@ +[/ + / Copyright (c) 2007 Andrew Sutton + / + / 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) + /] + +[section Graph] +The Graph concept contains a few requirements that are common to all the graph concepts. +These include some associated types for vertex_descriptor, edge_descriptor, etc. One +should note that a model of Graph is not required to be a model of Assignable, so algorithms +should pass graph objects by reference (or `const` reference). + +[h4 Associated Types] +[table + [[Type] [Description]] + [ + [`graph_traits::vertex_descriptor`] + [ + A vertex descriptor corresponds to a unique vertex in a graph. A vertex descriptor + must be DefaultConstructible, Assignable, and EqualityComparable. Vertex + descriptors are almost always passed by value. + ] + ] + [ + [`graph_traits::edge_descriptor`] + [ + An edge descriptor corresponds to a unqie edge /(u,v)/ in a graph. An edge descriptor + must be DefaultConstructible, Assignable, and EqualityComparable. Edge descriptors + are almost always passed by value. + ] + ] + [ + [`graph_traits::directed_category`] + [ + This type shall be convertible to `directed_tag` or `undirected_tag`. + ] + ] + [ + [`graph_traits::edge_parallel_category`] + [ + This describes whether the graph class allows the insertion of parallel edges + (multiple edges between the same source and target vertices). The two tags are + `allow_parallel_edge_tag` and `disallow_parallel_edge_tag`. + ] + ] + [ + [`graph_traits::traversal_category`] + [ + This describes the ways in which the vertices and edge of the graph can be visited. + The choices are `incidence_graph_tag`, `adjacency_graph_tag`, `bidirectional_graph_tag`, + `vertex_list_graph_tag`, `edge_list_graph_tag`, and `adjacency_matrix_tag`. + ] + ] +] + +[h4 Valid Expressions] +[table + [[Expression] [Description]] + [ + [`graph_traits::null_vertex()`] + [ + Returns a special `vertex_descriptor` which does not refer to any vertex for graphs + of type `G`. Note that default initialization of `vertex_descriptors` are /not/ + guaranteed to be equal to then `null_vertex()`. + + *Returns* `vertex_descriptor` + ] + ] +] + +[endsect] diff --git a/quickbook/concepts/graphs.qbk b/quickbook/concepts/graphs.qbk new file mode 100644 index 00000000..15eba8c1 --- /dev/null +++ b/quickbook/concepts/graphs.qbk @@ -0,0 +1,241 @@ +[/ + / Copyright (c) 2007 Andrew Sutton + / + / 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) + /] + +[section Graph Concepts] +The heart of the Boost Graph Library (BGL) is the interface, or concepts (in the +parlance of generic programming), that define how a graph can be examined and +manipulated in a data-structure neutral fashion. In fact, the BGL interface need +not even be implemented using a data-structure, as for some problems it is easier +or more efficient to define a graph implicitly based on some functions. + +The Boost.Graph interface does not appear as a single graph concept. Instead it is +factored into much smaller peices. The reason for this is that the purpose of a +concept is to summarize the requirements for particular algorithms. Any one algorithm +does not need every kind of graph operation, typically only a small subset. Furthermore, +there are many graph data-structures that can not provide efficient implementations of +all the operations, but provide highly efficient implementations of the operations +necessary for a particular algorithm . By factoring the graph interface into many smaller +concepts we provide the graph algorithm writer with a good selection from which to choose +the concept that is the closest match for their algorithm. + +Figure 1 shows the refinements relations between the graph concepts. The reason for +factoring the graph interface into so many concepts is to encourage algorithm interfaces +to require and use only the minimum interface of a graph, thereby increasing the +usability of the algorithm. + +[$images/concepts/graph_concepts.png] + +Table 1 gives a summary of the valid expressions and associated types for the graph +concepts and provides links to the detailed descriptions of each of the concepts. +The notation used in the table is as follows. + +[table + [[Expression] [Return Type or Description]] + [[[*[Graph]]]] + [[`graph_traits::vertex_descriptor`] [The type for vertex representative objects.]] + [[`graph_traits::edge_descriptor`] [The type for edge representative objects.]] + [[`graph_traits::directed_category`] [Graph is directed or undirected?]] + [[`graph_traits::edge_parallel_category`] [Graph allows parallel edges?]] + [[`graph_traits::traversal_category`] [The ways in which the vertices and edges can be traversed.]] + [[[*[IncidenceGraph]]]] + [[`graph_traits::degree_size_type`] [The integer type for vertex degree.]] + [[`graph_traits::out_edge_iterator`] [Type for iterating over out edges.]] + [[`out_edges(v,g)`] [`std::pair`]] + [[`out_degree(v,g)`] [`degree_size_type`]] + [[`source(e,g)`] [`vertex_descriptor`]] + [[`target(e,g)`] [`vertex_descriptor`]] + [[[*[BidirectionalGraph]]]] + [[`graph_traits::in_edge_iterator`] [Type for iterating over in edges.]] + [[`in_edges(v,g)`] [`std::pair`]] + [[`in_degree(v,g)`] [`degree_size_type`]] + [[`degree(v,g)`] [`degree_size_type`]] + [[[*[AdjacencyGraph]]]] + [[`graph_traits::adjacency_iterator`] [Type for iterating over adjacent vertices.]] + [[`adjacent_vertices(v,g)`] [`std::pair`]] + [[[*[VertexListGraph]]]] + [[`graph_traits::vertex_iterator`] [Type for iterating over vertices.]] + [[`graph_traits::vertices_size_type`] [Unsigned integer type for the number of vertices.]] + [[`vertices(g)`] [`std::pair`]] + [[`num_vertices(g)`] [`vertices_size_type`]] + [[[*[EdgeListGraph]]]] + [[`graph_traits::edge_iterator`] [Type for iterating over edges.]] + [[`graph_traits::edges_size_type`] [Unsigned integer type for the number of edges.]] + [[`edges(g)`] [`std::pair`]] + [[`num_edges(g)`] [`edges_size_type`]] + [[`source(e,g)`] [`vertex_descriptor`]] + [[`target(e,g)`] [`vertex_descriptor`]] + [[[*[AdjacencyMatrix]]]] + [[`edge(u,v,g)`] [`std::pair`]] + [[[*[MutableGraph]]]] + [[`add_vertex(g)`] [`vertex_descriptor`]] + [[`clear_vertex(v,g)`] [`void`]] + [[`clear_out_edges(v,g)`] [`void`]] + [[`clear_in_edges(v,g)`] [`void`]] + [[`add_edge(u,v,g)`] [`std::pair`]] + [[`remove_edge(u,v,g)`] [`void`]] + [[`remove_edge(e,g)`] [`void`]] + [[`remove_edge(ei,g)`] [`void`]] + [[`remove_edge_if(pred,g)`] [`void`]] + [[`remove_out_edge_if(v,pred,g)`] [`void`]] + [[`remove_in_edge_if(v,pred,g)`] [`void`]] + [[[*[PropertyGraph]]]] + [[`property_map::type`] [Type for a mutable property map.]] + [[`property_map::const_type`] [Type for a non-mutable property map.]] + [[`get(p,g)`] [Function to get a property map.]] + [[`get(p,g,x)`] [Get the property value for vertex or edge `x`]] + [[`put(p,g,x,v`)] [Set the property value for vertex or edge `x` to value `v`.]] + [[[*[MutablePropertyGraph]]]] + [[`add_vertex(vp,g)`] [`vertex_descriptor`]] + [[`add_edge(u,v,ep,g)`] [`std::pair`]] +] + +[include graph.qbk] +[include incidence_graph.qbk] +[include bidirectional_graph.qbk] +[include adjacency_graph.qbk] +[include vertex_list_graph.qbk] +[include edge_list_graph.qbk] +[include adjacency_matrix.qbk] +[include mutable_graph.qbk] +[include property_graph.qbk] +[include mutable_property_graph.qbk] + +[heading Pseudo-Concepts] +The concepts above describe the type and functional requirements of graphs. However, +these do not directly common concepts such as "directed graph" or "multigraph". As +such, there are a number of pseudo-concepts with which we can also describe graph objects. + +[heading Directed and Undirected Graphs] +The interface that Boost.Graph provides for accessing and manipulating an undirected +graph is the same as the interface for directed graphs described in the following +sections, however there are some differences in the behaviour and semantics. For example, +in a directed graph we can talk about out-edges and in-edges of a vertex. In an +undirected graph there is no "in" and "out", there are just edges incident to a vertex. +Nevertheless, in Boost.Graph we still use the `out_edges()` function (or `in_edges()`) +to access the incident edges in an undirected graph. Similarly, an undirected edge has +no "source" and "target" but merely an unordered pair of vertices, but we still use +`source()` and `target()` to access these vertices. The reason Boost.Graph does not +provide a separate interface for undirected graphs is that many algorithms on directed +graphs also work on undirected graphs, and it would be inconvenient to have to duplicate +the algorithms just because of an interface difference. When using undirected graphs +just mentally disregard the directionality in the function names. The example below +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`. + + + const int V = 2; + typedef ... UndirectedGraph; + UndirectedGraph graph(V); + + std::cout << "the edges incident to v: "; + boost::graph_traits::out_edge_iterator e, e_end; + boost::graph_traits::vertex_descriptor s = vertex(0, graph); + for(tie(e, e_end) = out_edges(s, graph); e != e_end; ++e) { + std::cout << "(" << source(*e, graph) + << "," << target(*e, graph) + << ")" << endl; + } + +Even though the interface is the same for undirected graphs, there are some behavioral +differences because edge equality is defined differently. In a directed graph, +edge /(u,v)/ is never equal to edge /(v,u)/, but in an undirected graph they may +be equal. If the undirected graph is a multigraph then /(u,v)/ and /(v,u)/ might be +parallel edges. If the graph is not a multigraph then /(u,v)/ and /(v,u)/ must be the +same edge. + +In the example below the edge equality test will return false for the directed graph +and true for the undirected graph. The difference also affects the meaning of `add_edge()`. +In the example below, if we had also written `add_add(v, u, graph)`, this would have +added a parallel edge between `u` and `v` (provided the graph type allows parallel edges - +which most do). The difference in edge equality also affects the association of edge +properties. In the directed graph, the edges /(u,v)/ and /(v,u)/ can have distinct +weight values, whereas in the undirected graph the weight of /(u,v)/ is the same as +the weight of /(v,u)/ since they are the same edge. + + typedef ... DirectedGraph; + typedef ... UndirectedGraph; + + DirectedGraph digraph(V); + UndirectedGraph graph(V) + + { + boost::graph_traits::vertex_descriptor u, v; + u = vertex(0, digraph); + v = vertex(1, digraph); + add_edge(digraph, u, v, Weight(1.2)); + add_edge(digraph, v, u, Weight(2.4)); + boost::graph_traits::edge_descriptor e1, e2; + bool found; + tie(e1, found) = edge(u, v, digraph); + tie(e2, found) = edge(v, u, digraph); + std::cout << "in a directed graph is "; + std::cout << "(u,v) == (v,u) ? " << (e1 == e2) << std::endl; + + property_map::type + weight = get(edge_weight, digraph); + cout << "weight[(u,v)] = " << get(weight, e1) << endl; + cout << "weight[(v,u)] = " << get(weight, e2) << endl; + } + + { + boost::graph_traits::vertex_descriptor u, v; + u = vertex(0, graph); + v = vertex(1, graph); + add_edge(graph, u, v, Weight(3.1)); + boost::graph_traits::edge_descriptor e1, e2; + bool found; + tie(e1, found) = edge(u, v, graph); + tie(e2, found) = edge(v, u, graph); + std::cout << "in an undirected graph is "; + std::cout << "(u,v) == (v,u) ? " << (e1 == e2) << std::endl; + + property_map::type + weight = get(edge_weight, graph); + cout << "weight[(u,v)] = " << get(weight, e1) << endl; + cout << "weight[(v,u)] = " << get(weight, e2) << endl; + } + +The output is: + +[pre +in a directed graph is (u,v) == (v,u) ? 0 +weight\[(u,v)\] = 1.2 +weight\[(v,u)\] = 2.4 +in an undirected graph is (u,v) == (v,u) ? 1 +weight\[(u,v)\] = 3.1 +weight\[(v,u)\] = 3.1 +] + +[heading Multigraphs] +A /multigraph/ is a graph (either directed or undirected) that has parallel edges +between vertices. The Boost.Graph types are mostly unrestrictive about the addition +of parallel edges, meaning that it is fairly easy to actually create multigraphs +without any additional work. + +There are certain sets of graph types that do not allow the addition of parallel edges. +Specifically, if the EdgeList and OutEdgeList of an [adjacency_list] models an +associative container, then the graph cannont be a multigraph. + +[heading Indexed Graphs] +Indexed graph provide a specific property, an index, for verticese, edges or both. +Many algorithms require vertex or edge indices for "fast" property acces, often +declaring exterior properties as `vector`s and using the indices as random access +iterators to access those properties. These concepts effectively require that +indices are accessible as interior properties of the graph. + +These concepts are provided to help describe interface requirements for algorithms +that allow indices to be provided as an exterior property map. With these concepts, +requirements (and interfaces) can be written more disticntly for algorithms that accept +indexed graphs, and those that require adaptation through exterior properties. + +There are two indexed graph concepts: [VertexIndexGraph] and [EdgeIndexGraph]. + +[include vertex_index_graph.qbk] +[include edge_index_graph.qbk] + +[endsect] diff --git a/quickbook/concepts/incidence_graph.qbk b/quickbook/concepts/incidence_graph.qbk new file mode 100644 index 00000000..329541c1 --- /dev/null +++ b/quickbook/concepts/incidence_graph.qbk @@ -0,0 +1,95 @@ +[/ + / Copyright (c) 2007 Andrew Sutton + / + / 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) + /] + +[section Incidence Graph] +The IncidenceGraph concept provides an interface for efficient access to the out-edges +(for directed graphs) or incident edges (for undirected graphs) of each vertex in +the graph. + +[h4 Refinement Of] +[BootGraph] + +[h4 Associated Types] +[table + [[Type] [Description]] + [ + [`graph_traits::traversal_category`] + [ + This tag type must be convertible to `incidence_graph_tag`. + ] + ] + [ + [`graph_traits::degree_size_type`] + [ + The unsigned integral type used for representing the number of edges incident + to a vertex. The `degree_size_type` must meet the requirements of the + UnsignedIntegral concept. + ] + ] + [ + [`graph_traits::out_edge_iterator`] + [ + An out-edge iterator for a vertex /v/ provides access to the out-edges of the + vertex. As such, the value type of an out-edge iterator is the `edge_descriptor` + type of the graph. An out-edge iterator must meet the requirements of + MultiPassInputIterator. + ] + ] +] + +[h4 Valid Expressions] +[table + [[Expression] [Description]] + [ + [`source(e,g)`] + [ + If `e` represents the edge /(u,v)/, this function returns the vertex descriptor + for /u/. + + *Returns* `vertex_descriptor`. + ] + ] + [ + [`target(e,g)`] + [ + If `e` represents the edge /(u,v)/, this function returns the vertex descriptor + for /v/. + + *Returns* `vertex_descriptor`. + ] + ] + [ + [`out_edges(v,g)`] + [ + Returns an iterator range providing access to the out-edges (for directed graphs) + or the incident edges (for undirected graphs). The source vertex of an edge obtained + via an out-edge iterator is guaranteed to be the vertex `v` in the call to + `out_edges(v,g)`, and the target vertex must be adjacenct to `v`. + + *Returns* `std::pair` + ] + ] + [ + [`out_degree(v,g)`] + [ + Returns the number of out-edges (for directed graphs) or the number of incident + edges (for undirected graphs) of the vertex `v`. + + *Returns* `degree_size_type`. + ] + ] +] + +[h4 Notes] +For undirected graphs, the edge /(u,v)/ is the same as edge /(v,u)/, so without some extra +guarantee an implementation would be free use any ordering for the pair of vertices in an +out-edge. For example, if you call `out_edges(u, g)`, and `v` is one of the vertices adjacent +to `u`, then the implementation would be free to return /(v,u)/ as an out-edge which would be +non-intuitive and cause trouble for algorithms. Therefore, the extra requirement is added that +the out-edge connecting `u` and `v` must be given as /(u,v)/ and not /(v,u)/. + +[endsect] diff --git a/quickbook/concepts/mutable_graph.qbk b/quickbook/concepts/mutable_graph.qbk new file mode 100644 index 00000000..338ddea8 --- /dev/null +++ b/quickbook/concepts/mutable_graph.qbk @@ -0,0 +1,174 @@ +b[/ + / Copyright (c) 2007 Andrew Sutton + / + / 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) + /] + +[section Mutable Graph] +A MutableGraph can be changed via the addition or removal of edges and vertices. + +[h4 Refinement Of] +[Graph] + +[h4 Valid Expressions] +[table + [[Expression] [Description]] + [ + [`add_edge(u,v,g)`] + [ + Add a new vertex to the graph. The `vertex_descriptor` for the new vertex is returned. + + *Returns* `vertex_descriptor` + ] + ] + [ + [`clear_vertex(v,g)`] + [ + Removes all edges incident (both in-edges and out-edges for directed graphs) to the + vertex `v`. + + *Returns* `void` + + *Precondition* `u` is a valid `vertex_descriptor` in `g`. + + *Postcondition* `u` does not appear as a source or target of any edge in `g`. + ] + ] + [ + [`clear_out_edges(v,g)`] + [ + Removes all edges out-edges of the vertex `v`. For undirected graphs this is functionally + equivalent to `clear_vertex(v,g)`. + + *Returns* `void` + + *Precondition* `u` is a valid `vertex_descriptor` in `g`. + + *Postcondition* `u` does not appear as a source of any edge in `g`. + ] + ] + [ + [`clear_in_edges(v,g)`] + [ + Removes all edges in-edges of the vertex `v`. For undirected graphs this is functionally + equivalent to `clear_vertex(v,g)`. + + *Returns* `void` + + *Precondition* `u` is a valid `vertex_descriptor` in `g`. + + *Postcondition* `u` does not appear as a target of any edge in `g`. + ] + ] + [ + [`remove_vertex(v,g)`] + [ + Remove the vertex `v` from the vertex set of the graph. Note that undefined behavior may + result if there are edges remaining in the graph who's target is `u`. The `clear_vertex(v,g)` + function should be called first to ensure the preconditions. + + *Returns* `vertex_descriptor` + + *Precondition* `u` is a valid `vertex_descriptor` in `g` and does not appear as the source + or target of any edge in `g`. + + *Postcondition* `u` is not longer in the vertex set of `g`, nor is `u` a valid descriptor. + ] + ] + [ + [`add_edge(u,v,g)`] + [ + Inserts the edge /(u,v)/ into the graph, and returns an edge descriptor pointing to the new edge. + If the graph disallows parallel edges, and the edge /(u,v)/ is already in the graph, then the boolean + flag returned is false and the returned edge descriptor points to the already existing edge. Note + that for undirected graphs, /(u,v)/ is the same edge as /(v,u)/, so after a call to the function + `add_edge(u,v,g)`, this implies that edge /(u,v)/ will appear in the out-edges of `u` and /(u,v)/ + (or equivalently /(v,u)/) will appear in the out-edges of `v`. Put another way, `v` will be adjacent + to `u` and `u` will be adjacent to `v`. + + *Returns* `vertex_descriptor` + + *Precondition* `u` and `v` are valid vertex descriptors in `g`. + + *Postcondition* The returned `edge_descriptor` points to a valid edge in `g`. + ] + ] + [ + [`remove_edge(u,v,g)`] + [ + Remove the edge (u,v) from the graph. If the graph allows parallel edges this remove all occurrences + of /(u,v)/. + + *Returns* `void` + + *Precondition* `u` and `v` are valid vertex descriptors in `g`. + + *Postcondition* The edge /(u,v)/ is no longer in the edge set of `g`. + ] + ] + [ + [`remove_edge(e,g)`] + [ + Remove the edge `e` from the graph. + + *Returns* `void` + + *Precondition* `e` is an edge in the graph. + + *Postcondition* The edge `e` is no longer in the edge set of `g`. + ] + ] + [ + [`remove_edge(ei,g)`] + [ + Remove the edge pointed to by the edge iterator `ei` from the graph. This expression is only required + when `g` also models [IncidenceGraph]. + + *Returns* `void` + + *Precondition* `*ei` is an edge in the graph. + + *Postcondition* The edge `*ei` is no longer in the edge set of `g`. + ] + ] + [ + [`remove_edge_if(pred,g)`] + [ + Remove all edges from the graph `g` for which the predicate `pred` returns true. + + *Returns* `void` + ] + ] + [ + [`remove_out_edge_if(v,pred,g)`] + [ + Remove all out-edges of the vertex `v` for which the predicate `pred` returns true. + + *Returns* `void` + ] + ] + [ + [`remove_in_edge_if(v,pred,g)`] + [ + Remove all in-edges of the vertex `v` for which the predicate `pred` returns true. + + *Returns* `void` + ] + ] +] + +[h4 Complexity Guarantees] +* Vertex insertion is guaranteed to be amortized constant time. +* Clearing avertex is /O(E + V)/. +* Vertex removal is /O(E + V)/. +* Edge insertion must be either amortized constant time of it can be /O(log(E/V))/ if the insertion checks +to prevent the addition of parallel edges (which is a "feature" of some graph types). +* Edge removal is guaranteed to be /O(E)/. + +[h4 Models] +* [undirected_graph] +* [directed_graph] +* [adjacency_list] + +[endsect] diff --git a/quickbook/concepts/mutable_property_graph.qbk b/quickbook/concepts/mutable_property_graph.qbk new file mode 100644 index 00000000..4a7e58b0 --- /dev/null +++ b/quickbook/concepts/mutable_property_graph.qbk @@ -0,0 +1,64 @@ +[/ + / Copyright (c) 2007 Andrew Sutton + / + / 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) + /] + +[section Mutable Property Graph] +A MutablePropertyGraph is a [MutableGraph] with properties attached internally to the +vertices and edges. When adding vertices and edges the value of the properties can be given. + +[h4 Refinement Of] +[MutableGraph] and [PropertyGraph] + +[h4 Associated Types] +[table + [[Type] [Description]] + [ + [`graph_traits::vertex_property_type`] + [ + The property type associated with vertices in the graph `G`. This type is not + guaranteed to be the same as the `VertexProperties` template parameter. + ] + ] + [ + [`graph_traits::edge_property_type`] + [ + The property type associated with edges in the graph `G`. This type is not + guaranteed to be the same as the `EdgeProperties` template parameter. + ] + ] +] + +[h4 Valid Expressions] +[table + [[Expression] [Description]] + [ + [`add_vertex(vp,g)`] + [ + Add a new vertex to the graph and copy vertex properties `vp` into the property + for the new vertex. The `vertex_descriptor` is returned. + + *Returns* `vertex_descriptor` + ] + ] + [ + [`add_edge(u,v,ep,g)`] + [ + Inserts the edge /(u,v)/ into the graph, and copies object `ep` into the property + for that edge. + + *Returns* `property_traits::const_type>::value_type` + + *Precondition* `u` and `v` are valid vertex descriptors in `g`. + + *Postcondition* The returned `edge_descriptor` points to a valid edge in `g`. + ] + ] +] + +[h4 Complexity Guarantees] +The `get(p,g)` function must return in constant time. + +[endsect] diff --git a/quickbook/concepts/numeric_value.qbk b/quickbook/concepts/numeric_value.qbk new file mode 100644 index 00000000..360a00fa --- /dev/null +++ b/quickbook/concepts/numeric_value.qbk @@ -0,0 +1,77 @@ +[/ + / Copyright (c) 2007 Andrew Sutton + / + / 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) + /] + +[section Numeric Value] +The [NumericValue] concept describes requirements for a type to behave +as if it were numeric. This concept is generally used by algorithms that +typically operate on numeric types, but can be specialized to operate on +user-defined numerics or discrete types that emulate numerics. + +This concept requires that its models be regular (i.e., default and copy +constructible, assignable, and equality comparable). Additioanlly, this +concept requires all common mathematical operators (i.e., addition, subtraction, +multiplication and division). + +Finally, this concept requires that its models define appropriate values of +zero and infinity. These are used within certain computations to represent +infinite and zero states. + +[heading Refinement Of] +[StdRegularType], [StdAddable], [StdSubtractable], [StdMulitplicable], +[StdDivisible]. + +[note Why is numeric not a standard concept?] + +[heading Notation] +The following expressions are used within this document: +[table + [[Expression] [Description]] + [[N] [A type modeling the [NumericValue] concept.]] +] + +[heading Associated Types] +[table + [[Name] [Type] [Description]] + [ + [Value Type] + [`numeric_value::value_type`] + [ + The underlying type of the numeric value. + + *Requirements:* `N` is a [NumericValue], and the `value_type` + and `N` must be the same type. + ] + ] +] + +[heading Expressions] +[table + [[Name] [Expression] [Result Type] [Description]] + [ + [Zero Value] + [`numeric_value::zero()`] + [`numeric_value::value_type`] + [ + Returns the zero-value of the numeric type. + ] + ] + [ + [Infinite Value] + [`numeric_value::infinity()`] + [`numeric_value::value_type`] + [ + Returns the designated value of infinity for the numeric type. + + *Notes:* Some types such as `float` and `double` have values + that represent infinity. For other types, this must be explicitly + designated. For built-in integral types this is often chosen to + be `std::numeric_limits::max()`. + ] + ] +] + +[endsect] diff --git a/quickbook/concepts/property_graph.qbk b/quickbook/concepts/property_graph.qbk new file mode 100644 index 00000000..054f409e --- /dev/null +++ b/quickbook/concepts/property_graph.qbk @@ -0,0 +1,86 @@ +[/ + / Copyright (c) 2007 Andrew Sutton + / + / 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) + /] + +[section Property Graph] +A PropertyGraph is a graph that has some property associated with each of the vertices or edges +in the graph. As a given graph may have several properties associated with each vertex or edge, +a /tag/ is used to identity which property is being accessed. The graph provides a function which +returns a property map object and also the value corresponding to a vertex or edge and its +indicated property. + +[h4 Refinement Of] +[Graph] + +[h4 Associated Types] +[table + [[Type] [Description]] + [ + [`property_map::type`] + [ + The type of the property map for the property specified by `Property`. This type must + be a model of [ReadWritePropertyMap] with a key type the same as the graph's + `vertex_descriptor` or `edge_descriptor` types. + ] + ] + [ + [`property_map::const_type`] + [ + The type of the property map for the property specified by `Property`. This type must + be a model of [ReadablePropertyMap] with a key type the same as the graph\'s + `vertex_descriptor` or `edge_descriptor` types. + ] + ] +] + +[h4 Valid Expressions] +[table + [[Expression] [Description]] + [ + [`get(p,g)`] + [ + Returns the property map specified by the property identified by the tag `p`. The parameter + `p` is only used to convey type information and has no value. + + *Returns* `property_map::type` if `g` is mutable and + `property_map::const_type` otherwise. + ] + ] + [ + [`get(p,g,x)`] + [ + Returns the property /value/ specified by the type of property tag `p` for the given + vertex or edge descriptor `x`. The object `p` is only used to convey type information + and has no value. This function is equivalent to `get(get(p,g),x)`. + + *Returns* `property_traits::const_type>::value_type` + ] + ] + [ + [`put(p,g,x,v)`] + [ + Set the property /value/ specified by the type of property tag `p` for the given + vertex or edge descriptor `x` to the value `v`. The object `p` is only used to + convey type information and has no value. + + *Returns* `void` + ] + ] + [ + [`out_degree(v,g)`] + [ + Returns the number of out-edges (for directed graphs) or the number of incident + edges (for undirected graphs) of the vertex `v`. + + *Returns* `degree_size_type`. + ] + ] +] + +[h4 Complexity Guarantees] +The `get(p,g)` function must return in constant time. + +[endsect] diff --git a/quickbook/concepts/utility.qbk b/quickbook/concepts/utility.qbk new file mode 100644 index 00000000..b1f66680 --- /dev/null +++ b/quickbook/concepts/utility.qbk @@ -0,0 +1,17 @@ +[/ + / Copyright (c) 2007 Andrew Sutton + / + / 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) + /] + +[section General Concepts] +This section describes utlity graph concepts - those that do not necessarily +pertain explicitly to graphs or visitors for algorithms. + +[include descriptor.qbk] +[include numeric_value.qbk] +[include degree_measure.qbk] +[include distance_measure.qbk] + +[endsect] diff --git a/quickbook/concepts/vertex_index_graph.qbk b/quickbook/concepts/vertex_index_graph.qbk new file mode 100644 index 00000000..a56064ca --- /dev/null +++ b/quickbook/concepts/vertex_index_graph.qbk @@ -0,0 +1,115 @@ +[/ + / Copyright (c) 2007 Andrew Sutton + / + / 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) + /] + +[section Vertex Index Graph] +The [VertexIndexGraph] concept requires that a graph type `G` provide vertex indices +for each vertex in the graph, and that those indices are ordered in the range +\[0, `num_vertices(g)`). + +Because the removal of vertices causes "gaps" in the index space, graphs that model +this concept must also provide functions that allow them to re-index the vertices. + +[heading Refinement Of] +[MutablePropertyGraph] + +[heading Notation] +[table + [[Expression] [Description]] + [[`G`] [A type that models the [Graph] concept.]] + [[`g`] [An object of type `G`.]] + [ + [`P`] + [A synonym for `property_map`.] + ] +] + +[heading Associated Types] +[table + [[Name] [Expression] [Result Type] [Description]] + [ + [Vertex Index Type] + [`property_traits::value_type`] + [An unsigned integer type] + [ + The unsigned integral type representing vertex indices. + + *Requirements:* `T` must model the [NoConcept UnsignedIntegral] concept. + ] + ] + [ + [Vertex Index Property Type] + [ + `P::type` + ] + [A mutable property map] + [ + The type of property map through which vertex indices are readable and + writable. + + *Requirements:* This type must be a model of the [ReadWritePropertyMap] + concept. The `value_type` of the `property_traits` of this type must + be the same as `vertex_index_type`. + ] + ] + [ + [Vertex Index Property Type] + [ + `P::const_type` + ] + [ A `const` property map] + [ + The type of property map through which vertex indices are readable. + + *Requirements:* This type must be a model of the [ReadablePropertyMap] + concept. The `value_type` of the `property_traits` of this type must + be the same as `vertex_index_type`. + ] + ] +] + +[heading Requirements] +[table + [[Name] [Expression] [Result Type] [Description]] + [ + [Vertex Index Property] + [`get(vertex_index,g)`] + [ + `P::type` or[br] + `P::const_type` + ] + [ + Returns the property map that provides read/write access to the + vertex indices of the graph. + + *Complexity:* Constant. + ] + ] + [ + [Vertex Index] + [`get(vertex_index,g,v)`] + [`G::vertex_index_type`] + [ + Returns the index of the given vertex within the graph. This is + equvalent to `get(get(vertex_index, g), v)`. + + *Complexity:* Amortized constant. + ] + ] + [ + [Renumber Vertex Indices] + [`renumber_vertex_indices(g)`] + [] + [ + Renumbers all vertices in the graph such that each vertex is in the + range \[0, `num_vertices(g)`). + + *Complexity:* Linear in `num_vertices(g)`. + ] + ] +] + +[endsect] diff --git a/quickbook/concepts/vertex_list_graph.qbk b/quickbook/concepts/vertex_list_graph.qbk new file mode 100644 index 00000000..01cacd86 --- /dev/null +++ b/quickbook/concepts/vertex_list_graph.qbk @@ -0,0 +1,75 @@ +[/ + / Copyright (c) 2007 Andrew Sutton + / + / 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) + /] + +[section Vertex List Graph] +The VertexListGraph concept refines the [Graph] concept, and adds the requirement +for efficient traversal of all the vertices in a graph. + +[h4 Refinement Of] +[Graph] + +[h4 Associated Types] +[table + [[Type] [Description]] + [ + [`graph_traits::traversal_category`] + [ + This tag type must be convertible to `vertex_list_graph_tag`. + ] + ] + [ + [`graph_traits::vertex_iterator`] + [ + A vertex iterator (obtained via vertices(g)) provides access to all of the vertices in + a graph. A vertex iterator type must meet the requirements of [MultiPassInputIterator]. + The value type of the vertex iterator must be the vertex descriptor of the graph. + ] + ] + [ + [`graph_traits::vertices_size_type`] + [ + The unsigned integer type used to represent the number of vertices in the graph. + ] + ] +] + +[h4 Valid Expressions] +[table + [[Expression] [Description]] + [ + [`vertices(g)`] + [ + Returns an iterator range providing access to all the vertices in the graph `g`. + + *Returns* `std::pair` + ] + ] + [ + [`num_vertices(g)`] + [ + Returns the number of vertices in the graph `g`. + + *Returns* `vertices_size_type` + ] + ] +] + +[h4 Complexity Guarantees] +The `vertices(g)` function must return in constant time. + +[h4 Design Rationale] +One issue in the design of this concept is whether to include the refinement from the +[IncidenceGraph] and [AdjacencyGraph] concepts. The ability to traverse the vertices +of a graph is orthogonal to traversing out-edges, so it would make sense to have a VertexListGraph +concept that only includes vertex traversal. However, such a concept would no longer really be a +graph, but would just be a set, and the STL already has concepts for dealing with such things. +However, there are many BGL algorithms that need to traverse the vertices and out-edges of a graph, +so for convenience a concept is needed that groups these requirements together, hence the VertexListGraph +concept. + + +[endsect] diff --git a/quickbook/concepts/visitor.qbk b/quickbook/concepts/visitor.qbk new file mode 100644 index 00000000..b6d51997 --- /dev/null +++ b/quickbook/concepts/visitor.qbk @@ -0,0 +1,20 @@ +[/ + / Copyright (c) 2007 Andrew Sutton + / + / 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) + /] + +[section Visitor] +This concept defines the basic requirements of all visitor concepts in the Boost.Graph +library. + +[h4 Refinement Of] +[SgiCopyConstructible] + +[h4 Design Rationale] +This concpet is provided primarily as a base concept for its refinements. Its sole purpose +is to require that instances of concepts be copy-constructible, which is how they are +passed to different graph algorithms. + +[endsect] diff --git a/quickbook/concepts/visitors.qbk b/quickbook/concepts/visitors.qbk new file mode 100644 index 00000000..5babc1b3 --- /dev/null +++ b/quickbook/concepts/visitors.qbk @@ -0,0 +1,30 @@ +[/ + / Copyright (c) 2007 Andrew Sutton + / + / 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) + /] + +[section Visitor Concepts] +The visitor concepts plays the same role in Boost.Graph as functors play in the STL. +Functors provide a mechanism for extending an algorithm; for customizing what is done +at each step of the algorithm. Visitors allow the user to insert their own operations +at various steps within a graph algorithm. Unlike the STL algorithms, graph algorithms +typically have multiple event points where one may want to insert a call-back via a +functor. Therefore visitors do not have a single operator() method like a functor, but +instead have several methods that correspond to the various event points. Each +algorithm has a different set of event points, which are described by the following +visitor concepts: + +[include visitor.qbk] +[include bfs_visitor.qbk] +[include dfs_visitor.qbk] +[include dijkstra_visitor.qbk] +[include bellman_ford_visitor.qbk] +[include clique_visitor.qbk] +[include cycle_visitor.qbk] +[include event_visitor.qbk] +[include event_visitor_list.qbk] + + +[endsect] \ No newline at end of file diff --git a/quickbook/graph.qbk b/quickbook/graph.qbk new file mode 100644 index 00000000..a5c4aa59 --- /dev/null +++ b/quickbook/graph.qbk @@ -0,0 +1,55 @@ +[/ + / Copyright (C) 2007-2009 Andrew Sutton + / + / 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) + /] + +[library Boost.Graph + [quickbook 1.4] + [authors [Siek, Jeremy], [Lee, Lie-Quan], [Lumsdaine, Andrew]] + [copyright 2000 2001 Jeremy Siek, Lie-Quan Lee, Andrew Lumsdaine] + [category graph] + [id graph] + [dirname graph] + [purpose + Graph data structures and algorithms. + ] + [license + 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]) + ] +] + +[/ Templates /] +[template super[x]''''''[x]''''''] +[template sub[x]''''''[x]''''''] + +[template delta[]'''δ'''] [/ d Greek small letter delta] + +[template figure[path caption] +''' + + + + + + '''[caption]''' + + +''' +] + +[include sgi_concepts.qbk] +[include boost_concepts.qbk] +[include boost_reference.qbk] + +[/ Contents ] +[include introduction.qbk] +[include history.qbk] +[include guide/guide.qbk] +[include concepts/concepts.qbk] +[include reference/reference.qbk] + +[/ [include bibliography.qbk] /] diff --git a/quickbook/guide/adjacency_list.qbk b/quickbook/guide/adjacency_list.qbk new file mode 100644 index 00000000..969a0287 --- /dev/null +++ b/quickbook/guide/adjacency_list.qbk @@ -0,0 +1,480 @@ +[/ + / Copyright (c) 2007 Andrew Sutton + / + / 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) + /] + +[section The Adjacency List] +As mentioned in the Tour, the `adjacency_list` has seven template parameters. Three are +used to select storage types for the vertex list, the edge list and the out edge list, +and the remaining three define the interior properties of vertices, edges, and the +graph itself. + +[h2 Choosing the Edgelist and VertexList] +This section focuses on how to decide which version of the `adjacency_list` class to use in different +situations. The adjacency_list is like a swiss-army knife in that it can be configured in many ways. +The parameters that we will focus on in this section are `OutEdgeList` and `VertexList`, which control +the underlying data structures that will be used to represent the graph. The choice of `OutEdgeList` and +`VertexList` affects the time complexity of many of the graph operations and the space complexity of the +graph object. + +Boost.Graph uses containers from the STL such as `std::vector`, `std::list`, and `std::set` to represent +the set of vertices and the adjacency structure (out-edges and in-edges) of the graph. There are several +selector types that are used to specify the choice of container for `OutEdgeList` and `VertexList`. + +* `vecS` selects `std::vector`. +* `listS` selects `std::list`. +* `slistS` selects `std::slist`. +* `setS` selects `std::set`. +* `multisetS` selects `std::multiset`. +* `hash_setS` selects `std::hash_set`. + +[h3 Choosing the VertexList Type] +The VertexList parameter determines what kind of container will be used to represent the vertex set, or +two-dimensional structure of the graph. The container must model /Sequence/ or /RandomAccessContainer/. In +general, listS is a good choice if you need to add and remove vertices quickly. The price for this is extra +space overhead compared to choosing `vecS`. + +[h4 Space Complexity of the VertexList] +The `std::list` has a higher per-vertex space overhead than the `std::vector`, storing three extra pointers +per vertex. + +[h4 Time Complexity of the VertexList] +The choice of VertexList affects the time complexity of the following operations. + +[table VertexList Storage Options + [[Operation] [Performance Considerations]] + [ + [`add_vertex()`] + [ + This operation is amortized constant time for both vecS and listS (implemented with + `push_back()`). However, when the VertexList type is `vecS` the time for this operation + is occasionally large because the vector will be reallocated and the whole graph copied + but is still amortized constant time. + ] + ] + [ + [`remove_vertex()`] + [ + This operation is constant time for listS and O(V + E) for vecS. The large time + complexity for vecS is because the vertex descriptors (which in this case are indices + that correspond to the vertices' place in the vertex list) must be adjusted in the + out-edges for the whole graph. + ] + ] + [ + [`vertex()`] + [ + This operation is constant time for vecS and for `listS`. + ] + ] +] + +[h3 Choosing the OutEdgeList Type] +The OutEdgeList parameter determines what kind of container will be used to store the out-edges (and +possibly in-edges) for each vertex in the graph. The containers used for edge lists must either satisfy +the requirements for Sequence or for AssociativeContainer. + +One of the first things to consider when choosing the OutEdgeList is whether you want `adjacency_list` to +enforce the absence of parallel edges in the graph (that is, enforce that the graph not become a multi-graph). +If you want this enforced then use the setS or hash_setS selectors. If you want to represent a +multi-graph, or know that you will not be inserting parallel edges into the graph, then choose one of +the Sequence types: `vecS`, `listS`, or `slistS`. You will also want to take into account the differences in +time and space complexity for the various graph operations. Below we use V for the total number of vertices +in the graph and E for the total number of edges. Operations not discussed here are constant time. + +[h4 Space Complexity of the OutEdgeList] +The selection of the OutEdgeList affects the amount of space overhead per edge in the graph object. In the +order of least space to most space, the selectors are `vecS`, `slistS`, `listS`, and `setS`. + +[h4 Time Complexity of the OutEdgeList] +In the following description of the time complexity for various operations, we use E/V inside of the "big-O" +notation to express the length of an out-edge list. Strictly speaking this is not accurate because E/V merely +gives the average number of edges per vertex in a random graph. The worst-case number of out-edges for a vertex +is V (unless it is a multi-graph). For sparse graphs E/V is typically much smaller than V and can be considered +a constant. + +[table OutEdgeList Storage Options + [[Operation] [Performance Considerations]] + [ + [`add_edge()`] + [ + When the OutEdgeList is a UniqueAssociativeContainer like `std::set` the absence of + parallel edges is enforced when an edge is added. The extra lookup involved has time + complexity O(log(E/V)). The OutEdgeList types that model Sequence do not perform this + check and therefore add_edge() is amortized constant time. This means that it if you + don't care whether the graph has parallel edges, or know that the input to the + graph does not contain them, then it is better to use the sequence-based OutEdgeList. + The `add_edge()` for the sequence-based OutEdgeList is implemented with `push_front()` + or `push_back()`. However, for `std::list` and `std::slist` this operation will + typically be faster than with `std::vector` which occasionally reallocates + and copies all elements. + ] + ] + [ + [`remove_edge()`] + [ + For sequence-based OutEdgeList types this operation is implemented with `std::remove_if()` + which means the average time is E/V. For set-based OutEdgeList types this is implemented + with the `erase()` member function, which has average time log(E/V). + ] + ] + [ + [`edge()`] + [ + The time complexity for this operation is O(E/V) when the OutEdgeList type is a Sequence + and it is O(log(E/V)) when the OutEdgeList type is an AssociativeContainer. + ] + ] + [ + [`clear_vertex()`] + [ + For directed graphs with sequence-based OutEdgeList types the time complexity is O(V + E), + while for associative container based OutEdgeList types the operation is faster, with + time complexity O(V log(E/V)). For undirected graphs this operation is O(E2/V2) or + O(E/V log(E/V)). + ] + ] + [ + [`remove_vertex()`] + [ + The time complexity for this operation is O(V + E) regardless of the OutEdgeList type. + ] + ] + [ + [`out_edge_iterator::operator++()`] + [ + This operation is constant time and exhibits a similar speed ordering as + the `out_edge_iterator` with respect to the OutEdgeList selection. + ] + ] + + [ + [`in_edge_iterator::operator++()`] + [ + This operation is constant time and fast (same speed as incrementing a pointer). + The selection of OneD does not affect the speed of this operation. + ] + ] + [ + [`vertex_iterator::operator++()`] + [ + This operation is constant time and exhibits a similar speed ordering as the + out_edge_iterator with respect to the OutEdgeList selection. Traversing through the + whole edge set is O(V + E). + ] + ] + [ + [`adjacency_iterator::operator++()`] + [ + This operation is constant time and exhibits a similar speed ordering as + the out_edge_iterator with respect to the OutEdgeList selection. + ] + ] +] + +[h2 Directed and Undirected Adjacency Lists] +The `adjacency_list` class can be used to represent both directed and undirected graphs, depending on the +argument passed to the Directed template parameter. Selecting `directedS` or `bidirectionalS` choose a directed +graph, whereas `undirectedS` selects the representation for an undirected graph. See Section Undirected Graphs +for a description of the difference between directed and undirected graphs in Boost.Graph. 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. + +[h2 Internal Properties] +Properties can be attached to the vertices or edges of an `adjacency_list` graph via the property interface. +The template parameters VertexProperty and EdgeProperty of the `adjacency_list` class are meant to be filled +by these interior properties. + +[note The Boost Graph Library supports two interchangeable methods for specifying interior properties: +bundled properties and property lists. The former is easier to use and requires less effort, whereas the +latter is compatible with older, broken compilers and is backward-compatible with Boost versions prior to +1.32.0. If you absolutely require these compatibility features, read on to learn about property lists. +Otherwise, we strongly suggest that you read about the bundled properties mechanism.] + +One may specify internal properties via property lists, which are built from instances of the property class +declared as follows. + + template struct property; + +The PropertyTag template parameter is a tag class that simply identifies or gives a unique name to the property. +There are several predefined tags, and it is easy to add more. + + struct vertex_index_t { }; + struct vertex_index1_t { }; + struct vertex_index2_t { }; + struct edge_index_t { }; + struct graph_name_t { }; + struct vertex_name_t { }; + struct edge_name_t { }; + struct edge_weight_t { }; + struct edge_weight2_t { }; + struct edge_capacity_t { }; + struct edge_residual_capacity_t { }; + struct edge_reverse_t { }; + struct vertex_distance_t { }; + struct vertex_root_t { }; + struct vertex_all_t { }; + struct edge_all_t { }; + struct graph_all_t { }; + struct vertex_color_t { }; + struct vertex_rank_t { }; + struct vertex_predecessor_t { }; + struct vertex_isomorphism_t { }; + struct vertex_invariant_t { }; + struct vertex_invariant1_t { }; + struct vertex_invariant2_t { }; + struct vertex_degree_t { }; + struct vertex_out_degree_t { }; + struct vertex_in_degree_t { }; + struct vertex_discover_time_t { }; + struct vertex_finish_time_t { }; + +The T template parameter of property specifies the type of the property values. The type T must be Default +Constructible, Assignable, and Copy Constructible. Like the containers of the C++ Standard Library, the +property objects of type T are held by-value inside of the graph. + +The NextProperty parameter allows property types to be nested, so that an arbitrary number of properties +can be attached to the same graph. + +The following code shows how a vertex and edge property type can be assembled and used to create a graph type. +We have attached a distance property with values of type float and a name property with values of type +std::string to the vertices of the graph. We have attached a weight property with values of type float to +the edges of the graph. + + // specify property types fora graph + typedef property > VertexProperty; + typedef property EdgeProperty; + + // specify the graph has having the above properties + typedef adjacency_list Graph; + + // instantiate the graph with N (a compile-time constant integer) vertices + Graph g(N); + +The property values are then read from and written to using property maps. See Section Interior Properties +for a description of how to obtain property maps from a graph, and read Section Property Maps for how to use +property maps. + +[h3 Built-in Vertex and Edge Properties] +Even if a graph type is instantiated without any user-specified properties, Boost.Graph will define a few +default properties for both vertices and edges. These are always available in algorithms through the +property map interfaces. + +Vertices have the following properties: + +Edges have the following properties: + +[h3 Custom Edge Properties] +Creating your own property types and properties is easy; just define a tag class for your new property. +The property tag class will need to define num with a unique integer ID, and kind which should be either +edge_property_tag, vertex_property_tag, or graph_property_tag. + + struct flow_t { + typedef edge_property_tag kind; + }; + + struct capacity_t { + typedef edge_property_tag kind; + }; + +You can also use enum's instead of struct's to create tag types. Create an enum type for each property. +The first part of the name of the enum type must be edge, vertex, or graph followed by an underscore, +the new property name, and a _t at the end. Inside the enum, define a value with the same name minus the +_t. Then invoke the BOOST_INSTALL_PROPERTY macro. + + enum edge_flow_t { edge_flow }; + enum edge_capacity_t { edge_capacity }; + + namespace boost { + BOOST_INSTALL_PROPERTY(edge, flow); + BOOST_INSTALL_PROPERTY(edge, capacity); + } + +Now you can use your new property tag in the definition of properties just as you would one of the builtin tags. + + typedef property Cap; + typedef property EdgeProperty; + typedef adjacency_list Graph; + +Just as before, the property maps for these properties can be obtained from the graph via the get(Property, g) function. + + property_map::type capacity = get(capacity_t(), G); + property_map::type flow = get(flow_t(), G); + +The file edge_property.cpp shows the complete source code for this example. + +[h3 Custom Vertex Properties] +Creating your own properties to attach to vertices is just as easy as for edges. Here we want to attach people's +first names to the vertices in the graph. + + struct first_name_t { + typedef vertex_property_tag kind; + }; + +Now we can use the new tag in the property class and use that in the assembly of a graph type. The following +code shows creating the graph type, and then creating the graph object. We fill in the edges and also assign +names to the vertices. The edges will represent "who owes who"; + + typedef property FirstNameProperty; + typedef adjacency_list MyGraphType; + + typedef pair Pair; + Pair edge_array[11] = { Pair(0,1), Pair(0,2), Pair(0,3), + Pair(0,4), Pair(2,0), Pair(3,0), + Pair(2,4), Pair(3,1), Pair(3,4), + Pair(4,0), Pair(4,1) }; + + MyGraphType G(5); + for (int i = 0; i < 11; ++i) { + add_edge(edge_array[i].first, edge_array[i].second, G); + } + + property_map::type name = get(first_name_t(), G); + + boost::put(name, 0, "Jeremy"); + boost::put(name, 1, "Rich"); + boost::put(name, 2, "Andrew"); + boost::put(name, 3, "Jeff"); + name[4] = "Kinis"; // you can also use the operator[] too + + who_owes_who(edges(G).first, edges(G).second, G); + +The `who_owes_who()` function written for this example was implemented in a generic style. The input is +templated so we do not know the actual graph type. To find out the type of the property map for our +first-name property, we need to use the property_map traits class. The const_type is used since the graph +parameter is const. Once we have the property map type, we can deduce the value type of the property using +the property_traits class. In this example, we know that the property's value type will be `std::string`, but +written in this generic fashion the `who_owes_who()` function could work with other property value types. + + template + void who_owes_who(EdgeIter first, EdgeIter last, const Graph& G) + { + // Access the propety acessor type for this graph + typedef typename property_map::const_type NameMap; + typedef typename boost::property_traits::value_type NameType; + + NameMap name = get(first_name, G); + NameType src_name, targ_name; + + while (first != last) { + src_name = boost::get(name, source(*first, G)); + targ_name = boost::get(name, target(*first, G)); + cout << src_name << " owes " + << targ_name << " some money" << "\n"; + ++first; + } + } + +The output is: + + Jeremy owes Rich some money + Jeremy owes Andrew some money + Jeremy owes Jeff some money + Jeremy owes Kinis some money + Andrew owes Jeremy some money + Andrew owes Kinis some money + Jeff owes Jeremy some money + Jeff owes Rich some money + Jeff owes Kinis some money + Kinis owes Jeremy some money + Kinis owes Rich some money + +The complete source code to this example is in the file interior_property_map.cpp. + +[h3 Customizing the Adjacency List Storage] +The `adjacency_list` is constructed out of two kinds of containers. One type of container to hold all the +vertices in the graph, and another type of container for the out-edge list (and potentially in-edge list) +for each vertex. Boost.Graph provides selector classes that allow the user to choose between several of the +containers from the STL. It is also possible to use your own container types. When customizing the VertexList +you need to define a container generator as described below. When customizing the OutEdgeList you will need +to define a container generator and the parallel edge traits. The file container_gen.cpp has an example of +how to use a custom storage type. + +[h4 Container Generator] +The `adjacency_list` class uses a traits class called `container_gen` to map the OutEdgeList and VertexList +selectors to the actual container types used for the graph storage. The default version of the traits class +is listed below, along with an example of how the class is specialized for the listS selector. + + namespace boost { + template + struct container_gen { }; + + template + struct container_gen { + typedef std::list type; + }; + } + +To use some other container of your choice, define a selector class and then specialize the `container_gen` +for your selector. + + struct custom_containerS { }; // your selector + + namespace boost { + // the specialization for your selector + template + struct container_gen { + typedef custom_container type; + }; + } + +There may also be situations when you want to use a container that has more template parameters than +just ValueType. For instance, you may want to supply the allocator type. One way to do this is to +hard-code in the extra parameters within the specialization of container_gen. However, if you want more +flexibility then you can add a template parameter to the selector class. In the code below we show how +to create a selector that lets you specify the allocator to be used with the `std::list`. + + template + struct list_with_allocatorS { }; + + namespace boost { + template + struct container_gen, ValueType> + { + typedef typename Alloc::template rebind::other Allocator; + typedef std::list type; + }; + } + + // now you can define a graph using std::list and a specific allocator + typedef adjacency_list< list_with_allocatorS< std::allocator >, vecS, directedS> MyGraph; + +[h4 Push and Erase for the Custom Container] +You must also tell the `adjacency_list` how elements can be efficiently added and removed from the +custom container. This is accomplished by overloading the `push()` and `erase()` functions for the custom +container type. The `push()` function should return an iterator pointing to the newly inserted element +and a bool flag saying whether the edge was inserted. + + template + std::pair::iterator, bool> + push(custom_container& c, const T& v) + { + // this implementation may need to change for your container + c.push_back(v); + return std::make_pair(boost::prior(c.end()), true); + } + + template + void erase(custom_container& c, const T& x) + { + // this implementation may need to change for your container + c.erase(std::remove(c.begin(), c.end(), x), c.end()); + } + +There are default `push()` and `erase()` functions implemented for the STL container types. + +[h4 Parallel Edge Traits] +When customizing the OutEdgeList, you must also specialize the `parallel_edge_traits` class to specify whether +the container type allows parallel edges (and is a Sequence) or if the container does not allow parallel +edges (and is an AssociativeContainer). + + template <> + struct parallel_edge_traits { + typedef allow_parallel_edge_tag type; + }; + +[endsect] \ No newline at end of file diff --git a/quickbook/guide/directed_graph.qbk b/quickbook/guide/directed_graph.qbk new file mode 100644 index 00000000..6b0bec73 --- /dev/null +++ b/quickbook/guide/directed_graph.qbk @@ -0,0 +1,371 @@ +[/ + / Copyright (c) 2007 Andrew Sutton + / + / 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) + /] + +[section Directed Graphs] +Like the previous section, here we take a look at how to solve different +types graph problems using the Boost.Graph library. In this case however, +the problems being addressed are better modeled with directed graphs. A +directed graph (also a /digraph/) is one in which edges can only be traversed +in a specific direction. + +In this section we are concerned with /dependency graphs/. A dependency graph +describes a relationship between two entities in which one (/source/) requires +a second (/target/). The source is said to be dependant upon the target. +Dependency graphs arise in many, many real-world situations such as source +code analysis, software installation, "tech-trees" in computer games, etc. +In this example, we will look at a common dependency graph: dependencies +between software documents and build targets. + +[h3 File Dependencies] +If you've ever typed `make` and wondered how the program decides the order +tasks to build, then this tutorial is for you. The make software relies on +dependency information explicitly encoded into Makefiles. Binaries (executable +programs and libraries) depend on sets of source files. Source files, which +implement program features, depend on header files, which expose type and +function declarations. These, in turn, might depend on generated source files +generated by `lex`, `yacc` or any other of an assortment of code-generating +tools. These dependencies can be modeled with a directed graph. + +For this example, we're actually going to use some of the files that actually +implement the examples described in this user's guide. Their dependencies are +shown in figure 1. Path names have been omitted for readability. + +[$images/guide/files.png] + +From this graph, it should be relatively easy to see that the build should +start at the bottom and proceed "upwards" with the executable programs being +built last - maybe. There are actually two different approaches to bulding +these programs: + +* One at a time. This is probably what you're used to seeing. The compiler +builds file A, followed by file B, and finally file C. +* In parallel. If you're lucky enough to have a multi-processor computer +available to you we might be able to process (compile) a number of different +files at the same time by distributing the tasks to different processors. + +The solution to both of these problems is addressed by topologically sorting +the graph. This provies the schedule of files to be processed by ordering +the vertices based on their dependencies. + +A third problem we might encounter is that of cycles in the dependency +graph. Cycles are bad since topological sorts will not work in their presence. + +[h4 Makefiles and Graphs] +The first step in implementing a make-ordering for source files is acquiring +some data. For this example, we our program will parse files in a stripped down, +Makefile-like format. The input looks something like something like this. + +[pre +undirected_graph.hpp : adjacency_list.hpp +directed_graph.hpp : adjacency_list.hpp +movies.hpp : undirected_graph.hpp +movies.cpp : movies.hpp tokenizer.hpp +kevin_bacon.cpp : movies.hpp visitors.hpp breadth_first_search.hpp +kevin_bacon.exe : movies.cpp kevin_bacon.cpp +build_order.cpp : directed_graph.hpp topological_sort.hpp +build_order.exe : build_order.cpp +] + +Obviously, we're going to have to build a parser for this input format. Just as +before our program starts by defining aliases for commonly used template types. + + struct Target; + + typedef boost::directed_graph Graph; + typedef Graph::vertex_descriptor Vertex; + typedef Graph::edge_descriptor Edge; + +In this graph, vertex properties are encapsulated in a `Target` structure. For +this application, a target is any named file that might appear in the dependency +graph. Unlike the previous example, we really don't have any need for edge propreties, +so we can simply omit that template parameter. The `Target` is defined as: + + struct Target + { + int index; + std::string name; + }; + +[note +If you think you're seeing some similarities between the previous example, and this +one... just wait. There are a number of common properties and tasks in many graph +related problems such as indexing vertices, providing name labels, etc. Pay special +attention to the method of adding vertices to the graph - the mapping of a unique +name to a vertex is nearly ubiquitous in the setup of graph problems. +] + +Likewise, we'll go ahead and predefine a property map that will be used later. +We also need a mapping of target name to vertex so we don't duplicate vertices +and have a convenient lookup tool later on. + + typedef boost::property_map::type TargetIndexMap; + typedef std::map TargetMap; + +We can now start building a program to parse the input data and build a dependency +graph. + + using namespace std; + using namespace boost; + + int main() + { + typedef char_separator separator; + typedef tokenizer tokenizer; + + Graph grapg; + TargetMap targets; + + for(string line; getline(cin, line); ) { + // skip comment and blank lines + if(line[0] == '#' || line.empty()) { + continue; + } + + // split the string on the dependency + size_t index = line.find_first_of(':'); + if(index == string::npos) { + continue; + } + string target = trim_copy(line.substr(0, index)); + string deps = trim_copy(line.substr(index + 1)); + + // add the target to the build graph + Vertex u = add_target(graph, targets, target); + + // tokenize the dependencies + separator sep(" \t"); + tokenizer tok(deps, sep); + tokenizer::iterator i = tok.begin(), j = tok.end(); + for( ; i != j; ++i) { + string dep = *i; + + // add this dependency as a target + Vertex v = add_target(graph, targets, dep); + + // add the edge + add_dependency(graph, u, v); + } + } + + // ...to be continued... + +This is a fairly large chunk of code that implements input parsing and graph construction +with the help of the `add_target()` and `add_dependency()` functions. Essentially, this +snippet creates a vertex (target) for each file named in the input file. A dependency +edge is added between the first target (preceeding the ':' character) and each subsequent +target (white space separated list following the ':'). The `add_target()` and `add_dependency()` +method are implemented as: + + Vertex add_target(Graph& graph, TargetMap& targets, const string& name) + { + Vertex v; + TargetMap::iterator it; + bool inserted; + tie(it, inserted) = targets.insert(make_pair(name, Vertex())); + if(inserted) { + v = add_vertex(graph); + it->second = v; + + graph[v].index = num_vertices(graph) - 1; + graph[v].name = name; + } + else { + v = it->second; + } + return v; + } + +You may notice that the `add_target()` function is nearly line-for-line identical to the +`add_actor()` function in the previous example. This is no coincidence - both functions +do exactly the same thing. They associate a vertex with a unique name and assign it an +index that we can use later for various graph algorithms. + + Edge add_dependency(Graph& graph, Vertex u, Vertex v) + { + return add_edge(v, u, graph).first; + } + +The `add_dependency()` method is considerably more terse than its undirected counter part, +but essentially does the same thing. There is one very important difference, however: +the direction of the edge is reversed to create a subtly different graph. Although +the method is called to indicate that vertex `u` dependes on vertex `v`, the added edge +actually indicates that vertex `v` satisfies the dependency of vertex `u`. In fact, this +is the reverse of the original graph and is shown in Figure 2. + +[$images/guide/reverse.png] + +[h4 Obtaining the Make Order] +We are now ready to compute the make order by running a topological sort. Thanks to a +canned implementation, this is trivial. + + int main() + { + // ...continued from above... + + TargetIndexMap indices = get(&Target::index, graph); + + typedef list MakeOrder; + MakeOrder order; + topological_sort(graph, front_inserter(order), vertex_index_map(indices)); + + BuildOrder::iterator i = order.begin(), j = order.end(); + for( ; i != j; ++i) { + cout << graph[*i] << "\n"; + } + } + +The `topological_sort()` algorithm takes an output iterator as the second parameter. +Here, we use a standard front insertion iterator to prepend each target to the make +order. The `vertex_index_map()` named parameter is also required for the implementation. +After computation, we simply print the ordering to standard output. + +[h4 parallel Compilation] +What if we have multiple processors available? Surely there is a way to determine if +we can compile several independent files simultaneously, thereby reducing the overall +build time. In fact, there is. Consider rephrasing the question to "what is the earliest +time that a file can be built assuming that an unlimited number of files can be built +at the same time?". In our simplified example, the only criteria for when a file can +be built is that it has no dependencies (i.e., in edges). Further simplifiying the +example, we assume that each file takes the same amount of time to build (1 time unit). + +For parallel compilation, we can build all files with zero dependencies in the first +time unit at the same time. For each file, the time at which it can be built is one +more than the maximum build time of the files on which it depends. In this example, +`adjacency_list.hpp` is one of the files that will compile first (in parallel). +The `directed_graph.hpp` file will compile in the second time step, and `build_order.cpp` +in the third. + +To implement this, we need a vector that represents the time slots in which each vertex +will be built. By visiting the vertices in topological order, we ensure that we can +assigned the correct time slot to each vertex since values "propogate" down the ordering. +Just for fun, we'll merge the time ordering with the output so we can see a) the order +in which each file is built and b) the time slot it could be built in. + + int main() + { + // ...continued from above... + vector time(num_vertices(graph), 0); + BuildOrder::iterator i = order.begin(), j = order.end(); + for( ; i != j; ++i) { + int slot = -1; + Graph::in_edge_iterator j, k; + for(tie(j, k) = in_edges(*i, graph); j != k; ++j) { + Vertex v = source(*j, graph); + slot = std::max(time[graph[v].index], slot); + } + time[g[*i].index] = slot + 1; + + cout << g[*i].name << "\t[" << time[g[*i].index] << "]\n"; + } + } + +This is a code may be a little dense, but demonstrates two important aspects of +the Boost.Graph library. First this demonstrates the importantance of vertex +indices. Despite their instability with mutable graphs, many (most?) graph algorithms +use vertex indices to efficiently associate extra data with a vertex. In fact, this +approach is so ubiquitous in the examples that it leads many to believe the +`vertex_descriptor` is always the index of a vertex. + +[warning +A `vertex_descriptor` is *not* its index in the graphs container of vectors! +] + +The second important aspect this demonstrates is the construction of an /external +property/ for vertices. Although we don't use the `time` vector in any additional +computations, we could easily turn it into a property map for use with other +algorithms. + +The output might something like this: + +[pre +$ ./make_order < files +topological_sort.hpp [0] +breadth_first_search.hpp [0] +visitors.hpp [0] +tokenizer.hpp [0] +adjacency_list.hpp [0] +directed_graph.hpp [1] +build_order.cpp [2] +build_order.exe [3] +undirected_graph.hpp [1] +movies.hpp [2] +kevin_bacon.cpp [3] +movies.cpp [3] +kevin_bacon.exe [4] +] + +Although it probably won't since I doctored the tabbing for display purposes. + +[h4 Finding Cycles] +Admittedly, cycles in dependency graphs for software probably don't occur so often +that we need to develop special software to find them. However, if the dependency +graph is big (think about all the source code, binaries, data files and thier +dependencies that constitute a typical Linux distribution), then its possible that +cycles creep into the graph. It might be nice to determine if there is such a cycle +before actually trying to build it. + +To do this, we are going to provide a customized visitor for a depth-first search (DFS). +Just like the custom visitors in our undirected graph examples, we overload a visitor +event (here, the `back_edge` event) to indicate that a cycle has been found. Using the +same setup as before, our visitor follows: + + struct CycleDetector : public dfs_visitor<> + { + CycleDetector(bool& c) + : has_cycle(c) + {} + + template + void back_edge(Edge, Graph&) + { + has_cycle = true; + } + + bool& has_cycle; + }; + + CycleDetector detect_cycles(bool& c) + { return CycleDetector(c); } + +That's it... When the `back_edge()` method is called, we know that a cycle exists +in the graph. This literally indicates that there is an edge to a vertex that we +have already visited, hence: a cycle. We also provide a helper function that +instantiates the visitor. + +Using the cycle-detecting visitor is just as easy as before. After constructing the +graph, we would find the following in the `main()` program. + + int main() + { + // ...continued from above... + + TargetIndexMap indices = get(&Target::index, g); + + bool cycle = false; + depth_first_search(g, + vertex_index_map(indices). + visitor(detect_cycles(cycle))); + cout << "has cycle: " << cycle << "\n"; + } + +Unfortunately, our test input file doesn't currently contain any cycles - a sign of +good engineering - so we'll have to add one. Add the following lines to the input +to create a completely superfluous cycle. + +[pre +movies.exe : kevin_bacon.exe +kevin_bacon.exe : movies.exe +] + +Running the program on the modified input should yield: + +[pre +$ ./cycle < files +has cycle: 1 +] + +[endsect] \ No newline at end of file diff --git a/quickbook/guide/guide.qbk b/quickbook/guide/guide.qbk new file mode 100644 index 00000000..43a69043 --- /dev/null +++ b/quickbook/guide/guide.qbk @@ -0,0 +1,14 @@ +[/ + / Copyright (c) 2007 Andrew Sutton + / + / 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) + /] + +[section User's Guide] + +[include undirected_graph.qbk] +[include directed_graph.qbk] +[include adjacency_list.qbk] + +[endsect] \ No newline at end of file diff --git a/quickbook/guide/undirected_graph.qbk b/quickbook/guide/undirected_graph.qbk new file mode 100644 index 00000000..6d43128e --- /dev/null +++ b/quickbook/guide/undirected_graph.qbk @@ -0,0 +1,473 @@ +[/ + / Copyright (c) 2007 Andrew Sutton + / + / 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) + /] + +[section Undirected Graphs] +In this section, our example revolves around a particular type of /social network/. +A social network is a graph that models the relationships between people. Specifically, +in this example we are looking at a graph that connects co-stars of films. + +[h3 Co-Star Graphs] +The first example problem we want to look at is the "Six Degrees of Kevin Bacon" +problem. In this problem, two actors are related if they appear in the same movie, +which can be trivially represented using an undirected graph. + +For the Six Degrees problem, we define a citation graph such that each vertex in +the graph represents an actor, and each edge connects two actors if and only if +they appear in the same movie. Consider the example in Figure 1. Here we have +ten relatively well-known actors and the movies in which they appear together - +and yes, Kevin Bacon is actually in /Animal House/ (he plays a snotty Omega pledge +in his film debut). + +[$images/guide/movie.png] + +Although this is a relatively simple graph, it isn't hard to imagine that it +scales up fairly quickly. Consider what would happen if we added all of Kevin +Bacon's co-stars from major motion picture in which he starred - and all of +their co-stars. It's not hard to imagine that only three iterations might +actually encompass all of Hollywood and beyond (Bollywood?). So what can we do +with these graphs? + +For starters, we can identify two different problems of the "Six Degrees". + +* How far is every actor in the graph from Kevin Bacon? This gives us the number +of steps between Mr. Bacon and any other actor. The distances from a central actor +can give clues to the size (especially the diameter) of a graph. +* What is the "fastest" way to travel along the co-star graph from Kevin Bacon +to any other actor? This is more commonly known as the "Six Degrees of Kevin +Bacon Game". + +These are actually two different instances of the same problem and can be solved +using the same algorithm - a simple breadth-first search (BFS). + +[note +The term "six degrees of separation" refers to the total distance one must travel +in a social network to get from one's self to any other person in the network. +This notion is supported through a number of social experiments, namely that of +Stanley Milgram who coined the term "small world" with respect to social networks. +His experiment showed that Americans are connected, on average by six friendships. +The notion of a "small world" social network is now nearly synonymous with a +graph having an average degree of connectivity (formally known as its /mean geodesic +distance/) of just six steps. + +On a side note, the name "Six Degrees of Kevin Bacon" can be attributed to a +producer on /The Jon Stewart Show/ when the creators (students from Abright +College) made an appearence to discuss and demonstrate the concept. +] + +[h4 Actors, Movies, and Graphs] + +Our program begins by inlcuding required headers and creating some convenient +type aliases. + + #include + #include + #include + #include + + struct Actor; + struct Movie; + + typedef boost::undirected_graph Graph; + typedef Graph::vertex_descriptor Vertex; + typedef Graph::edge_descriptor Edge; + +In this snippet, our `Actor` structure is going to represent the properties of each +vertex in the graph while the `Movie` structure encapsulates edge information (i.e., +the movie that two actors appear in). + +The graph itself is defined by the type `boost::undirected_graph`. +Essentially, this states that each vertex will have properties given in the `Actor` +structure, and that edges will have properties in the `Movie` structure. We also +create some aliases for the graph's vertex and edge descriptors. + +[important +Many of the examples in the Boost Graph Library treat vertex descriptors as the +index of a vertex within the graph. It must be noted however, that this is not +a reliable approach to indexing vertices and /will not/ work with the `undirected_graph` +and `directed_graph` classes. Try to get in the habit of thinking of vertex and +edge descriptors as opaque types and values - they are simply keys that provide +access to the properties of their respective types. +] + +In order to fully model our problem, we need to finish defining the `Actor` and +`Movie` structures for our graph. + + struct Actor + { + int distance; + std::string name; + }; + + struct Movie + { + std::string name; + }; + +In this example, we are "internalizing" a couple of properties for each vertex. +The `Actor::distance` property will be used to record the distance from each actor +to Kevin Bacon. The `Actor::name` and `Movie::name` properties should be fairly +self-explanatory. However in this example, we are going to require that all actors +have unique names. We'll see why in a bit. + +We're also going to define a number of other types related to the graphs properties: +/property maps/. These maps provide a mechanism for accessing the interior and exterior +properties of vertices and edges in a uniform manner. In this example, all of the +vertex and edge properties are internal, but we could easily make them external and +have the program run just as quickly. + + typedef boost::property_map::type ActorDistanceMap; + +The first template argument `Graph` defines the type of the graph that +the property map is going to access. The second template argument with the somewhat +peculiar syntax is the type of the property. These are pointers to `Actor` member +variables of type `int`. + +Now that the preliminaries are out of the way, we need to concentrate on the construction +of our graph. For this task, we're going to need another data structure that maps actor +names to vertices in the graph. We're going to use this to prevent adding mulitple +vertices for the same actor and later, to find the vertex in the graph that corresponds to +Kevin Bacon. + +This program reads an input file from standard input. The input file is given in an edge- +list format with semicolon separators. Each line corresponds to an edge, giving the two +actors as the endpoints and the name of the movie they both appear in. For example: +[pre +Tim Matheson;Kevin Bacon;Animal House (1978) +John Belushi;Kevin Bacon;Animal House (1978) +Carrie Fisher;John Belushi;The Blues Brothers (1980) +Mark Hamill;Carrie Fisher;Star Wars (1977) +] + +The following function implements the input parser for the graph data. + + #include + + // the very important actor-to-vertex mapping + typedef std::map ActorMap; + + using namespace std; + using namespace boost; + + void build_costar_graph(istream& is, Graph& graph, ActorMap&) + { + // pull all of the data from std in. + for(string line; getline(is, line); ) { + // skip any comment or blank lines + if(line[0] == '#' || line.empty()) { + continue; + } + + // tokenize the string + char_delimiters_separator sep(false, "", ";"); + tokenizer<> tok(line, sep); + tokenizer<>::iterator i = tok.begin(); + + // grab the names of the two actors and the movie title + string first = *i++; + string second = *i++; + string movie = *i++; + + // get the vertices associated with the actors adding them + // to the graph if necessary + Vertex + u = add_actor(g, actors, first), + v = add_actor(g, actors, second); + + // create an edge (movie) linking the actors + add_movie(g, u, v, movie); + } + } + +To finish graph construction, we need to implement the `add_actor()` and `add_movie()` +functions: + + Vertex add_actor(Graph& graph, ActorMap& actors, const string& name) + { + // try inserting the actors name into the actors map + Vertex v; + ActorMap::iterator it; + bool inserted; + tie(it, inserted) = actors.insert(make_pair(name, Vertex())); + + if(inserted) { + // if the vertex was inserted into the map, we need to + // create a new vertex in the graph and make sure that + // the map references the correct vertex + v = add_vertex(graph); + it->second = v; + + // configure the vertex properties + g[v].name = name; + } + else { + // otherwise, the name is already in the map, so + // return the vertex associated with it + v = it->second; + } + + return v; + } + + Edge add_movie(Graph& g, Vertex u, Vertex v, const string& movie) + { + Edge e; + bool inserted; + tie(e, inserted) = add_edge(u, v, g); + if(inserted) { + g[e].name = movie; + } + return e; + } + +There are several important features of these two functions to pay special attention to. +The first is the use of the `tie()` constructor. This is arguably one of the most useful +and most used functions (it's actually a type) in Boost.Graph. It simply takes the +values returned in a `std::pair` and assigns them to the variables passed to the +constructor. In this function it is more or less equivalent to: + + std::pair x = actors.insert(...); + ActorMap::iterator iter = x.first; + bool inserted = x.second; + +The second (and most important) is the assignment of the vertex properties. These +two lines of code use the /bundled properties/ syntax to assign both an index +and a name to the vertex that was just added to the graph. + +Our main program looks like this: + + int main() + { + Graph graph; + ActorMap actors; + build_costar_graph(cin, graph, actors); + + // ...to be continued... + } + +[h4 Distance To Kevin Bacon] +Now, all we have left to do is assign distances to Kevin Bacon. To do this, we're going +to use a breadth-first search (starting from Kevin Bacon) and simply record the "depth" +of each vertex as the distance from Kevin to every other actor. Fortunately, Boost.Graph +gives us lots of help in this area so we don't have to write much more code. Let's look +at the main program. + + int main() + { + // ...continued from above... + + // find kevin (our starting point) + Vertex kevin = actors["Kevin Bacon"]; + + // get a property map and zero out kevin's distance-to-self + ActorDistanceMap distances = get(&Actor::distance, graph) + distances[kevin] = 0; + + breadth_first_search(graph, kevin, + visitor( + make_bfs_visitor(record_distances(distances, on_tree_edge())) + ) + ); + + // ...to be continued... + +This is actually the "meat" of the solution. First, get a reference to the vertex that +represents Kevin Bacon - our `ActorMap` is very good at this. Next we have to get the +property map for our actor's distances so we can set Kevin's distance to zero. In this +case, the actor's distance is actually a /bundled property/ of the `Actor` structure. + +Finally, we invoke the `breadth_first_search()` on `graph` with `kevin` as our starting +vertex. The `visitor()` function is actually a /named parameter/ - a function that assigns +a value to a parameter of an algorithm. In this case, the parameter is the /visitor/ +parameter (as indicated by the function name). The value is in turn provided by the +`make_bfs_visitor()` function, which creates visitor object depnding on the parameters. +The `record_distances()` function creates a `distance_recorder` visitor. The `distances` +argument is our property map, indicating that the visitor will operate on those values. +Finally, the `on_tree_edge()` call instructs the `distance_recorder` to record distances +when a new edge in the BFS tree is encountered. This BFS visitor will effectively compute +the distance from a root vertex to all other vertices in the graph. + +This is a somewhat verbose way of writing the code. We could write it a little more +succinctly, although it's somewhat less readable: + + graph[kevin].distance = 0; + breadth_first_search(graph, kevin, + visitor(make_bfs_visitor(record_distances(get(&Actor::distance, graph), on_tree_edge()))) + ); + +After finishing, each vertex's distance property will be assigned. All there is left to do +is display the numbers: + + int main() + { + // ...continued from above... + Graph::vertex_iterator i, j; + for(tie(i, j) = vertices(g); i != j; ++i) { + cout << graph[*i].distance << " : " << graph[*i].name << "\n"; + } + } + +The output should look something like this (note that $ is a shell prompt): +[pre +$ ./kevin_bacon < movies +1 : Chris Penn +1 : Sarah Jessica Parker +2 : James Belushi +2 : David Ogden Stiers +3 : Mark Hamill +3 : Dan Akroyd +1 : John Belushi +1 : Tim Matheson +2 : Tom Hulce +2 : Peter Riegert +2 : Karen Allen +2 : Mike Meyers +2 : Sylvester Stallone +2 : Eddie Murphy +] + +[h4 The Kevin Bacon Game] +Using the above algorithm we can find how far away each actor is from Kevin Bacon, but what +if we want to know how to get there. For example, we know that Dan Akroyd is three steps away +so what are the movies? We could look at the input file, but that won't really give us any +advantage. A better solution would be to modify the program to record the shortest paths. + +Since the term /shortest paths/ arises in the problem description, we might be tempted to +use a shortest paths algorithm such as Dijkstra's. However, if we think about the problem a +little bit, we should realize that there aren't any edge weights - something required for +Dijkstra's algorithm. We could implicitly treat all edges as having a weight of one, but +that turns out to be somewhat ineffective. It turns out that we can use the same BFS +algorithm to record shortest paths instead of (or in addition to) actors' distances to +Kevin Bacon. Specifically, we can record each the parent of each vertex in the BFS tree +and simply backtrack from a given actor to Kevin Bacon. + +There are only a couple of modifications that we really need to make. First, we want to +add an extra property for each actor: its parent vertex in the search tree. For convenience, +we are also going to add a new property map type. + + struct Actor + { + // ...same as before... + Vertex parent; + }; + + // ... + typedef boost::property_map::type ActorParentMap; + +The only other changes are going to be in the `main()` program. + + int main(int argc, char *argv[]) + { + string src = "Kevin Bacon"; + string tgt; + + if(argc < 2) { + cerr << "usage: actor_paths actor [actor] < movies"; + return -1; + } + else if(argc == 2) { + tgt = argv[1]; + } + else { + src = argv[1]; + tgt = argv[2]; + } + + Graph graph; + ActorMap actors; + build_costar_graph(cin, graph, actors); + + // ...to be continued... + +This program accepts a couple of command line parameters. If one actor is given then +we find the path to Kevin Bacon. If two actors are given, we find the shortest path +between the two actors. We can now get the vertices for specified actors, and find +the paths between them. + + // ...continued from before... + Vertex u = find_actor_vertex(g, actors, src); + Vertex v = find_actor_vertex(g, actors, tgt); + if(u == Graph::null_vertex()) { + cerr << "could not find actor " << src << "\n"; + return -1; + } + if(v == Graph::null_vertex()) { + cerr << "could not find actor " << tgt << "\n"; + return -1; + } + + // get the parents map for later use. + ActorParentMap parents = get(&Actor::parent, g); + + breadth_first_search(graph, kevin, + visitor( + make_bfs_visitor(record_predecessors(distances, on_tree_edge())) + ) + ); + + // ...to be continued... + +The `find_actor_vertex()` method is relatively trivial. We extracted it as a function +so the program wouldn't be quite so repetitive. + + Vertex find_actor_vertex(const Graph& g, const ActorMap& actors, const std::string& name) + { + Vertex v = Graph::null_vertex(); + ActorMap::const_iterator i = actors.find(name); + if(i != actors.end()) { + v = i->second; + } + return v; + } + +Otherwise, the code is essentially the same as above. In this case, we're constructing +a `predecessor_recorder` as the visitor to the BFS. In contrast to the `distance_recorder` +this method stores the parents (or predecessor) of each vertex in the BFS tree. This is +an important property because it allows us to backtrack from one endpoint in the graph +to the starting point, showing the path from, say Kevin Bacon to any another actor. + +Backtracking is relatively easy. + + int main(...) + { + // ...continued from before... + while(v != u) { + Vertex p = parents[v]; + string from = g[v].name; + string to = g[p].name; + + // find the edge so we can print the movie + Edge e; + bool found; + tie(e, found) = edge(v, p, g); + + string movie = g[e].name; + cout << from << " starred with " << to << " in '" << movie << "'\n"; + + v = p; + } + + return 0; + } + +Althgough we could simply backtrack over the parents and print the actors in a chain, +we think it's more entertaining to know the movies that each pair co-stars in. To do +this we use the `edge()` function to locate the edge corresponding edge connecting +the two actors who costarred in a movie. + +The output might look something like: +[pre +$ ./six_degrees "Dan Akroyd" < movies +Dan Akroyd starred with Carrie Fisher in 'The Blues Brothers (1980)' +Carrie Fisher starred with Elisabeth Shue in 'Soapdish (1991)' +Elisabeth Shue starred with Kevin Bacon in 'Hollow Man (2000)' +] + +You now have a completely /unbeatable/ implementation of the "Six Degrees of Kevin +Bacon" game - provided of course that you add a lot more movie data to the simple +data set provided with this example. + +[endsect] \ No newline at end of file diff --git a/quickbook/history.qbk b/quickbook/history.qbk new file mode 100644 index 00000000..28321ad5 --- /dev/null +++ b/quickbook/history.qbk @@ -0,0 +1,110 @@ +[/ + / Copyright (c) 2007 Andrew Sutton + / + / 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) + /] + +[section History] + +The Boost Graph Library began its life as the Generic Graph Component Library (GGCL), a software +project at the Lab for Scientific Computing (LSC) at the University of Notre Dame, under the +direction of Professor Andrew Lumsdaine. The Lab's research directions include numerical linear +algebra, parallel computing, and software engineering (including generic programming). + +Soon after the Standard Template Library was released, work began at the LSC to apply generic +programming to scientific computing. The Matrix Template Library (Jeremy Siek's masters thesis) +was one of the first projects. Many of the lessons learned during construction of the MTL were +applied to the design and implementation of the GGCL. + +Graph algorithms play an important role in sparse matrix computations, so the LSC had a need for +a good graph library. However, none of the available graph libraries (LEDA, GTL, Stanford GraphBase) +were written using the generic programming style of the STL, and hence did not fulfill the flexibility +and high-performance requirements of the LSC. Others were also expressing interest in a generic C++ +graph library. During a meeting with Bjarne Stroustrup we were introduced to several people at AT&T +who needed such a library. There had also been earlier work in the area of generic graph algorithms, +including some codes written by Alexander Stepanov, and Dietmar Kuhl's masters thesis. + +With this in mind, and motivated by homework assignments in his algorithms class, Jeremy began +prototyping an interface and some graph classes in the spring on 1998. Lie-Quan Lee then developed +the first version of GGCL, which became his masters thesis project. + +The following year, Jeremy went to work for SGI with Alexander Stepanov and Matt Austern. During +this time Alex's disjoint-sets based connected components algorithm was added to GGCL, and Jeremy +began working on the concept documentation for GGCL similar to Matt's STL documentation. + +While working at SGI, Jeremy heard about Boost and was excited to find a group of people interested +in creating high-quality C++ libraries. At Boost there were several people interested in generic +graph algorithms, most notably Dietmar Kuhl. Some discussions about generic interfaces for graph +structures resulted in the a revision of GGCL which closely resembles the current Boost Graph Library +interface. + +On September 4, 2000 GGCL passed the Boost formal review and became the Boost Graph Library (BGL). +The first release of BGL was September 27, 2000. + +[h2 Changes by Revision] + +* Version 1.35.0 + * New algorithms and components + * kolmogorov_max_flow, from Stephan Diederich as part of the 2006 Google Summer of Code. + * read_dimacs_max_flow and write_dimacs_max_flow for max-flow problems, from Stephan Diederich. + * read_graphml and write_graphml for GraphML input/output, from Tiago de Paula Peixoto. + * Enhancements + * LEDA Adaptor improvements, from Jens Muller. + +* Version 1.34.0 + * New algorithms and components + * edmonds_maximum_cardinality_matching, from Aaron Windsor. + * lengauer_tarjan_dominator_tree, from JongSoo Park. + * compressed_sparse_row_graph, from Jeremiah Willcock and Douglas Gregor of Indiana University. + * sorted_erdos_renyi_iterator, from Jeremiah Willcock of Indiana University. + * Enhancements + * biconnected_components now has a visitor parameter and supports named parameters, from Janusz Piwowarski. + * adjacency_matrix now models the Bidirectional Graph concept. + * adjacency_list is now Serializable, from Jeremy Siek of Rice University. + * Added edges_size_type and vertices_size_type to adjacency_list_traits, from Jeremy Siek of Rice University. + * Added operator< , etc. to the edge descriptor of adjacency_list, from Jeremy Siek of Rice University. + * Bug Fixes + * Fixed a bug that causes the relaxed heap to fail on x86 Linux. + * Bundled properties now work with adjacency list I/O. + * floyd_warshall_all_pairs_shortest_paths now properly uses its compare, inf, and zero parameters. + * johnson_all_pairs_shortest_paths now supports compare, combine, inf, and zero. + * Fixed a bug in smallest_last_vertex_ordering.hpp which could cause a vertex to be moved to the wrong bucket during an BucketSorter update. + +* Version 1.33.1 + * Bug Fixes + * fruchterman_reingold_force_directed_layout: Fixed enumeration of grid-force pairs, which caused some odd graph formations along grid lines. + * king_ordering and cuthill_mckee_ordering: Fixed bug that caused failures with the multi-component version of these algorithms. + +* Version 1.33.0 + * New algorithms and components + * Experimental Python bindings, from Doug Gregor and Indiana University. + * floyd_warshall_all_pairs_shortest_paths, from Lauren Foutz and Scott Hill. + * astar_search, from Kristopher Beevers and Jufeng Peng. + * fruchterman_reingold_force_directed_layout, from Doug Gregor and Indiana University. + * biconnected_components and articulation_points, from Indiana University. + * gursoy_atun_layout, from Jeremiah Willcock and Doug Gregor of Indiana University. + * king_ordering, from D. Kevin McGrath of Indiana University. + * erdos_renyi_iterator + * plod_iterator + * small_world_iterator + * Enhancements + * bellman_ford_shortest_paths now permits one to specify the starting vertex, so that it will perform its own initialization. + * undirected_dfs is now data-recursive, resulting in improved performance in some cases, from Synge Todo. + * dijkstra_shortest_paths now uses a relaxed heap [61] as its priority queue, improving its complexity to O(V log V) and improving real-world performance for larger graphs. + * read_graphviz now has a new, Spirit-based parser that works for all graph types and supports arbitrary properties on the graph, from Ron Garcia. The old, Bison-based GraphViz reader has been deprecated and will be removed in a future Boost release. + * write_graphviz now supports output of dynamic properties (as read in through the new read_graphviz). + * cuthill_mckee_ordering has been recast as an invocation of breadth_first_search and now supports graphs with multiple components. + * subgraph now supports bundled properties. get_property now refers to the subgraph property, not the root graph's property. + * filtered_graph now supports bundled properties. + * reverse_graph now supports bundled properties, set_property, and get_property. + * Bug fixes + * bellman_ford_shortest_paths now deals with unreachable vertices better. + * adjacency_list: parallel edge removal with OutEdgeListS = listS has been fixed. Copying and swapping has been fixed. + * Incremental connected components: fixed a bug in the incremental_components routine that may have caused incorrect results. + * The remove_out_edge_if function for an undirected adjacency_list has been rewritten and should no longer dereference singular iterators. + * write_graphviz now accepts a vertex_id parameter that is used to name the nodes. + * read_graphviz now accepts empty attribute lists. + * sequential_vertex_coloring has been updated, tested, and documented. + +[endsect] \ No newline at end of file diff --git a/quickbook/images/eq/Makefile b/quickbook/images/eq/Makefile new file mode 100644 index 00000000..1c4d7eff --- /dev/null +++ b/quickbook/images/eq/Makefile @@ -0,0 +1,36 @@ + +src = \ + mean_geodesic.tex \ + small_world.tex \ + closeness.tex \ + scaled_closeness.tex \ + betweenness.tex \ + relative_betweenness.tex \ + central_point_dominance.tex \ + num_paths_directed.tex \ + num_paths_undirected.tex \ + num_triangles.tex \ + clustering_coef.tex +dvi = $(src:%.tex=%.dvi) +ps = $(src:%.tex=%.ps) +png = $(src:%.tex=%.png) +aux = $(src:%.tex=%.aux) +log = $(src:%.tex=%.log) + +%.png: %.ps + convert -density 120 $< $@ + +%.ps: %.dvi + dvips -E $< -o $@ + +%.dvi: %.tex + latex --interaction=nonstopmode $< + +all: $(png) + make clean-aux + +clean: + rm -f $(png) $(ps) $(dvi) $(aux) $(log) + +clean-aux: + rm -rf $(aux) $(log) $(dvi) \ No newline at end of file diff --git a/quickbook/images/eq/betweenness.tex b/quickbook/images/eq/betweenness.tex new file mode 100644 index 00000000..d02c5fae --- /dev/null +++ b/quickbook/images/eq/betweenness.tex @@ -0,0 +1,15 @@ +\documentclass[12pt]{article} + +\usepackage{amsmath} +\usepackage{amsfonts} +\usepackage{amssymb} +\usepackage{pst-plot} +\usepackage{color} +\pagestyle{empty} + +\begin{document} +\[ +C_B\left(v\right) = \sum_{s \neq v \neq t \in V} + \frac{\delta_{st}\left(v\right)}{\delta_{st}} +\] +\end{document} \ No newline at end of file diff --git a/quickbook/images/eq/central_point_dominance.tex b/quickbook/images/eq/central_point_dominance.tex new file mode 100644 index 00000000..4bf2a95c --- /dev/null +++ b/quickbook/images/eq/central_point_dominance.tex @@ -0,0 +1,16 @@ +\documentclass[12pt]{article} + +\usepackage{amsmath} +\usepackage{amsfonts} +\usepackage{amssymb} +\usepackage{pst-plot} +\usepackage{color} +\pagestyle{empty} + +\begin{document} +\[ +C'_B\left(G\right) = \frac + {\sum_{v \in V}{C_B\left(v^{*}\right) - C'_B\left(v\right)}} + {n - 1} +\] +\end{document} \ No newline at end of file diff --git a/quickbook/images/eq/closeness.tex b/quickbook/images/eq/closeness.tex new file mode 100644 index 00000000..0654bfca --- /dev/null +++ b/quickbook/images/eq/closeness.tex @@ -0,0 +1,15 @@ +\documentclass[12pt]{article} + +\usepackage{amsmath} +\usepackage{amsfonts} +\usepackage{amssymb} +\usepackage{pst-plot} +\usepackage{color} +\pagestyle{empty} + +\begin{document} +\[ +C\left(u\right) = + \frac{1}{\sum_{v \in V}{d\left(u,v\right)}} +\] +\end{document} \ No newline at end of file diff --git a/quickbook/images/eq/clustering_coef.tex b/quickbook/images/eq/clustering_coef.tex new file mode 100644 index 00000000..a6202c89 --- /dev/null +++ b/quickbook/images/eq/clustering_coef.tex @@ -0,0 +1,14 @@ +\documentclass[12pt]{article} + +\usepackage{amsmath} +\usepackage{amsfonts} +\usepackage{amssymb} +\usepackage{pst-plot} +\usepackage{color} +\pagestyle{empty} + +\begin{document} +\[ +CC\left(v\right) = \frac {P\left(v\right)}{T\left(v\right)} +\] +\end{document} \ No newline at end of file diff --git a/quickbook/images/eq/mean_geodesic.tex b/quickbook/images/eq/mean_geodesic.tex new file mode 100644 index 00000000..1a218624 --- /dev/null +++ b/quickbook/images/eq/mean_geodesic.tex @@ -0,0 +1,15 @@ +\documentclass[12pt]{article} + +\usepackage{amsmath} +\usepackage{amsfonts} +\usepackage{amssymb} +\usepackage{pst-plot} +\usepackage{color} +\pagestyle{empty} + +\begin{document} +\[ +\bar{D}\left(u\right) = + \frac{\sum_{v \in V}{d\left(u,v\right)}}{\left|V\right|-1} +\] +\end{document} \ No newline at end of file diff --git a/quickbook/images/eq/num_paths_directed.tex b/quickbook/images/eq/num_paths_directed.tex new file mode 100644 index 00000000..d31a328b --- /dev/null +++ b/quickbook/images/eq/num_paths_directed.tex @@ -0,0 +1,14 @@ +\documentclass[12pt]{article} + +\usepackage{amsmath} +\usepackage{amsfonts} +\usepackage{amssymb} +\usepackage{pst-plot} +\usepackage{color} +\pagestyle{empty} + +\begin{document} +\[ +P(v) = d\left(v\right) \cdot \left(d\left(v\right) - 1\right) +\] +\end{document} \ No newline at end of file diff --git a/quickbook/images/eq/num_paths_undirected.tex b/quickbook/images/eq/num_paths_undirected.tex new file mode 100644 index 00000000..21f077c0 --- /dev/null +++ b/quickbook/images/eq/num_paths_undirected.tex @@ -0,0 +1,16 @@ +\documentclass[12pt]{article} + +\usepackage{amsmath} +\usepackage{amsfonts} +\usepackage{amssymb} +\usepackage{pst-plot} +\usepackage{color} +\pagestyle{empty} + +\begin{document} +\[ +P(v) =\frac + {d\left(v\right) \cdot \left(d\left(v\right) - 1\right)} + {2} +\] +\end{document} \ No newline at end of file diff --git a/quickbook/images/eq/num_triangles.tex b/quickbook/images/eq/num_triangles.tex new file mode 100644 index 00000000..5e791de3 --- /dev/null +++ b/quickbook/images/eq/num_triangles.tex @@ -0,0 +1,14 @@ +\documentclass[12pt]{article} + +\usepackage{amsmath} +\usepackage{amsfonts} +\usepackage{amssymb} +\usepackage{pst-plot} +\usepackage{color} +\pagestyle{empty} + +\begin{document} +\[ +T(v) = \left|e_{pq} \in E\right| +\] +\end{document} \ No newline at end of file diff --git a/quickbook/images/eq/relative_betweenness.tex b/quickbook/images/eq/relative_betweenness.tex new file mode 100644 index 00000000..d7537ed7 --- /dev/null +++ b/quickbook/images/eq/relative_betweenness.tex @@ -0,0 +1,16 @@ +\documentclass[12pt]{article} + +\usepackage{amsmath} +\usepackage{amsfonts} +\usepackage{amssymb} +\usepackage{pst-plot} +\usepackage{color} +\pagestyle{empty} + +\begin{document} +\[ +C'_B\left(v\right) = C_B\left(v\right)\frac{2}{\left(n - 1\right)\left(n - 2\right)} += +C_B\left(v\right)\frac{2}{n^2-3n+2} +\] +\end{document} \ No newline at end of file diff --git a/quickbook/images/eq/scaled_closeness.tex b/quickbook/images/eq/scaled_closeness.tex new file mode 100644 index 00000000..53b90770 --- /dev/null +++ b/quickbook/images/eq/scaled_closeness.tex @@ -0,0 +1,15 @@ +\documentclass[12pt]{article} + +\usepackage{amsmath} +\usepackage{amsfonts} +\usepackage{amssymb} +\usepackage{pst-plot} +\usepackage{color} +\pagestyle{empty} + +\begin{document} +\[ +C\left(u\right) = + \frac{n}{\sum_{v \in V}{d\left(u,v\right)}} +\] +\end{document} \ No newline at end of file diff --git a/quickbook/images/eq/small_world.tex b/quickbook/images/eq/small_world.tex new file mode 100644 index 00000000..9c79f465 --- /dev/null +++ b/quickbook/images/eq/small_world.tex @@ -0,0 +1,20 @@ +\documentclass[12pt]{article} + +\usepackage{amsmath} +\usepackage{amsfonts} +\usepackage{amssymb} +\usepackage{pst-plot} +\usepackage{color} +\pagestyle{empty} + +\begin{document} +\[ +\bar{D}\left(G\right) + = \frac + {\displaystyle\sum_{u \in V}{\bar{D}\left(u\right)}} + {\left(\left|V\right|\right)} + = \frac + {\displaystyle\sum_{u \in V}\sum_{v \in V}{d\left(u,v\right)}} + {\left|V\right| \cdot \left(\left|V\right|-1\right)} +\] +\end{document} \ No newline at end of file diff --git a/quickbook/images/reference/Makefile b/quickbook/images/reference/Makefile new file mode 100644 index 00000000..fb2e7fc5 --- /dev/null +++ b/quickbook/images/reference/Makefile @@ -0,0 +1,46 @@ + +GVFLAGS = -Tpng + +dot_src = \ + connected_components_before.dot \ + connected_components_after.dot \ + geodesic.dot \ + info_network.dot +circo_src = \ + distribution_undirected.circo \ + distribution_directed.circo \ + triangle.circo \ + prism_3_2.circo +fdp_src = \ + social_network.fdp +neato_src = \ + comm_network.neato + +dot_png = $(dot_src:%.dot=%.png) +circo_png = $(circo_src:%.circo=%.png) +fdp_png = $(fdp_src:%.fdp=%.png) +neato_png = $(neato_src:%.neato=%.png) + +%.png: %.dot + dot $(GVFLAGS) -o $@ $< + convert $@ -resize 80% $@ + +%.png: %.circo + circo $(GVFLAGS) -o $@ $< + convert $@ -resize 80% $@ + +%.png: %.fdp + fdp $(GVFLAGS) -o $@ $< + convert $@ -resize 80% $@ + +%.png: %.neato + neato $(GVFLAGS) -o $@ $< + convert $@ -resize 80% $@ + +all: $(dot_png) $(circo_png) $(fdp_png) $(neato_png) + +clean: + rm -rf $(dot_png) + rm -rf $(circo_png) + rm -rf $(fdp_png) + rm -rf $(neato_png) diff --git a/quickbook/images/reference/comm_network.neato b/quickbook/images/reference/comm_network.neato new file mode 100644 index 00000000..d3996f33 --- /dev/null +++ b/quickbook/images/reference/comm_network.neato @@ -0,0 +1,17 @@ +graph { + // make this look like a directed graph + edge [dir=forward]; + + Mary -- Jill; + Jill -- Scott; + Scott -- Mary; + Scott -- Bill; + Bill -- Josh; + Josh -- Frank; + Frank -- Scott; + Frank -- Anne; + Anne -- Howard [len=2]; + Howard -- Frank; + Frank -- Laurie; + Laurie -- Mary; +}; \ No newline at end of file diff --git a/quickbook/images/reference/connected_components_after.dot b/quickbook/images/reference/connected_components_after.dot new file mode 100644 index 00000000..a16bdf14 --- /dev/null +++ b/quickbook/images/reference/connected_components_after.dot @@ -0,0 +1,12 @@ + + +graph G { + subgraph cluster_0 { + 0 -- 1 -- 2 -- 0; + label = "Component 0"; + } + subgraph cluster_1 { + 3 -- 4; + label = "Component 1"; + } +} \ No newline at end of file diff --git a/quickbook/images/reference/connected_components_before.dot b/quickbook/images/reference/connected_components_before.dot new file mode 100644 index 00000000..9271e3b7 --- /dev/null +++ b/quickbook/images/reference/connected_components_before.dot @@ -0,0 +1,5 @@ + +graph G { + 0 -- 1 -- 2 -- 0; + 3 -- 4; +} diff --git a/quickbook/images/reference/distribution_directed.circo b/quickbook/images/reference/distribution_directed.circo new file mode 100644 index 00000000..43f7eb98 --- /dev/null +++ b/quickbook/images/reference/distribution_directed.circo @@ -0,0 +1,11 @@ + +digraph G { + 0 -> 1; + 1 -> 2; + 2 -> 3; + 3 -> 5; + 5 -> 4; + 4 -> 1; + 4 -> 3; + 5 -> 2; +} \ No newline at end of file diff --git a/quickbook/images/reference/distribution_undirected.circo b/quickbook/images/reference/distribution_undirected.circo new file mode 100644 index 00000000..5a438ed0 --- /dev/null +++ b/quickbook/images/reference/distribution_undirected.circo @@ -0,0 +1,11 @@ + +graph G { + 0 -- 1; + 1 -- 2; + 2 -- 3; + 3 -- 5; + 5 -- 4; + 4 -- 1; + 4 -- 3; + 2 -- 5 +} \ No newline at end of file diff --git a/quickbook/images/reference/geodesic.dot b/quickbook/images/reference/geodesic.dot new file mode 100644 index 00000000..854b632a --- /dev/null +++ b/quickbook/images/reference/geodesic.dot @@ -0,0 +1,15 @@ + +graph G { + 0 -- 1; + 1 -- 2; + 1 -- 3; + 2 -- 4; + 3 -- 5; + 4 -- 6; + 4 -- 7; + 4 -- 8; + 5 -- 8; + 6 -- 9; + 7 -- 9; + 8 -- 9; +} \ No newline at end of file diff --git a/quickbook/images/reference/info_network.dot b/quickbook/images/reference/info_network.dot new file mode 100644 index 00000000..4dad74b7 --- /dev/null +++ b/quickbook/images/reference/info_network.dot @@ -0,0 +1,13 @@ +digraph { + slashdot -> wikipedia; + slashdot -> bbc; + digg -> slashdot; + digg -> wikipedia; + blogspot -> wikipedia; + blogspot-> slashdot; + blogger -> digg; + blogger -> slashdot; + blogger -> wikipedia; + bbc -> wikipedia; + myspace -> digg; +} \ No newline at end of file diff --git a/quickbook/images/reference/prism_3_2.circo b/quickbook/images/reference/prism_3_2.circo new file mode 100644 index 00000000..cbf99ea9 --- /dev/null +++ b/quickbook/images/reference/prism_3_2.circo @@ -0,0 +1,7 @@ +digraph { + 0 -> 1 -> 2 -> 0; + 3 -> 4 -> 5 -> 3; + 0 -> 3 -> 0; + 1 -> 4 -> 1; + 2 -> 5 -> 2; +} \ No newline at end of file diff --git a/quickbook/images/reference/social_network.fdp b/quickbook/images/reference/social_network.fdp new file mode 100644 index 00000000..15902b42 --- /dev/null +++ b/quickbook/images/reference/social_network.fdp @@ -0,0 +1,14 @@ +graph { + Scott -- Jill; + Mary -- Scott; + Jill -- Mary; + Bill -- Scott; + Josh -- Bill; + Scott -- Frank; + Laurie -- Frank; + Anne -- Frank; + Howard -- Anne; + Frank -- Howard; + Josh -- Frank; + Laurie -- Mary; +}; \ No newline at end of file diff --git a/quickbook/images/reference/triangle.circo b/quickbook/images/reference/triangle.circo new file mode 100644 index 00000000..72245147 --- /dev/null +++ b/quickbook/images/reference/triangle.circo @@ -0,0 +1,3 @@ +graph { + 0 -- 1 -- 2 -- 0; +} \ No newline at end of file diff --git a/quickbook/introduction.qbk b/quickbook/introduction.qbk new file mode 100644 index 00000000..356ae253 --- /dev/null +++ b/quickbook/introduction.qbk @@ -0,0 +1,214 @@ +[/ + / Copyright (c) 2007 Andrew Sutton + / + / 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) + /] + +[section Introduction] + +Graphs are mathematical abstractions that are useful for solving many types of problems in +computer science. Consequently, these abstractions must also be represented in computer +programs. A standardized generic interface for traversing graphs is of utmost importance to +encourage reuse of graph algorithms and data structures. Part of the Boost Graph Library is +a generic interface that allows access to a graph's structure, but hides the details of the +implementation. This is an "open" interface in the sense that any graph library that implements +this interface will be interoperable with the BGL generic algorithms and with other algorithms +that also use this interface. The BGL provides some general purpose graph classes that conform +to this interface, but they are not meant to be the ``only'' graph classes; there certainly will +be other graph classes that are better for certain situations. We believe that the main +contribution of the The BGL is the formulation of this interface. + +The BGL graph interface and graph components are generic, in the same sense as the the Standard +Template Library (STL). In the following sections, we review the role that generic programming +plays in the STL and compare that to how we applied generic programming in the context of graphs. + +Of course, if you are already are familiar with generic programming, please dive right in! Here's +the Table of Contents. + +The source for the BGL is available as part of the Boost distribution, which you can download +from here. + +[h2 How to Build Boost.Graph] +[*DON'T!] The Boost Graph Library is a header-only library and does not need to be built to be used. +The only exception is the GraphViz input parser. + +When compiling programs that use the BGL, be sure to compile with optimization. For instance, +select "Release" mode with Microsoft Visual C++ or supply the flag -O2 or -O3 to GCC. + +[h2 Genericity in the STL] +There are three ways in which the STL is generic. + +[h3 Algorithm/Data Structure Interoperability in the STL] +First, each algorithm is written in a data-structure neutral way, allowing a single template +function to operate on many different classes of containers. The concept of an iterator is the +key ingredient in this decoupling of algorithms and data-structures. The impact of this technique +is a reduction in the STL's code size from O(M*N) to O(M+N), where M is the number of algorithms +and N is the number of containers. Considering a situation of 20 algorithms and 5 data-structures, +this would be the difference between writing 100 functions versus only 25 functions! And the +differences continues to grow faster and faster as the number of algorithms and data-structures +increase. + +[h3 Extension Through Function Objects] +The second way that STL is generic is that its algorithms and containers are extensible. The user +can adapt and customize the STL through the use of function objects. This flexibility is what makes +STL such a great tool for solving real-world problems. Each programming problem brings its own set +of entities and interactions that must be modeled. Function objects provide a mechanism for extending +the STL to handle the specifics of each problem domain + +[h3 Element Type Parameterization] +The third way that STL is generic is that its containers are parameterized on the element type. Though +hugely important, this is perhaps the least "interesting" way in which STL is generic. Generic +programming is often summarized by a brief description of parameterized lists such as `std::list`. +This hardly scratches the surface! + +[h2 Genericity in Boost.Graph] +Like the STL, there are three ways in which the BGL is generic. + +[h3 Algorithm/Data Structure Interoperability in Boost.Graph] +First, the graph algorithms of the BGL are written to an interface that abstracts away the details +of the particular graph data-structure. Like the STL, the BGL uses iterators to define the interface +for data-structure traversal. There are three distinct graph traversal patterns: traversal of all +vertices in the graph, through all of the edges, and along the adjacency structure of the graph +(from a vertex to each of its neighbors). There are separate iterators for each pattern of traversal. + +This generic interface allows template functions such as breadth_first_search() to work on a large +variety of graph data-structures, from graphs implemented with pointer-linked nodes to graphs +encoded in arrays. This flexibility is especially important in the domain of graphs. Graph data +structures are often custom-made for a particular application. Traditionally, if programmers want +to reuse an algorithm implementation they must convert/copy their graph data into the graph library's +prescribed graph structure. This is the case with libraries such as LEDA, GTL, Stanford GraphBase; +it is especially true of graph algorithms written in Fortran. This severely limits the reuse of their +graph algorithms. + +In contrast, custom-made (or even legacy) graph structures can be used as-is with the generic graph +algorithms of the BGL, using external adaptation (see Section How to Convert Existing Graphs to the +BGL). External adaptation wraps a new interface around a data-structure without copying and without +placing the data inside adaptor objects. The BGL interface was carefully designed to make this +adaptation easy. To demonstrate this, we have built interfacing code for using a variety of graph +dstructures (LEDA graphs, Stanford GraphBase graphs, and even Fortran-style arrays) in BGL graph +algorithms. + +[h3 Extension through Visitors] +Second, the graph algorithms of the BGL are extensible. The BGL introduces the notion of a visitor, +which is just a function object with multiple methods. In graph algorithms, there are often several +key /event points/ at which it is useful to insert user-defined operations. The visitor object has +a different method that is invoked at each event point. The particular event points and corresponding +visitor methods depend on the particular algorithm. They often include methods like `start_vertex()`, +`discover_vertex()`, `examine_edge()`, `tree_edge()`, and `finish_vertex()`. + +[h3 Vertex and Edge Property Multi-Parameterization] +The third way that the BGL is generic is analogous to the parameterization of the element-type +in STL containers, though again the story is a bit more complicated for graphs. We need to +associate values (called "properties") with both the vertices and the edges of the graph. In +addition, it will often be necessary to associate multiple properties with each vertex and edge; +this is what we mean by multi-parameterization. The STL `std::list` class has a parameter `T` +for its element type. Similarly, BGL graph classes have template parameters for vertex and edge +"properties". A property specifies the parameterized type of the property and also assigns an +identifying tag to the property. This tag is used to distinguish between the multiple properties +which an edge or vertex may have. A property value that is attached to a particular vertex or edge +can be obtained via a property map. There is a separate property map for each property. + +Traditional graph libraries and graph structures fall down when it comes to the parameterization +of graph properties. This is one of the primary reasons that graph data-structures must be +custom-built for applications. The parameterization of properties in the BGL graph classes makes +them well suited for re-use. + +[h2 Algorithms] +Boost.Graph algorithms consist of a core set of algorithm patterns (implemented as generic algorithms) +and a larger set of graph algorithms. The core algorithm patterns are: +* Breadth First Search +* Depth First Search +* Uniform Cost Search + +By themselves, the algorithm patterns do not compute any meaningful quantities over graphs; they are +merely building blocks for constructing graph algorithms. The graph algorithms in the BGL currently +include: + +* Dijkstra's Shortest Paths +* Bellman-Ford Shortest Paths +* Johnson's All-Pairs Shortest Paths +* Kruskal's Minimum Spanning Tree +* Prim's Minimum Spanning Tree +* Connected Components +* Strongly Connected Components +* Dynamic Connected Components (using Disjoint Sets) +* Topological Sort +* Transpose +* Reverse Cuthill Mckee Ordering +* Smallest Last Vertex Ordering +* Sequential Vertex Coloring + +[h2 Data Structures] +Boost.Graph currently provides two graph classes and an edge list adaptor: + +* adjacency_list +* adjacency_matrix +* edge_list + +The adjacency_list class is the general purpose "swiss army knife" of graph classes. It is highly +parameterized so that it can be optimized for different situations: the graph is directed or +undirected, allow or disallow parallel edges, efficient access to just the out-edges or also to +the in-edges, fast vertex insertion and removal at the cost of extra space overhead, etc. + +The adjacency_matrix class stores edges in a |V| x |V| matrix (where |V| is the number of vertices). +The elements of this matrix represent edges in the graph. Adjacency matrix representations are +especially suitable for very dense graphs, i.e., those where the number of edges approaches |V|2. + +The `edge_list` class is an adaptor that takes any kind of edge iterator and implements an +Edge List Graph. + +[h2 Projects Using This Library] +This section should probably be merged into the global "Who's using me now page". But, for completeness +here's the list (with links, too): + +* [@http://www.cs.rpi.edu/~musser/gsd/ Generic Software Design Course at RPI] +* [@http://alps.comp-phys.org/ The ALPS quantum mechanics project] +* [@http://bioinformatics.icmb.utexas.edu/lgl/ Large Graph Layout at University of Texas] +* [@http://www.cs.concordia.ca/~gregb/home/c691R-w2004.html Bioinformatics Algorithms at Concordia University] +* [@http://photon.poly.edu/~hbr/cs903/ Algorithm Course at Polytechnic University in Brooklyn] +* [@http://www.bioconductor.org/repository/devel/vignette/RBGL.pdf BGL interface for language R] +* [@http://www.cuj.com/documents/s=8470/cuj0307tan/ CUJ Article about Electronic Design Automation] +* [@http://rubyforge.org/projects/rgl/ A BGL-inspired Ruby Graph Library] +* [@http://www.codeproject.com/cs/miscctrl/quickgraph.asp A BGL-inspired C# Graph Library] +* [@http://map1.squeakfoundation.org/sm/package/5729d80a-822b-4bc2-9420-ef7ecaea8553 A BGL-inspired Squeak (Smalltalk) Graph Library] +* [@http://www.datasim.nl/education/coursedetails.asp?coursecategory=CPP&coursecode=ADCPP BGL course at DataSim] +* [@http://www.vrjuggler.org/ VR Juggler: Virtual Reality Tools] +* [@http://hyperworx.org Hyperworx Platform Project] + +[h2 Publications about this Library] +* Dr. Dobb's Sept. 2000 Article +* OOPSLA'99 GGCL Paper +* Lie-Quan Lee's Master's Thesis about GGCL(ps) (pdf) +* Dietmar Kuhl's Master's Thesis: Design Pattern for the Implementation of Graph Algorithms +* ISCOPE'99 Sparse Matrix Ordering (pdf) +* C++ Template Workshop 2000, Concept Checking + +[h2 Acknowledgements] +We owe many debts of thanks to a number of individuals who both inspired and encouraged us in +developing the Boost Graph Library. + +A most profound thanks goes to Alexander Stepanov for his pioneering work in generic programming, +for his encouragement, and for his algorithm contributions to the BGL. We thank Matthew Austern for +his work on documenting the concepts of STL which provided a foundation for creating the concepts in +the BGL. We thank Dietmar Kuhl for his work on generic graph algorithms and design patterns; +especially for the property map abstraction. + +Dave Abrahams, Jens Maurer, Beman Dawes, Gary Powell, Greg Colvin, Valentin Bonnard, and the rest +of the group at Boost provided valuable input to the BGL interface, numerous suggestions for improvement, +proof reads of the documentation, and help with polishing the code. A special thanks to Dave Abrahams +for managing the formal review. + +We also thank the following BGL users whose questions helped to improve the BGL: Gordon Woodhull, +Dave Longhorn, Joel Phillips, and Edward Luke. + +A special thanks to Jeffrey Squyres for editing and proof reading of the documentation. + +Our original work on the Boost Graph Library was supported in part by NSF grant ACI-9982205 and by +the Director, Office of Science, Division of Mathematical, Information, and Computational Sciences of +the U.S. Department of Energy under contract number DE-AC03-76SF00098. + +In our work we also used resources of the National Energy Research Scientific Computing Center, which +is supported by the Office of Science of the U.S. Department of Energy. + +[endsect] \ No newline at end of file diff --git a/quickbook/reference/adjacency_list.qbk b/quickbook/reference/adjacency_list.qbk new file mode 100644 index 00000000..ce2c4e70 --- /dev/null +++ b/quickbook/reference/adjacency_list.qbk @@ -0,0 +1,411 @@ +[/ + / Copyright (c) 2007 Andrew Sutton + / + / 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) + /] + +[section Adjacency List] + +[warning +This reference is missing documentation for a number of associated types and +methods. +] + +[h4 Missing or Incorrect Documentation] +* `edge_iterator` +* `clear_in_edges()` +* `clear_out_edges()` + +The adjacency_list class implements a generalized adjacency list graph structure. +The template parameters provide many configuration options so that you can pick a +version of the class that best meets your needs. An adjacency-list is basically a +two-dimensional structure, where each element of the first dimension represents a +vertex, and each of the vertices contains a one-dimensional structure that is its +edge list. Figure 1 shows an adjacency list representation of a directed graph. + +The VertexList template parameter of the adjacency_list class controls what kind +of container is used to represent the outer two-dimensional container. The +OutEdgeList template parameter controls what kind of container is used to represent +the edge lists. The choices for OutEdgeList and VertexList will determine the space +complexity of the graph structure, and will determine the time complexity of the +various graph operations. The possible choices and tradeoffs are discussed in +Section Choosing the Edgelist and VertexList. + +The Directed template parameter controls whether the graph is directed, undirected, +or directed with access to both the in-edges and out-edges (which we call +bidirectional). The bidirectional graph takes up twice the space (per edge) of a +directed graph since each edge will appear in both an out-edge and in-edge list. +Figure 2 shows an adjacency list representation of an undirected graph. + +A tutorial on how to use the adjacency_list class is in Section Using adjacency_list. + +[h3 Template Parameters] +[table + [[Parameter] [Description] [Default]] + [ + [`OutEdgeList`] + [ + The selector for the container used to represent the edge-list for each + of the vertices. + ] + [`vecS`] + ] + [ + [`VertexList`] + [ + The selector for the container used to represent the vertex-list of the graph. + ] + [`vecS`] + ] + [ + [`Directed`] + [ + A selector to choose whether the graph is directed, undirected, or + directed with bidirectional edge access (access to both out-edges + and in-edges). The options are directedS, undirectedS, and + bidirectionalS. + ] + [`directedS`] + ] + [ + [`VertexProperties`] + [Specifies internal properties for vertices.] + [`no_property`] + ] + [ + [`EdgeProperties`] + [Specifies internal properties for edges.] + [`no_property`] + ] + [ + [`GraphProperties`] + [Specifies internal properties for the graph object.] + [`no_property`] + ] + [ + [`EdgeList`] + [ + The selector for the container used to represent the edge-list for + the graph. + ] + [`listS`] + ] +] + +[h4 Model of] +VertexAndEdgeListGraph, MutablePropertyGraph, CopyConstructible, Assignable, +and Serializable. + +[h4 Where Defined] + +`boost/graph/adjacency_list.hpp` + +The serialization functionality is in `boost/graph/adj_list_serialize.hpp`. + +[h3 Vertex and Edge Properties] +Properties such as color, distance, weight, and user-defined properties can be +attached to the vertices and edges of the graph using properties. The property +values can be read from and written to via the property maps provided by the +graph. The property maps are obtained via the get(property, g) function. How +to use properties is described in Section Internal Properties . The property +maps are objects that implement the interface defined in Section Property Map +Concepts or may be bundled properties, which have a more succinct syntax. The +types of all property values must be Copy Constructible, Assignable, and +Default Constructible. The property maps obtained from the adjacency_list class +are models of the Lvalue Property Map concept. If the adjacency_list is const, +then the property map is constant, otherwise the property map is mutable. + +If the VertexList of the graph is vecS, then the graph has a builtin vertex +indices accessed via the property map for the vertex_index_t property. The +indices fall in the range [0, num_vertices(g)) and are contiguous. When a +vertex is removed the indices are adjusted so that they retain these +properties. Some care must be taken when using these indices to access exterior + roperty storage. The property map for vertex index is a model of Readable +Property Map. + +[h3 Iterator and Descriptor Stability/Invalidation] +Some care must be taken when changing the structure of a graph (via adding or +removing edges). Depending on the type of adjacency_list and on the operation, +some of the iterator or descriptor objects that point into the graph may become +invalid. For example, the following code will result in undefined (bad) +behavior: + + typedef adjacency_list Graph; // VertexList = vecS + Graph G(N); + + // Fill in the graph... + + // Attempt to remove all the vertices. Wrong! + graph_traits::vertex_iterator vi, vi_end; + for(tie(vi, vi_end) = vertices(G); vi != vi_end; ++vi) { + remove_vertex(*vi, G); + } + + // Remove all the vertices. This is still wrong! + graph_traits::vertex_iterator vi, vi_end, next; + tie(vi, vi_end) = vertices(G); + for(next = vi; vi != vi_end; vi = next) { + ++next; + remove_vertex(*vi, G); + } + +The reason this is a problem is that we are invoking remove_vertex(), which +when used with an adjacency_list where VertexList=vecS, invalidates all +iterators and descriptors for the graph (such as vi and vi_end), thereby +causing trouble in subsequent iterations of the loop. + +If we use a different kind of `adjacency_list`, with `VertexList` as `listS`, +then the iterators are not invalidated by calling remove_vertex unless the +iterator is pointing to the actual vertex that was removed. The following code +demonstrates this. + + typedef adjacency_list Graph; // VertexList = listS + Graph G(N); + + // Fill in the graph... + + // Attempt to remove all the vertices. Wrong! + graph_traits::vertex_iterator vi, vi_end; + for(tie(vi, vi_end) = vertices(G); vi != vi_end; ++vi) { + remove_vertex(*vi, G); + } + + // Remove all the vertices. This is OK. + graph_traits::vertex_iterator vi, vi_end, next; + tie(vi, vi_end) = vertices(G); + for(next = vi; vi != vi_end; vi = next) { + ++next; + remove_vertex(*vi, G); + } + +The stability issue also affects vertex and edge descriptors. For example, +suppose you use vector of vertex descriptors to keep track of the parents +(or predecessors) of vertices in a shortest paths tree (see +`examples/dijkstra-example.cpp`). You create the parent vector with a call +to dijkstra_shortest_paths(), and then remove a vertex from the graph. +Subsequently you try to use the parent vector, but since all vertex descriptors +have become invalid, the result is incorrect. + + std::vector parent(num_vertices(G)); + std::vector distance(num_vertices(G)); + + dijkstra_shortest_paths(G, s, + distance_map(&distance[0]) + .predecessor_map(&parent[0])); + + 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) { + std::cout << p[*vi] << " is the parent of " << *vi << std::endl; + } + +Note that in this discussion iterator and descriptor invalidation is concerned +with the invalidation of iterators and descriptors that are not directly +affected by the operation. For example, performing `remove_edge(u, v, g)` will +always invalidate any edge descriptor for /(u,v)/ or edge iterator pointing to +/(u,v)/, regardless of the kind `adjacency_list`. In this discussion of iterator +and descriptor invalidation, we are only concerned with the affect of +`remove_edge(u, v, g)` on edge descriptors and iterators that point to other +edges (not /(u,v)/). + +In general, if you want your vertex and edge descriptors to be stable (never +invalidated) then use listS or setS for the VertexList and OutEdgeList template +parameters of adjacency_list. If you are not as concerned about descriptor and +iterator stability, and are more concerned about memory consumption and graph +traversal speed, use vecS for the VertexList and/or OutEdgeList template +parameters. + +The following table summarizes which operations cause descriptors and iterators +to become invalid. In the table, OEL is an abbreviation for OutEdgeList and VL +means VertexList. The "Adjacency Iterator" category includes the `out_edge_iterator`, +`in_edge_iterator`, and `adjacency_iterator types`. A more detailed description of +descriptor and iterator invalidation is given in the documentation for each +operation. + +[table + [[Function] [Vertex Descriptor] [Edge Descriptor] [Vertex Iterator] [Edge Iterator] [Adjacency Iterator]] + [ + [`add_edge()`] + [Valid] + [Valid] + [Valid] + [ + OEL = `vecS` && + + Directed = `directedS`] + [OEL = `vecS`] + ] + [ + [ + `remove_edge()` + + `remove_edge_if()` + + `remove_out_edge_if()` + + `remove_in_edge_if()` + + `clear_vertex()` + ] + [Valid] + [Valid] + [Valid] + [ + OEL = `vecS` && + + Directed = `directedS`] + [OEL = `vecS`] + ] + [ + [`add_vertex()`] + [Valid] + [Valid] + [Valid] + [Valid] + [Valid] + ] + [ + [`remove_vertex()`] + [VL = `vecS`] + [VL = `vecS`] + [VL = `vecS`] + [VL = `vecS`] + [VL = `vecS`] + ] +] + +[h3 Associated Types] +[table + [[Type] [Description]] + [ + [`graph_traits::vertex_descriptor`] + [ + The type for the vertex descriptors associated with the `adjacency_list`. + ] + ] + [ + [`graph_traits::edge_descriptor`] + [ + The type for the edge descriptors associated with the `adjacency_list`. + ] + ] + [ + [`graph_traits::vertex_iterator`] + [ + The type for iterators returned by `vertices()`. The concept modeled by this + type varies with the type of the `VertexList` parameter. If the `VertexList` + selector is `vecS`, then this type models the `RandomAccessIterator` concept. + In all other cases, it is a model of `BidirectionalIterator`. + ] + ] + [ + [`graph_traits::out_edge_iterator`] + [ + The type for iterators returned by `edges()`. The concept modeled by this type + depends on the `OutEdgeList` parameter. If the selector is `vecS` then the + iterator is a model of `RandomAccessIterator`. If the selector is `slistS` + then it is a model of `ForwardIterator`. Otherwise, the iterator models + `BidirectionalIterator`. + ] + ] + [ + [`graph_traits::in_edge_iterator`] + [ + This type is only valid if the `Directed` parameter is given as `bidirectionalS`. + The concepts modeled by this type are the same as the `out_edge_iterator`. + ] + ] + [ + [`graph_traits::adjacency_iterator`] + [ + The type for iterators returned by `adjacent_vertices()`. The concepts modeled + by this type are the same as `out_edge_iterator`. Dereferencing these types, + however, will result in vertex descriptors rather than edge descriptors. + ] + ] + [ + [`graph_traits::inv_adjacency_iterator`] + [ + The type for iterators returned by `inv_adjacent_vertices()`. The concepts + modeled by this type are identical to hose of the `adjacency_iterator`. + ] + ] + [ + [`graph_traits::directed_category`] + [ + Provides inforamtion about whether the graph is undirected (`undirected_tag`), + directed (`directed_tag`), or bidirectional (`bidirectional_tag`). + ] + ] + [ + [`graph_traits::edge_parallel_category`] + [ + This describes whether the class allows the insertion of parallel edges; those + with the same source and target. When `EdgeList` is selected as `setS` or + `hash_setS`, this type is set to `disallow_parallel_edge_tag`. Otherwise it + is `allow_parallel_edge_tag`. + ] + ] + [ + [`graph_traits::vertices_size_type`] + [The type used for dealing with the number of vertices in the graph. ] + ] + [ + [`graph_traits::edge_size_type`] + [The type used for dealing with the number of edges in the graph. ] + ] + [ + [`graph_traits::degree_size_type`] + [The type used for dealing with the number of edges incident to a vertex in the graph. ] + ] + [ + [ + `property_map::type` + + `property_map::const_type` + ] + [ + The property map type for vertex or edge properties in the graph. The specific + property is specified by the `Property` template argument, and must match one of + the properties specified in the `VertexProperties` or `EdgeProperties` for the + graph. + ] + ] + [ + [`graph_property::type`] + [ + The value type ofor the graph property specified by the `Property` parameter. + ] + ] + [ + [`adjacency_list::out_edge_list_selector`] + [The instantiated type of the `OutEdgeList` template parameter.] + ] + [ + [`adjacency_list::vertex_list_selector`] + [The instantiated type of the `VertexList` template parameter.] + ] + [ + [`adjacency_list::directed_selector`] + [The instantiated type of the `Directed` template parameter.] + ] + [ + [`adjacency_list::edge_list_selector`] + [The instantiated type of the `EdgeList` template parameter.] + ] +] + +[h3 Member Functions] +[table + [[Member Function] [Description]] + [ + [`adjacency_list(const GraphProperties& = GraphProperties()`] + [ + The default constructor creates an empty graph with no vertices or edges. + ] + ] +] + +[endsect] \ No newline at end of file diff --git a/quickbook/reference/betweenness_centrality.qbk b/quickbook/reference/betweenness_centrality.qbk new file mode 100644 index 00000000..697cef22 --- /dev/null +++ b/quickbook/reference/betweenness_centrality.qbk @@ -0,0 +1,185 @@ +[/ + / Copyright (c) 2007 Andrew Sutton + / + / 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) + /] + +[section Betweenness Centrality] + + template + void + brandes_betweenness_centrality(const Graph& g, CentralityMap cm) + + template + void + brandes_betweenness_centrality(const Graph& g, + CentralityMap cm, + EdgeCentralityMap ecm) + + // Named Parameter Interface + template + void brandes_betweenness_centrality(const Graph& g, ...); + + +The /betweenness centrality/ measure is commonly used in network analysis to identify +vertices (also called actors) that are lie many shortest paths between other vertices +in a graph. Intuitively, vertices with high betweenness centrality act as "hubs" through +which more information flows. The betweenness centrality of a vertex is given as + +[$images/eq/betweenness.png] + +Where ['[delta][sub st]] is the number of shortest paths between the vertices /s/ and +/t/ and ['[delta][sub st](v)] is the number of shortest paths that pass through the +vertex /v/. Note that the ratio inside the sum an be interpreted as the probability +that /v/ lies on a shortest path between the vertices /s/ and /t/. + +This function can also consider the /edge betweenness centrality/, which is defined +as, fro each edge, the betweenness centrality that was contribuetd to the targets +of the edge. This is plural for undirected graphs. Like vertex betweenness, this +measure can be used to determine the edges through which most shortest paths must +pass. + +These functions measure the /absolute/ betweenness centrality for vertices. These +values can be converted to /relative/ betweenness centrality by scaling each of +the absolute values by: + +[$images/eq/relative_betweenness.png] + +Where /n/ is the number of vertices in the graph. Also, given the relative betwenness +centrality, one can compute the /central point dominance/, which is a mueasure of the +maximum betweenness of any point in the graph. For example, this value will be 0 for +complete graphs and 1 for star graphs (where all paths cross a central vertex). +The central point dominance of a graph is defined as: + +[$images/eq/central_point_dominance.png] + +This module provides a number of functions for computing both vertex and edge +centrality and related measures. + +[heading Where Defined] +`boost/graph/betweenness_centrality.hpp` + +[heading Parameters] +[table + [[Type] [Parameter] [Description]] + [ + [required, in] [`const Graph& g`] + [ + The graph for which the betweenness centrality of vertices or edges + is being computed. + + *Requirements:* The `Graph` type must be a model of the [VertexListGraph] + and [IncidenceGraph] concepts. If the `EdgeCentralityMap` parameter + is present, this parameter type must also model the [EdgeListGraph]. + ] + ] + [ + [required, out] [`CentralityMap cm`] + [ + The graph for which the betweenness centrality of vertices or edges + is being computed. + + *Requirements:* + ] + ] + [ + [required, in] [`DistanceMap dm`] + [ + Given a vertex `v`, the `dm` parameter provides the length of the + shortest path between a vertex `u` and `v`. The vertex `u` is the + vertex for which the distance map was initially computed. + + *Requirements:* `DistanceMap` must be a model of [ReadablePropertyMap]. + The `key_type` of the distance map must be the same as the `vertex_descriptor` + of the `Graph` parameter. The `value_type` is required to be a model of + [NumericValue]. + ] + ] + [ + [required, in] [`DistanceMatrixMap dm`] + [ + Given vertices /u/ and /v/, the `dm` parameter provides the length + of the shortest path between the two vertices. Note that the + distance between a vertex and itself should be 0 (i.e., `dm[u][u] == 0`). + + *Requirements:* `DistanceMatrixMap` must be a model of [ReadablePropertyMap]. + The `key_type` of the distance matrixc must be the same as the `vertex_descriptor` + of the `Graph` parameter. The `value_type` must be a [ReadWritePropertyMap] + whose `key_type` is also the `vertex_descriptor` of the `Graph` and + whose `value_type` is a model of [NumericValue]. + ] + ] + [ + [required, out] [`ClosenessMap cm`] + [ + The cm parameter stores the output of the computed closeness (or + distance) for each vertex in `g`. + + *Requirements:* The type of `close` must be model the [WritablePropertyMap] + concepts. The `key_type` of the property map must be the same as the + `vertex_descriptor` of the `Graph`, and the `value_type` must be a model + of [NumericValue]. + ] + ] + [ + [optional, in] [`Measure measure`] + [ + The 'measure' parameter is an instance of a closeness measure that + performs the final operation (the reciprocal) for this computation. + + *Requirements:* The `Measure` type must be a model of the [DistanceMeasure] + concept. The `distance_type` must be the same type as the `value_type` + of the `DistanceMap` or `DistanceMatrixMap`. The `result_type` of the + `Measure` must model the [NumericValue] concept. + ] + ] +] + +[heading Return] +The `vertex_closeness_centrality()` function returns the closeness of a vertex. +If the source vertex is disconnected from any vertices in the graph, this value is 0. + +[heading Complexity] +The `closenesss_centrality()` function returns in ['O(n[super 2]*O(M))] where /n/ +is the number of vertices in the graph and /M/ is the complexity of the given distance +measure. This is ['O(n[super 2])] by default + +The `vertex_closeness_centrality()` function returns in ['O(n*O(M))]. This is +linear by default. + +[heading Example (Closeness Centrality)] + +[heading Undocumented Functions] +These functions are also part of the betweenness centrality module, but are not +documented since they are more appropriately called using the named parameter +interface. + + template + void + brandes_betweenness_centrality(const Graph& g, + CentralityMap centrality, + EdgeCentralityMap edge_centrality, + IncomingMap incoming, + DistanceMap distance, + DependencyMap dependency, + PathCountMap path_count, + VertexIndexMap vertex_index) + + template + void + brandes_betweenness_centrality(const Graph& g, + CentralityMap centrality, + EdgeCentralityMap edge_centrality, + IncomingMap incoming, + DistanceMap distance, + DependencyMap dependency, + PathCountMap path_count, + VertexIndexMap vertex_index, + WeightMap weight_map) + +[endsect] diff --git a/quickbook/reference/breadth_first_search.qbk b/quickbook/reference/breadth_first_search.qbk new file mode 100644 index 00000000..9facc789 --- /dev/null +++ b/quickbook/reference/breadth_first_search.qbk @@ -0,0 +1,153 @@ +[/ + / Copyright (c) 2007 Andrew Sutton + / + / 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) + /] + +[section Breadth-First Search] + template + void + breadth_first_search(Graph& g, + typename graph_traits::vertex_descriptor s, + bgl_named_params& params = ``/defaults/``) + + template + void + breadth_first_search(Graph& g, + typename graph_traits::vertex_descriptor s, + Buffer& q, + Visitor vis, + bgl_named_params& params = ``/defaults/``) + +The `breadth_first_search()` function performs a breadth-first traversal \[49\] of a directed or +undirected graph. A breadth-first traversal visits vertices that are closer to the source before +visiting vertices that are further away. In this context "distance" is defined as the number of edges +in the shortest path from the source vertex. The `breadth_first_search()` function can be used to +compute the shortest path from the source to all reachable vertices and the resulting shortest-path +distances. For more definitions related to BFS, see section Breadth-First Search. + +BFS uses two data structures to to implement the traversal: a color marker for each vertex and +a queue. White vertices are undiscovered while gray vertices are discovered but have undiscovered +adjacent vertices. Black vertices are discovered and are adjacent to only other black or gray +vertices. The algorithm proceeds by removing a vertex /u/ from the queue and examining each out-edge +/(u,v)/. If an adjacent vertex /v/ is not already discovered, it is colored gray and placed in the +queue. After all of the out-edges are examined, vertex u is colored black and the process is +repeated. Pseudo-code for the BFS algorithm is a listed below. + +[pre +BFS(G, s) + for each vertex u in V\[G\] initialize vertex u + color\[u\] := WHITE + d\[u\] := infinity + p\[u\] := u + end for + + color\[s\] := GRAY + d\[s\] := 0 + ENQUEUE(Q, s) discover vertex s + + while not EMPTY(Q) + u := DEQUEUE(Q) examine vertex u + for each vertex v in adj\[u\] examine edge /(u,v)/ + if(color\[v\] = WHITE) /(u,v)/ is a tree edge + color\[v\] := GRAY + d\[v\] := d\[u\] + 1 + p\[v\] := u + ENQUEUE(Q, v) discover vertex v + else /(u,v)/ is a non-tree edge + if (color\[v\] = GRAY) /(u,v)/ has a gray target + ... + else /(u,v)/ has a black target + ... + end if + end for + color\[u\] := BLACK finsih vertex u + end while + return (d, p) +] + +[heading Where Defined] +`boost/graph/breadth_first_search.hpp` + +[heading Parameters] +[table + [[Type] [Parameter] [Description]] + [ + [in] [`Graph& g`] + [ + A directed or undirected graph. The graph type must be a model of [VertexListGraph] + and [IncidenceGraph]. + ] + ] + [ + [in] [`vertex_descriptor s`] + [ + The source vertex where the search is started. This must be a valid vertex descriptor of + `g`. + ] + ] +] + +[heading Named Parameters] +[table + [[Type] [Parameter] [Description]] + [ + [in] [`visitor(Visitor vis)`] + [ + A visitor object that is inovked inside the algorithm at event points specified by the + [BFSVisitor]. The `vis` object must be model the [BFSVisitor] concept. + + *Default* `bfs_visitor`. + ] + ] + [ + [in] [`vertex_index_map(VeretxIndexMap index_map)`] + [ + This maps each vertex to an integer in the range \[0, `num_vertices(g)`). + This parameter is only necessary when the default color property map is + used. The type VertexIndexMap must be a model of ReadablePropertyMap. The + value type of the map must be an integer type. The vertex descriptor type + of the graph needs to be usable as the key type of the map. + + *Default* `get(vertex_index, g)`. Note if you use this default, make sure + that your graph has an interior `vertex_index` property. For example + `adjacency_list` with `VertexList=listS` does not have an interior + `vertex_index` property. + ] + ] + [ + [util] [`color_map(ColorMap color)`] + [ + This is used by the algorithm to keep track of its progress through the + graph. The type ColorMap must be a model of ReadWritePropertyMap and + its key type must be the graph's `vertex_descriptor` type and the value + type of the color map must model ColorValue. + + *Default* An `iterator_property_map` create from a `std::vector` of + `default_color_type` of size `num_vertices(g)` and using `index_map` as + the index map (to access colors for a vertex). + ] + ] + [ + [util] [`buffer(Buffer& q)`] + [ + The queue used to determine the order in which vertices will be discovered. + If a FIFO queue is used, then the traversal will be according to the usual + BFS ordering. Other types of queues can be used, but the traversal order will + be different. For example Dijkstra's algorithm can be implemented using a + priority queue. The type Buffer must be a model of [NoConcept Buffer]. + + The `value_type` of the buffer must be the vertex_descriptor type for the graph. + + *Default* `boost::queue` + ] + ] +] + +[heading Complexity] +The time complexity is /O(E + V)/. + +[heading Example] + +[endsect] \ No newline at end of file diff --git a/quickbook/reference/bron_kerbosch_all_cliques.qbk b/quickbook/reference/bron_kerbosch_all_cliques.qbk new file mode 100644 index 00000000..9048de9f --- /dev/null +++ b/quickbook/reference/bron_kerbosch_all_cliques.qbk @@ -0,0 +1,191 @@ +[/ + / Copyright (c) 2007 Andrew Sutton + / + / 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) + /] + +[section Bron Kerbosch All Cliques] +[template ex_bron_kerbosch_printing_cliques[] [link + boost_graph.reference.algorithms.subgraph.bron_kerbosch_all_cliques.examples.printing_cliques + Printing Cliques Example]] +[template ex_bron_kerbosch_clique_number[] [link + boost_graph.reference.algorithms.subgraph.bron_kerbosch_all_cliques.examples.clique_number + Clique Number Example]] + +[heading Overview] +This algorithm finds all /cliques/ of the given graph, invoking a visitor when +each clique is found. A clique is formally defined as a maxiamally connected +subgraph of a graph. This means that there are no more (and no fewer) vertices +in the graph that are connected to all other vertices in the graph. A vertex can +participate in many cliques. Note that the smallest clique contains two vertices +since each vertex is connected to the other. + +Consider the social network (represented by an undirected graph) in Figure 1. + +[figure + images/reference/social_network.png + *Figure 1.* A network of friends. +] + +There are a number of cliques in the graph. We can easily identify the two largest: + +* Scott, Jill, and Mary +* Frank, Howard, and Anne + +There are six other cliques represented by pairs of actors. Note that the Scott, +Mary, Frank, and Laurie do not form a clique because Mary and Frank are not directly +connected. See the [ex_bron_kerbosch_printing_cliques] for more details. + +The /clique number/ of a graph is defined as the size (the number of vertices) of +the largest clique in the graph. The social network in Figure 1 has a clique number +of 3. The [bron_kerbosch_clique_number] implements this measure. See the +[ex_bron_kerbosch_clique_number] for an example of its use. + +The Bron-Kerbosch algorithm was originally developed to operate over adjacency +matrices representing /undirected graphs/. The algorithm can also be applied to +/directed graphs/ using a more restrictive definition of a connected subgraph. +A /directed clique/ is a maximally connected subgraph in which each pair of vertices +/u/ and /v/ are connected by the edges /(u, v)/ and /(v, u)/. + +Although the algorithm can be used with adjacency list-based graph classes, it +will perform less efficiently than an adjacency matrix. Also, running this algorithm +on a directed graph will double the performance penalty (which is generally negligible). + +[section [^bron_kerbosch_all_cliques()]] + #include + + template + void bron_kerbosch_all_cliques(const Graph& g, Visitor vis) + +[heading Parameters] +[table + [[Type] [Parameter] [Description]] + [ + [required, in] [`const Graph& g`] + [ + The graph for which cliques are being visited. + + *Preconditions:* The indices of vertices in the graph must be + in the range \[0, `num_vertices(g)`). + + *Requirements:* The `Graph` type must be a model of the [AdjacencyMatrix], + [IncidenceGraph] concept and the [VertexIndexGraph] + concepts[footnote Any `Graph` type that implements the `edge()` + function will satisfy the expression requirements for the + [AdjacencyMatrix], but may incur additional overhead due non-constant + time complexity.]. + ] + ] + [ + [required, in] [`Visitor vis`] + [ + The visitor object to the algorithm. + + *Requirements:* This `Visitor` class must model the + [CliqueVisitor] class. + ] + ] + [ + [optional, in] [`std::size_t min`] + [ + The minimum size of a clique to visit. + + *Default:* 2 - the size of the smallest possible clique. + ] + ] +] + +[heading Complexity] +This problem has a loose upper bound of ['O(2[super n])] if one considers all possible +combinations of subsets of vertices as cliques (i.e., the powerset of vertices). +The original publication, however, approximates the runtime of the algorithm as +being proportional to ['O(3.14[super n])]. + +Graphs that do not meet the constant-time requirements of the [AdjacencyMatrix] +concept will incur additional runtime costs during execution (usually by a linear +factor). Examples of such graphs include the [undirected_graph], [directed_graph], +and the [adjacency_list] classes. + +Note that using the Bron-Kerbosch algorithm on directed graphs will doubles the +amount of time it takes to determine edge connection. +[endsect] + +[section [^bron_kerbosch_clique_number()]] + #include + + template + std::size_t bron_kerbosch_clique_number(const Graph& g) + +The `bron_kerbosch_clique_number()` function returns the size of the largest +clique in a graph - its clique number. + +[heading Parameters] +[table + [[Type] [Parameter] [Description]] + [ + [required, in] [`const Graph& g`] + [ + The graph for which cliques are being visited. + + *Preconditions:* The indices of vertices in the graph must be + in the range \[0, `num_vertices(g)`). + + *Requirements:* The `Graph` type must be a model of the [AdjacencyMatrix], + [IncidenceGraph] concept and the [VertexIndexGraph] + concepts[footnote Any `Graph` typen that implements the `edge()` + function will satisfy the expression requirements for the + [AdjacencyMatrix], but may incur additional overhead due non-constant + time complexity.]. + ] + ] +] + +[heading Return] +The `bron_kerbosch_clique_number()` function returns the size of the largest +clique in the the graph `g`. + +[heading Complexity] +The `bron_kerbosch_clique_number()` function has the same complexity as the +[bron_kerbosch_all_cliques] function. +[endsect] + +[section Examples] +[heading Printing Cliques] +This example demonstrates how to find and print all the cliques in a graph. + +[code_bron_kerbosch_print_cliques] + +If given the input file `social_network.graph`, which represents the social network +pictured in Figure 1 of the +[link boost_graph.reference.algorithms.subgraph.bron_kerbosch_all_cliques.overview Overview], +the program will produce the following output: + +[pre +Scott Jill Mary +Scott Bill +Scott Frank +Mary Laurie +Bill Josh +Josh Frank +Frank Laurie +Frank Anne Howard +] + +[heading Clique Number] +This example demonstrates the use of the [bron_kerbosch_clique_number] example. + +[code_bron_kerbosch_clique_number] + +If given the input file `social_network.graph`, which represents the social network +pictured in Figure 1 of the +[link boost_graph.reference.algorithms.subgraph.bron_kerbosch_all_cliques.overview Overview], +the program will produce the following output: + +[pre +clique number: 3 +] + +[endsect] + +[endsect] \ No newline at end of file diff --git a/quickbook/reference/closeness_centrality.qbk b/quickbook/reference/closeness_centrality.qbk new file mode 100644 index 00000000..3943a931 --- /dev/null +++ b/quickbook/reference/closeness_centrality.qbk @@ -0,0 +1,302 @@ +[/ + / Copyright (c) 2007 Andrew Sutton + / + / 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) + /] + +[section Closeness Centrality] +[template ex_closeness_centrality[] [link + boost_graph.reference.algorithms.measures.closeness_centrality.examples.closeness_centrality + Closeness Centrality Example]] +[template ex_scaled_closeness[] [link + boost_graph.reference.algorithms.measures.closeness_centrality.examples.scaled_closeness_centrality + Scaled Closeness Centrality Example]] + +[heading Overview] +The /closeness centrality/ measure is commonly used in network analysis to identify +vertices (also called actors) that are "close" to all others. To phrase differently, +actors that are closer to all others have a greater reach, making them more +influential in the network. The closeness measure is defined as the inverse of the +sum of all geodesic distances (lengths of shortest paths) from one vertex to all +others (excluding itself) in the graph. Closeness is computed as: + +[$images/eq/closeness.png] + +Where /d(u,v)/ is the shortest path (geodesic distance) from /u/ to /v/. + +Note that if any vertex in the graph is unreachable from any other, then distance +between those two unonnected vertices is infinite. This imlplies that the closeness +of that vertex is zero. If an undirected graph has unconnected components, then +all vertices will have a closeness of zero. This is not necessarily true for +unconnected directed graphs since some vertex might reach all others, but may +not itself be reachable by any others. An example of such a graph is a tree whose +direted edges from from the root toward the leaves. + +Consider the following social network represented by an undirected graph in +Figure 1. + +[figure + images/reference/social_network.png + *Figure 1.* A network of friends. +] + +Computing the closeness for each person in the graph, we find that Frank is the +most central person in the network, with a closeness centrality of approximiately +0.091 (1/11). We also find that Jill, Mary, and Laurie are the least central +people in the network (with closeness centralities of .056 or 1/18). See the +[ex_closeness_centrality] for details on computing the closeness centralites of +undirected graphs. + +The same measure can also be applied to directed graphs, but has dubious meaning +if the graph is not /strongly connected/. Consider the communication networks +between the friends listed above. For this graph, we connect two people /a/ and +/b/ if /a/ sends a text message to /b/ (for example). + +[figure + images/reference/comm_network.png + *Figure 2.* Communications between friends. +] + +In this network, Frank is once again the most central (with a closeness centrality +of 0.067) because he is "closer" to each of the various communication cycles in the +network. Laurie is the furthest removed, with a closeness centrality of .028. + +In these examples, distance is defined as the number of "hops" in the shortest path +from one vertex to another. It should be noted, however, that distance can also be +represented as the sum of edge-weights on the shortest path between the two vertices. +The definition of distance for this measure is outside the scope of this computation. +This is to say that distance is defined and computed before closeness centrality +can be computed. + +This framework also allows for a specialization of the measure through the use +of a function object. This measure defaults to the reciprocal in the equation +above, but can be easily redefined to perform alternative computations or, in +the case of non-trivial types, re-define the notion of reciprocal. + +See the [ex_scaled_closeness] for an example of how to overload the +default measures used to compute closeness centrality. + +[section [^closeness_centrality()]] + #include + + template + float closeness_centrality(const Graph& g, DistanceMap dm) + + template + ResultType closeness_centrality(const Graph& g, DistanceMap dm) + + template + typename Measure::result_type + closeness_centrality(const Graph& g, DistanceMap dm, Measure m) + +The `vertex_closeness_centrality()` function can be used to compute the closeness +centrality of a single vertex. This function requires a distance map that contains +the distance from one vertex (the source) to all others in the graph. This +distance map can be computed as the result of a "shortest paths" algorithm (e.g., +[dijkstra_shortest_paths], [bellman_ford_shortest_paths], or [dag_shortest_paths]), +or recording distances from a [breadth_first_search]. + +[heading Parameters] +[table + [[Type] [Parameter] [Description]] + [ + [template] [`ResultType`] + [ + The `ResultType` template parmeter explitly specifies the the + return type of the `closeness()` function. If not + given, the return type is `float`. + + *Requirements:* The return type is required to model the + [NumericValue] concept. + ] + ] + [ + [required, in] [`const Graph& g`] + [ + The graph for which vertex measures are being comptued. + + *Requirements:* The `Graph` type must be a model of the + [VertexListGraph] concept. + ] + ] + [ + [required, in] [`DistanceMap dm`] + [ + Given a vertex `v`, the `dm` parameter provides the length of the + shortest path between a vertex `u` and `v`. The vertex `u` is the + vertex for which the distance map was initially computed. + + *Requirements:* `DistanceMap` must be a model of [ReadablePropertyMap]. + The `key_type` of the distance map must be the same as the `vertex_descriptor` + of the `Graph` parameter. The `value_type` is required to be a model of + [NumericValue]. + ] + ] + [ + [optional, in] [`Measure measure`] + [ + The 'measure' parameter is an instance of a closeness measure that + performs the final operation (the reciprocal) for this computation. + + *Requirements:* The `Measure` type must be a model of the [DistanceMeasure] + concept. The `distance_type` must be the same type as the `value_type` + of the `DistanceMap` or `DistanceMatrixMap`. The `result_type` of the + `Measure` must model the [NumericValue] concept. + ] + ] +] + +[heading Return] +The `closeness_centrality()` function returns the closeness of a vertex. +If the source vertex is disconnected from any vertices in the graph, this value is 0. + +[heading Complexity] +The `closeness_centrality()` function returns in ['O(n*O(M))]. This is linear by +default where /n/ is the number of vertices is in the graph and /O(M)/ is the +omplexity of the measure. If no measure is given, this function returns in linear +time. +[endsect] + +[section [^all_closeness_centralities()]] + #include + + template + void all_closeness_centralities(const Graph& g, DistanceMatrixMap dm, ClosenessMap cm) + + template + void all_closeness_centralities(const Graph& g, DistanceMatrixMap dm, ClosenessMap cm, Measure m) + +This module defines a flexible framework for computing the closeness centrality +of vertices in a graph for previously computed geodesics by providing two generic +functions. The first function, `closeness_centrality()` computes the closeness of +each vertex in a graph given a matrix containing the distances between vertices. +This matrix can be computed as the output of an "all pairs shortest path" algorithm +(e.g, [floyd_warshall_all_pairs_shortest_paths] or [johnson_all_pairs_shortest_paths]) +or as the result of a [breadth_first_search] (if the graph is unweighted). + +[heading Parameters] +[table + [[Type] [Parameter] [Description]] + [ + [required, in] [`const Graph& g`] + [ + The graph for which closeness centrality values are being comptued. + + *Requirements:* The `Graph` type must be a model of the + [VertexListGraph] concept. + ] + ] + [ + [required, in] [`DistanceMatrixMap dm`] + [ + Given vertices /u/ and /v/, the `dm` parameter provides the length + of the shortest path between the two vertices. Note that the + distance between a vertex and itself should be 0 (i.e., `dm[u][u] == 0`). + + *Requirements:* `DistanceMatrixMap` must be a model of [ReadablePropertyMap]. + The `key_type` of the distance matrixc must be the same as the `vertex_descriptor` + of the `Graph` parameter. The `value_type` must be a [ReadWritePropertyMap] + whose `key_type` is also the `vertex_descriptor` of the `Graph` and + whose `value_type` is a model of [NumericValue]. + ] + ] + [ + [required, out] [`ClosenessMap cm`] + [ + The cm parameter stores the output of the computed closeness (or + distance) for each vertex in `g`. + + *Requirements:* The type of `close` must be model the [WritablePropertyMap] + concepts. The `key_type` of the property map must be the same as the + `vertex_descriptor` of the `Graph`, and the `value_type` must be a model + of [NumericValue]. + ] + ] + [ + [optional, in] [`Measure measure`] + [ + The 'measure' parameter is an instance of a closeness measure that + performs the final operation (the reciprocal) for this computation. + + *Requirements:* The `Measure` type must be a model of the [DistanceMeasure] + concept. The `distance_type` must be the same type as the `value_type` + of the `DistanceMap` or `DistanceMatrixMap`. The `result_type` of the + `Measure` must model the [NumericValue] concept. + ] + ] +] + +[heading Complexity] +The `all_closenesss_centralities()` function returns in ['O(n[super 2]*O(M))] where /n/ +is the number of vertices in the graph and /O(M)/ is the complexity of the distance +measure. If no distance measure is given, this functions returns in ['O(n[super 2])] +time. +[endsect] + +[section Examples] +[heading Closeness Centrality] +This example computes the closeness centrality for all vertices (people) a social +network such as the one pictured in Figure 1. The program also sorts the vertices by +their corresponding closeness in descending order. This example includes the +following files: + +* [^examples/closeness_centrality.hpp] +* [^examples/helper.hpp] + +[closeness_centrality_example] + +If this program is given the `social_network.graph` file as input, the output +will be: + +[pre +Scott 0.0833333 +Jill 0.0588235 +Mary 0.0625 +Bill 0.0588235 +Josh 0.0625 +Frank 0.0909091 +Laurie 0.0666667 +Anne 0.0588235 +Howard 0.0588235 +] + +Note that this program can be easily modified to work on directed graphs. In the +file `social_network.hpp`, simply replace `typedef undirected_graph ...` to +`typedef directed_graph ...`. + +[heading Scaled Closeness Centrality] +In some literature, closeness is defined as the number of vertices divided by the +sum of distances, or more formally. + +[$images/eq/scaled_closeness.png] + +Where /n/ is the number of vertices in the graph. While this example demonstrates +the implementation of a [DistanceMeasure], the resulting value can be also +obtained by multiplying the default result by the number of vertices in the graph. +This example uses the following files: + +* [^examples/scaled_closeness_centrality.hpp] +* [^examples/helper.hpp] + +[scaled_closeness_centrality_example] + +If given the same social network as input, the output of this program will be: + +[pre +Scott 0.75 +Jill 0.529412 +Mary 0.5625 +Bill 0.529412 +Josh 0.5625 +Frank 0.818182 +Laurie 0.6 +Anne 0.529412 +Howard 0.529412 +] + +It is relatively easy to verify that each of these values is nine times the values +given in the previous example. +[endsect] + +[endsect] diff --git a/quickbook/reference/clustering_coefficient.qbk b/quickbook/reference/clustering_coefficient.qbk new file mode 100644 index 00000000..5d5c9623 --- /dev/null +++ b/quickbook/reference/clustering_coefficient.qbk @@ -0,0 +1,199 @@ +[/ + / Copyright (c) 2007 Andrew Sutton + / + / 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) + /] + +[section Clustering Coefficient] +[template ex_clustering_coefficient[] [link + boost_graph.reference.algorithms.measures.closeness_centrality.examples.closeness_centrality + Closeness Centrality Example]] + +[heading Overview] +The /clustering coefficient/ is a measure used in network analysis to describe a +connective property of vertices. The clustering coefficient of a vertex gives the +probability that two neighbors of that vertex are, themselves, connected. In social +networks, this is often interpreted as the probability that a persons friends are +also friends. + +This measure is derived from two different properties of a vertex /v/. The first is the +number of possible paths through that vertex. The number of paths through a vertex +can be counted as the number of possible ways to connect the neighbors (adjacent +vertices) of /v/. This number differs for directed and undirected graphs. For directed +graphs it is given as: + +[$images/eq/num_paths_directed.png] + +Where /d(v)/ is the out-degree of the vertex /v/. For undirected graphs: + +[$images/eq/num_paths_undirected.png] + +Note that for undirected graphs the out-degree of /v/ is the same as the degree +of /v/. + +The second property is the number of triangles centered on the vertex /v/. Triangles +are counted as each pair of neighbors (adjacent vertices) /p/ and /q/ that are +connected (i.e., and edge exists between /p/ and /q/). Note that if /p/ and /q/ +are connected, they form a distinct triangle /{v, p, q}/. For directed graphs, the +edges /(p, q)/ and /(q, p)/ can form two distinct triangles. The number of triangles +centered on a vertex is given as: + +[$images/eq/num_triangles.png] + +Where ['e[sub pq]] is an edge connecting vertices /p/ and /q/ in the edge set of +the graph. The clustering coefficient of the vertex is then computed as: + +[$images/eq/clustering_coef.png] + +Note that the clustering coefficient of a vertex /v/ is 0 if none of its neighbors +are connected to each other. Its clustering coefficient is 1 if all of its neighbors +are connected to each other. + +The /mean clustering coefficient/ can be computed for the entire graph as quantification +of the /small-world property/. A graph is a small world property if its clustering +coefficient is significantly higher than a random graph over the same vertex set. + +Consider the following social network represented by an undirected graph in +Figure 1. + +[figure + images/reference/social_network.png + *Figure 1.* A network of friends. +] + +Computing the clustering coefficient for each person in this network shows that +Frank has a clustering coefficient of 0.1. This implies that while Frank has many +friends, his friends are not necessarily friendly with each other. On the other +hand Jill, Anne, and Howard each have a value of 1.0, meaning that they enjoy +participation in a social clique. + +The mean clustering coefficient of this graph is 0.4. Unfortunately, since the +graph is so small, one cannot determine whether or not this network does exhibit +the small-world property. + +[section [^clustering_coefficient()]] + #include + + template + float clustering_coefficient(const Graph& g, Vertex v) + + template + ResultType clustering_coefficient(const Graph& g, Vertex v) + +The `clustering_coefficient()` function returns the clustering coefficient of +the given vertex. The second variant allows the caller to explicitly specify +the type of the clustering coefficient. + +[heading Parameters] +[table + [[Type] [Parameter] [Description]] + [ + [template] [`ResultType`] + [ + The `ResultType` template parmeter explitly specifies the the + return type of the function. If not given, the return type is `float`. + + *Requirements:* The return type is required to model the [NumericValue] + concept. + ] + ] + [ + [required, in] [`const Graph& g`] + [ + The graph for which vertex measures are being comptued. + + *Requirements:* The `Graph` type must be a model of the [IncidenceGraph], + [AdjacencyGraph] and [AdjacencyMatrix] concepts[footnote Any `Graph` type + that implements the `edge()` function will satisfy the expression requirements + for the [AdjacencyMatrix], but may incur additional overhead due non-constant + time complexity.]. + ] + ] +] + +[heading Return] +The `clustering_coefficient()` function returns the clustering coefficient of the +vertex. The return type is either `float` or the type specified by the user. + +[heading Complexity] +The `clustering_coefficient()` function returns in ['O(d(v)[super 2]] where +/d(v)/ is the degree of /v/. +[endsect] + +[section [^all_clustering_cofficients()]] + #include + + template + typename property_traits::value_type + all_clustering_coefficients(const Graph& g, ClusteringMap cm) + +Compute the clustering coefficients for each vertex and return the mean clustering +coefficient to the caller. + +[heading Parameters] +[table + [[Type] [Parameter] [Description]] + [ + [required, in] [`const Graph& g`] + [ + The graph for which vertex measures are being comptued. + + *Requirements:* The `Graph` type must be a model of the [VertexListGraph], + [IncidenceGraph], [AdjacencyGraph] and [AdjacencyMatrix] concepts[footnote Any + `Graph` type that implements the `edge()` function will satisfy the expression + requirements for the [AdjacencyMatrix], but may incur additional overhead due + non-constant time complexity.]. + ] + ] + [ + [required, in] [`ClusteringMap cm`] + [ + The clustering map `cm` stores the clustering coefficient of each + vertex in the graph `g`. + + *Requirements:* The `ClusteringMap` type must modelt the [WritablePropertyMap] + concept. + ] + ] +] + +[heading Complexity] +The `all_clustering_coefficients()` function returns in ['O(nd[super 2])] where +/d/ is the mean (average) degree of vertices in the graph. +[endsect] + +[section [^num_paths_through_vertex()]] +[endsect] + +[section [^num_triangles_on_vertex()]] +[endsect] + +[section Examples] +[heading Clustering Coefficient] +This example computes both the clustering coefficient for each vertex in a graph and +the mean clustering coefficient for the graph, printing them to standard output. + +[code_clustering_coefficient] + +If this program is given the `social_network.graph` file as input which represents +the graph shown in the +[link boost_graph.reference.algorithms.measures.clustering_coefficient.overview Overview], +the output will be: + +[pre +Scott 0.166667 +Jill 1 +Mary 0.333333 +Bill 0 +Josh 0 +Frank 0.1 +Laurie 0 +Anne 1 +Howard 1 +mean clustering coefficient: 0.4 +] + +[endsect] + +[endsect] diff --git a/quickbook/reference/connected_components.qbk b/quickbook/reference/connected_components.qbk new file mode 100644 index 00000000..30ec9410 --- /dev/null +++ b/quickbook/reference/connected_components.qbk @@ -0,0 +1,94 @@ +[/ + / Copyright (c) 2007 Andrew Sutton + / + / 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) + /] + +[section Connected Components] + template + typename property_traits::value_type + connected_components(const Graph &g, ComponentMap c, + const bgl_named_params& params = ``/defaults/``); + + +The connected_components() functions compute the connected components of an undirected +graph using a DFS-based approach. A connected component of an undirected graph is a +set of vertices that are all reachable from each other. If the connected components +need to be maintained while a graph is growing the disjoint-set based approach of +function `incremental_components()` is faster. For "static" graphs this DFS-based +approach is faster \[8\]. + +The output of the algorithm is recorded in the component property map, which will +contain numbers giving the component number assigned to each vertex. This algorithm +returns the total number of connected components in the graph. + +[heading Where Defined] +`boost/graph/connected_components.hpp` + +[heading Parameters] +[table + [[Type] [Parameter] [Description]] + [ + [in] [`const Graph& g`] + [ + The /undirected/ graph for which connected components are being found. + This graph must be a model of VertexListGraph and Incidence Graph. + ] + ] + [ + [out] [`ComponentMap c`] + [ + The algorithm computes how many connected components are in the graph, + and assigning each component an integer label. The algorithm then records + which component each vertex in the graph belongs to by recording the + component number in the component property map. The ComponentMap type + must be a model of WritablePropertyMap. The value type shouch be an + integer type, preferably the same as the `vertices_size_type` of the + graph. The key type must be the graph's `vertex_descriptor` type. + ] + ] +] + +[heading Named Parameters] +[table + [[Type] [Parameter] [Description]] + [ + [util] [`color_map(ColorMap color)`] + [ + This is used by the algorithm to keep track of its progress through the + graph. The type ColorMap must be a model of ReadWritePropertyMap and + its key type must be the graph's `vertex_descriptor` type and the value + type of the color map must model ColorValue. + + *Default* An `iterator_property_map` create from a `std::vector` of + `default_color_type` of size `num_vertices(g)` and using `index_map` as + the index map (to access colors for a vertex). + ] + ] + [ + [in] [`vertex_index_map(VertexIndexMap index_map)`] + [ + This maps each vertex to an integer in the range \[0, `num_vertices(g)`). + This parameter is only necessary when the default color property map is + used. The type VertexIndexMap must be a model of ReadablePropertyMap. The + value type of the map must be an integer type. The vertex descriptor type + of the graph needs to be usable as the key type of the map. + + *Default* `get(vertex_index, g)`. Note if you use this default, make sure + that your graph has an interior `vertex_index` property. For example + `adjacency_list` with `VertexList=listS` does not have an interior + `vertex_index` property. + ] + ] +] + +[heading Complexity] +This algorithm runs in /O(V + E)/. + +[heading Notes] +This algorithm will not compile if passed a /directed/ graph. + +[heading Examples] + +[endsect] \ No newline at end of file diff --git a/quickbook/reference/degree_centrality.qbk b/quickbook/reference/degree_centrality.qbk new file mode 100644 index 00000000..4595e90b --- /dev/null +++ b/quickbook/reference/degree_centrality.qbk @@ -0,0 +1,440 @@ +[/ + / Copyright (c) 2007 Andrew Sutton + / + / 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) + /] + +[section Degree Centrality] +[template ex_degree_centrality[] [link + boost_graph.reference.algorithms.measures.degree_centrality.examples.degree_centrality + Degree Centrality Example]] +[template ex_influence_prestige[] [link + boost_graph.reference.algorithms.measures.degree_centrality.examples.influence_and_prestige + Influence and Prestige Example]] +[template degree_centrality_measures[] [link + boost_graph.reference.algorithms.measures.degree_centrality.measures + Measures Section]] + +[heading Overview] +The /degree centrality/ measure is used in social network analysis to help +determine which vertices (or more specifically actors) are the most central +or important to a network. Degree centrality of a vertex is computed over the number +of connections (adjacent vertices) of that vertex. This definition varies for +undirected and directed graphs. For undirected graphs, the degree centrality of a +vertex is equivalent to its degree. For directed graphs it is equivalent to either +its in- or out-degree. + +Consider the social network represented by an undirected graph in Figure 1. + +[figure + images/reference/social_network.png + *Figure 1.* A network of friends. +] + +This graph depicts a set of friends and their relationships (friendship, dating, etc.) +The degree centrality of each person in this graph is their number of friends. +Here, Frank has the highest degree centrality with five friends, whereas Laurie, +Jill, Bill, Anne, and Howard are the least central with two friends apiece. See +the [ex_degree_centrality] for details on computing the degree centrality of +undirected graphs. + +For directed graphs, there are related two interpretations of degree centrality. +When degree centrality is measured over the out-degree of a vertex, it is called +/influence/. When the in-degree is measured, the measure is called /prestige/. +See the [degree_centrality_measures] for information types and functions related +to the computation of influence and prestige. + +Consider the information network represented by the directed graph in Figure 2. + +[figure + images/reference/info_network.png + *Figure 2.* A network of informational websites. +] + +This graph represents links between information websites, presumably regarding a +specific topic. The most influential (out-degree centrality) is blogger with +three outgoing links while wikipedia is the least influential. The most prestigous +(in-degree centrality) is wikipedia with five incoming references. The least +prestigous websites are myspace, blogger, and blogspot each of which have no +incoming links. See the [ex_influence_prestige] for details on computing the +influence and prestige of directed graphs. + +[section [^degree_centrality()]] + #include + + template + typename graph_traits::degree_size_type + degree_centrality(const Graph& g, Vertex v); + + template + typename Measure::degree_type + degree_centrality(const Graph& g, Vertex v, Measure measure); + +The `degree_centrality()` function computes this measure for a single vertex, +returning the value to the caller. Optionally, a degree measure can be given, +specializing the computation of degree centrality. See the [degree_centrality_measures] +section for more details on the influence and prestige measures. + +[heading Parameters] +[table + [[Type] [Parameter] [Description]] + [ + [required, in] [`const Graph& graph`] + [ + The graph object for which the degree centralities will be computed. + + *Requirements:* The `Graph` type must be a model of the [IncidenceGraph] + concept. If the `Measure` parameter is given as `prestige_measure`, + then the graph must be a model of the [BidirectionalGraph] concept. + ] + ] + [ + [required, in] [`Vertex v`] + [ + The vertex descriptor for which the degree centrality is computed. + + *Requirements:* The `Vertex` type must be the same as the `vertex_descriptor` + of the `Graph` parameter. + ] + ] + [ + [optional, in] [`Measure measure`] + [ + The `measure` parameter allows the caller to override the default + computation of degree centrality for a vertex. + + *Requirements:* The `Measure` type must be a model of the + [DegreeMeasure] concept. The `degree_type` of `Measure` must + be the same as the `value_type` of the `CentralityMap` type. + ] + ] +] + +[heading Return Value] +The `degree_centrality()` function returns the centrality of a vertex. +If no `measure` parameter is given, the return type is the same as the +`degree_size_type` of the `Graph`. Otherwise, it is the `degree_type` of +the `Measure`. + +[heading Complexity] +The `degree_centrality()` returns in /O(M)/. If the measure is not given, +or the measure is given as `influence_measure` or `prestige_measure`, this function +returns in constant time. +[endsect] + +[section [^influence()]] + template + typename graph_traits::degree_size_type + influence(const Graph& g, Vertex v); + +The `influence()` function the influence of the vertex to the caller. The influence +of a vertex is the same as its out-degree. + +[heading Parameters] +[table + [[Type] [Parameter] [Description]] + [ + [required, in] [`const Graph& graph`] + [ + The graph object for which the degree centralities will be computed. + + *Requirements:* The `Graph` type must be a model of the [IncidenceGraph] + concept. If the `Measure` parameter is given as `prestige_measure`, + then the graph must be a model of the [BidirectionalGraph] concept. + ] + ] + [ + [required, in] [`Vertex v`] + [ + The vertex descriptor for which the degree centrality is computed. + + *Requirements:* The `Vertex` type must be the same as the `vertex_descriptor` + of the `Graph` parameter. + ] + ] +] + +[heading Return Value] +The `influence()` function returns the influence of the vertex, which is the same +as its out-degree. + +[heading Complexity] +The `influence()` function returns in constant time. +[endsect] + +[section [^prestige()]] + template + typename graph_traits::degree_size_type + prestige(const Graph& g, Vertex v); + +The `prestige()` function the prestige of the vertex to the caller. The prestige +of a vertex is the same as its in-degree. + +[heading Parameters] +[table + [[Type] [Parameter] [Description]] + [ + [required, in] [`const Graph& graph`] + [ + The graph object for which the degree centralities will be computed. + + *Requirements:* The `Graph` type must be a model of the [IncidenceGraph] + concept. If the `Measure` parameter is given as `prestige_measure`, + then the graph must be a model of the [BidirectionalGraph] concept. + ] + ] + [ + [required, in] [`Vertex v`] + [ + The vertex descriptor for which the degree centrality is computed. + + *Requirements:* The `Vertex` type must be the same as the `vertex_descriptor` + of the `Graph` parameter. + ] + ] +] + +[heading Return Value] +The `prestige()` function returns the influence of the vertex, which is the same +as its out-degree. + +[heading Complexity] +The `prestige()` returns in constant time. +[endsect] + +[section [^all_degree_centralities()]] + #include + + template + void all_degree_centralities(const Graph& g, CentralityMap cent); + + template + void all_degree_centralities(const Graph& g, CentralityMap cent, Measure measure); + +The `all_degree_centralities()` computes the degree centrality for each vertex in the +graph, assigning the values to an output property map. Optionally, a degree measure +can be given, specializing the computation of degree centrality. See the +[degree_centrality_measures] section for more details on the influence and +prestige measures. + +[heading Parameters] +[table + [[Type] [Parameter] [Description]] + [ + [required, in] [`const Graph& graph`] + [ + The graph object for which the degree centralities will be computed. + + *Requirements:* The `Graph` type must model the [VertexListGraph] + and [IncidenceGraph] concepts. If the `Measure` parameter is given + as `prestige_measure`, then the graph must be a model of the + [BidirectionalGraph] concept. + ] + ] + [ + [required, out] [`CentralityMap cent`] + [ + The property map that contains the degree centralities of all vertices + in a graph after calling the `degree_centrality()` function. + + *Requirements:* The `CentralityMap` type must be a model of the + [WritablePropertyMap] concept. The `key_type` of the map must + be the same as the `vertex_descriptor` of the `Graph` type. If the + `Measure` parameter is given in the call, then the `value_type` + of `CentralityMap` must be the same as `Measure::degree_type`. + Otherwise, the `value_type` must be the same as the `degree_size_type` + of the graph. + ] + ] + [ + [optional, in] [`Measure measure`] + [ + The `measure` parameter allows the caller to override the default + computation of degree centrality for a vertex. + + *Requirements:* The `Measure` type must be a model of the + [DegreeMeasure] concept. The `degree_type` of `Measure` must + be the same as the `value_type` of the `CentralityMap` type. + ] + ] +] + +[heading Complexity] +The `all_degree_centralities()` function returns in /O(n*O(M))/ where /n/ is the +number of vertices in the graph and /M/ is a measure of a vertex. If the measure +is not specified or is `influence_measure` or `prestige_measure`, this function +returns in linear time. +[endsect] + +[section [^all_influence_values()]] + #include + + template + void all_influence_values(const Graph& g, CentralityMap cent); + + +The `all_influence_values()` function computes the influence of each vertex in the +graph, assigning the values to an output property map. + +[heading Parameters] +[table + [[Type] [Parameter] [Description]] + [ + [required, in] [`const Graph& graph`] + [ + The graph object for which the degree centralities will be computed. + + *Requirements:* The `Graph` type must model the [VertexListGraph] + and [IncidenceGraph] concepts. If the `Measure` parameter is given + as `prestige_measure`, then the graph must be a model of the + [BidirectionalGraph] concept. + ] + ] + [ + [required, out] [`CentralityMap cent`] + [ + The property map that contains the degree centralities of all vertices + in a graph after calling the `degree_centrality()` function. + + *Requirements:* The `CentralityMap` type must be a model of the + [WritablePropertyMap] concept. The `key_type` of the map must + be the same as the `vertex_descriptor` of the `Graph` type. If the + `Measure` parameter is given in the call, then the `value_type` + of `CentralityMap` must be the same as `Measure::degree_type`. + Otherwise, the `value_type` must be the same as the `degree_size_type` + of the graph. + ] + ] +] + +[heading Complexity] +The `all_influence_values()` function returns linear time with respect to the +number of vertices in the graph. +[endsect] + +[section [^all_prestige_values()]] + #include + + template + void all_prestige_values(const Graph& g, CentralityMap cent); + + +The `all_prestige_values()` function computes the prestige of each vertex in the +graph, assigning the values to an output property map. + +[heading Parameters] +[table + [[Type] [Parameter] [Description]] + [ + [required, in] [`const Graph& graph`] + [ + The graph object for which the degree centralities will be computed. + + *Requirements:* The `Graph` type must model the [VertexListGraph] + and [IncidenceGraph] concepts. If the `Measure` parameter is given + as `prestige_measure`, then the graph must be a model of the + [BidirectionalGraph] concept. + ] + ] + [ + [required, out] [`CentralityMap cent`] + [ + The property map that contains the degree centralities of all vertices + in a graph after calling the `degree_centrality()` function. + + *Requirements:* The `CentralityMap` type must be a model of the + [WritablePropertyMap] concept. The `key_type` of the map must + be the same as the `vertex_descriptor` of the `Graph` type. If the + `Measure` parameter is given in the call, then the `value_type` + of `CentralityMap` must be the same as `Measure::degree_type`. + Otherwise, the `value_type` must be the same as the `degree_size_type` + of the graph. + ] + ] +] + +[heading Complexity] +The `all_prestige_values()` function returns linear time with respect to the +number of vertices in the graph. +[endsect] + +[section Measures] + template struct influence_measure; + template struct prestige_measure; + + template + influence_measure measure_influence(const Graph&); + + template + prestige_measure measure_prestige(const Graph&); + +These functions in this module can be specialized throught the use of different +/measure/ functors. These funtors are called to compute the degree centraltiy of a +vertex within the computational framework. This module provides the two default +measures for /influence/ and /prestige/ and functions to help instantiate them. +Custom measures can also be used. + +The `influence_measure` returns the out-degree of a vertex. Using this measure +requires the `Graph` to model the [IncidenceGraph] concept. + +The `prestige_measure` returns the in-degree of a vertex. Using this measure +requires the `Graph` to model the [BidirectionalGraph] concept. + +The `measure_influence()` and `measure_prestige()` functions can be used to +create the corresponding measure objects. +[endsect] + +[section Examples] +[heading Degree Centrality] +This example reads a graph from standard input (in a simple edge-list format), +computes the degree-centrality of each vertex, and prints them to standard +output. This example includes of the following files: + +* [^examples/degreee_centrality.hpp] +* [^examples/helper.hpp] + +[degree_centrality_example] + +If given the `social_network.graph` file as input, the program will produce the +following output: + +[pre +Scott: 4 +Jill: 2 +Mary: 2 +Bill: 2 +Josh: 2 +Frank: 5 +Laurie: 1 +Anne: 2 +Howard: 2 +] + +[heading Influence and Prestige] +This example is nearly identical to the previous in that it computes the degree +centrality over vertices in a graph. However, this example constructs a directed +graph and computes both influence and prestige. This example consist of the following +files: + +* [^examples/influence_prestige.hpp] +* [^examples/helper.hpp] + +[influence_prestige_example] + +If given the `info_network.graph` file as input, the program will produce +the following output where the second column is influence and the third is prestige: + +[pre +myspace 1 0 +digg 2 2 +blogger 3 0 +slahsdot 0 1 +wikipedia 0 5 +slashdot 2 2 +blogspot 2 0 +bbc 1 1 +] +[endsect] + +[endsect] \ No newline at end of file diff --git a/quickbook/reference/depth_first_search.qbk b/quickbook/reference/depth_first_search.qbk new file mode 100644 index 00000000..39b3a022 --- /dev/null +++ b/quickbook/reference/depth_first_search.qbk @@ -0,0 +1,161 @@ +[/ + / Copyright (c) 2007 Andrew Sutton + / + / 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) + /] + +[section Depth-First Search] + template + void + depth_first_search(Graph& g, + bgl_named_params& params = ``/defaults/``) + + template + void + depth_first_search(Graph& g, + Visitor vis, + ColorMap color, + typename graph_traits::vertex_descriptor s) + +The `depth_first_search()` function performs a depth-first traversal of the vertices +in a directed graph. When possible, a depth-first traversal chooses a vertex adjacent +to the current vertex to visit next. If all adjacent vertices have already been +discovered, or there are no adjacent vertices, then the algorithm backtracks to the +last vertex that had undiscovered neighbors. Once all reachable vertices have been +visited, the algorithm selects from any remaining undiscovered vertices and continues +the traversal. The algorithm finishes when all vertices have been visited. Depth-first +search is useful for categorizing edges in a graph, and for imposing an ordering on the +vertices. Section /Depth-First Search/ describes the various properties of DFS and +walks through an example. + +Similar to BFS, color markers are used to keep track of which vertices have been +discovered. White marks vertices that have yet to be discovered, gray marks a +vertex that is discovered but still has vertices adjacent to it that are undiscovered. +A black vertex is discovered vertex that is not adjacent to any white vertices. + +The `depth_first_search()` function invokes user-defined actions at certain event-points +within the algorithm. This provides a mechanism for adapting the generic DFS algorithm +to the many situations in which it can be used. In the pseudo-code below, the event +points for DFS are indicated in by the triangles and 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 [DFSVisitor]. In the pseudo-code we show the algorithm +computing predecessors /p/, discovery time /d/ and finish time /t/. By default, the +`depth_first_search()` function does not compute these properties, however there are +pre-defined visitors such as [predecessor_recorder] and [time_stamper] that +can be used to do this. + +[pre +DFS(G) + for each vertex u in V initialize vertex u + color\[u\] := WHITE + p\[u\] = u + end for + + time := 0 + if there is a starting vertex s + call DFS-VISIT(G, s) start vertex /s/ + + for each vertex u in V + if color\[u\] = WHITE start vertex /u/ + call DFS-VISIT(G, u) + end for + + return (p,d_time,f_time) + +DFS-VISIT(G, u) + color\[u\] := GRAY discover vertex /u/ + d_time\[u\] := time := time + 1 + + for each v in Adj\[u\] examine edge /(u,v)/ + if (color\[v\] = WHITE) /(u,v)/ is a tree edge + p\[v\] = u + call DFS-VISIT(G, v) + else if (color\[v\] = GRAY) /(u,v)/ is a back edge + ... + else if (color\[v\] = BLACK) /(u,v)/ is a cross or forward edge + ... + end for + + color\[u\] := BLACK finish vertex /u/ + f_time\[u\] := time := time + 1 +] + +[heading Where Defined] +`boost/graph/depth_first_search.hpp` + +[heading Parameters] +[table + [[Type] [Parameter] [Description]] + [ + [in] [`Graph& g`] + [ + A directed or undirected graph. The graph type must be a model of [VertexListGraph] + and [IncidenceGraph]. + ] + ] + [ + [in] [`vertex_descriptor s`] + [ + This specifies the vertex that the depth-first search should originate from. Note + that this can also be given as a named parameter. + ] + ] +] + +[heading Named Parameters] +[table + [[Type] [Parameter] [Description]] + [ + [in] [`visitor(Visitor vis)`] + [ + A visitor object that is inovked inside the algorithm at event points specified by the + [DFSVisitor]. The `vis` object must be model the [DFSVisitor] concept. + + *Default* `bfs_visitor`. + ] + ] + [ + [in] [`root_vertex(vertex_descriptor s)`] + [ + This specifies the vertex that the depth-first search should originate from. + + *Default* `*vertices(g).first` + ] + ] + [ + [in] [`vertex_index_map(VeretxIndexMap index_map)`] + [ + This maps each vertex to an integer in the range \[0, `num_vertices(g)`). + This parameter is only necessary when the default color property map is + used. The type VertexIndexMap must be a model of ReadablePropertyMap. The + value type of the map must be an integer type. The vertex descriptor type + of the graph needs to be usable as the key type of the map. + + *Default* `get(vertex_index, g)`. Note if you use this default, make sure + that your graph has an interior `vertex_index` property. For example + `adjacency_list` with `VertexList=listS` does not have an interior + `vertex_index` property. + ] + ] + [ + [util] [`color_map(ColorMap color)`] + [ + This is used by the algorithm to keep track of its progress through the + graph. The type ColorMap must be a model of ReadWritePropertyMap and + its key type must be the graph's `vertex_descriptor` type and the value + type of the color map must model ColorValue. + + *Default* An `iterator_property_map` create from a `std::vector` of + `default_color_type` of size `num_vertices(g)` and using `index_map` as + the index map (to access colors for a vertex). + ] + ] +] + +[heading Complexity] +The time complexity is /O(E + V)/. + +[heading Example] + +[endsect] \ No newline at end of file diff --git a/quickbook/reference/directed_graph.qbk b/quickbook/reference/directed_graph.qbk new file mode 100644 index 00000000..14597e97 --- /dev/null +++ b/quickbook/reference/directed_graph.qbk @@ -0,0 +1,779 @@ +[/ + / Copyright (c) 2007 Andrew Sutton + / + / 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) + /] + +[section Directed Graph] +This section provides detailed information about the `directed_graph` class, +its associated types, member functions and non-member interface. A directed +graph is one in which edges have distinct direction. Edges flow from a /source/ +vertex to a /target/ and are generally only traversed through the outgoing +edges of a vertex. However, incoming edges are also accessible. The class +provides a general purpose implementation of directed graphs and can be +used with algorithms in the Boost Graph Library. + +[h4 Notation] +The following notation is used in this documentation. The following type names +are generally meant to mean the following: +[table + [[Used Type] [Actual Type]] + [ + [`directed_graph`] + [ + `directed_graph` where `VP`, `EP` and `GP` are template + arguments that correspond to user-defined or default verex properties, + edge properties, and graph properties. + ] + ] + [ + [`vertex_descriptor`] + [`directed_graph::vertex_descriptor`] + ] + [ + [`edge_descriptor`] + [`directed_graph::edge_descriptor`] + ] + [ + [`vertex_iterator`] + [`directed_graph::vertex_iterator`] + ] + [ + [`edge_iterator`] + [`directed_graph::edge_iterator`] + ] +] + +Moreover, objects with the following names are generally expected to have the +following types. + +[table + [[Object Name] [Type]] + [[`g`] [`directed_graph`]] + [[`u`, `v`] [`vertex_descriptor`]] + [[`e`] [`edge_descriptor`]] + [[`i`] [`vertex_iterator` or `edge_iterator`]] + [[`p`] [A property tag (usually a template parameter)]] + [[`d`] [A vertex or edge descriptor (usually a template parameter)]] + [[`v`] [The value of a property (usually a template parameter)]] +] + +[h4 Descriptor and Iterator Stability] +With the `directed_graph` class, descriptors and iterators remain stable after +all operations except descriptors and iterators to those edges or vertices being +removed. Removing a vertex or edge will not invalidate descriptors or iterators +referencing other vertices or edges. + +For example, consider the following code: + + directed_graph<> g; + directed_graph<>::vertex_descriptor u = add_vertex(g); + directed_graph<>::vertex_descriptor v = add_vertex(g); + directed_graph<>::vertex_descriptor w = add_vertex(g); + remove_vertex(u); + add_edge(v, w, g); + +After running this program, the descriptor `u` will be invalid but `v` and `w` will +still be valid so the call to `add_edge(v,w,g)` is also valid. Note that this +property does not hold for all graph types. + +[h4 Vertex Indexing and Stability] +The `directed_graph` class provides a built-in internal properties for vertex +types, and will provide some degree of automated index management. Algorithms +that use vertex indices generally assume that they are in the range +\[0, `num_vertices(g)`). With the `directed_graph` class vertex indices will +be in this continuous range until a vertex is removed from the graph. This is +the only operation that invalidates vertex indices, but the vertices will need +to be renumbered using the `renumber_vertex_indices()` function. + +The `remove_vertex_and_renumber_indices(vi,g)` function can be used to autmoatically +renumber indices after removing the vertex referenced by the given iterator. Because +this function runs in linear time, it should not be used for repeated removals. + +[h4 Template Parameters] +There are three parameters to the `directed_graph` class. +[table + [[Parameter] [Description] [Default]] + [ + [`VertexProperties`] + [Specifies internal properties for vertices of the graph.] + [`no_property`] + ] + [ + [`EdgeProperties`] + [Specifies internal properties for edges of the graph.] + [`no_property`] + ] + [ + [`GraphProperties`] + [Specifies internal properties for the graph itself.] + [`no_property`] + ] +] + +[h5 Model Of] +[IncidenceGraph], [VertexListGraph], [EdgeListGraph], [AdjacencyGraph], +[MutableGraph], and [PropertyGraph]. + +[h5 Where Defined] +`boost/graph/directed_graph.hpp` + +[h4 Associated Types] +There are a number of useful types associated with the `directed_graph` class. +Most of these are accessed through [graph_traits] or other template classes. +For convenience these types have been grouped by purpose. + +[h5 Descriptor Types] +[table + [[Type] [Description]] + [ + [`graph_traits::vertex_descriptor`] + [ + The type for the vertex descriptors associated with the graph. The `vertex_descriptor` + models the [Descriptor] and [NoConcept Hashable] concepts. + ] + ] + [ + [`graph_traits::edge_descriptor`] + [ + The type for the edge descriptors associated with the graph. The `edge_descriptor` + models the [Descriptor] and [NoConcept Hashable] concepts. + ] + ] +] + +Note that edge and vertex descriptors for the `unsigned_graph` can be used as keys for both +[SgiSortedAssociativeContainer]s and [SgiHashedAssociativeContainer]s such as `std::map` and +`std::tr1::unordered_map` respectively. + +[h5 Iterator Types] +[table + [[Type] [Description]] + [ + [`graph_traits::vertex_iterator`] + [ + The type for iterators returned by `vertices()`. Verex iterators are + models of the [SgiBidirectionalIterator] concept. + ] + ] + [ + [`graph_traits::edge_iterator`] + [ + The type for iterators returned by `edges()`. Edge iterators are + models of the [SgiBidirectionalIterator] concept. + ] + ] + [ + [`graph_traits::out_edge_iterator`] + [ + The type for iterators returned by `out_edges()`. Out-edge iterators + are models of the [SgiBidirectionalIterator] concept. + ] + ] + [ + [`graph_traits::in_edge_iterator`] + [ + The type for iterators returned by `in_edges()`. In-edge iterators + are models of the [SgiBidirectionalIterator] concept. + ] + ] + [ + [`graph_traits::adjacency_iterator`] + [ + The type for iterators returned by `adjacent_vertices`. Adjacency + iterators are models of the [SgiBidirectionalIterator] concept. + ] + ] +] + +[h5 Miscellaneous Types] +[table + [[Type] [Description]] + [ + [`graph_traits::vertices_size_type`] + [The type used for dealing with the number of vertices in the graph.] + ] + [ + [`graph_traits::edge_size_type`] + [The type used for dealing with the number of edges in the graph.] + ] + [ + [`graph_traits::degree_size_type`] + [The type used for dealing with the number of edges incident to a vertex in the graph.] + ] + [ + [`directed_graph::vertex_index_type`] + [The integral type representing vertex indices (generally `unsigned int`).] + ] + [ + [ + `property_map::type` + + `property_map::const_type` + ] + [ + The property map type for vertex or edge properties in the graph. The specific + property is specified by the `Property` template argument, and must match one of + the properties specified in the `VertexProperties` or `EdgeProperties` for the + graph. + ] + ] + [ + [`graph_property::type`] + [ + The value type for the graph property specified by the `Property` parameter. + `Property` must be one of the types in the `GraphProperties` template argument. + ] + ] + [ + [`graph_traits::directed_category`] + [ + This is always `bidirectional_tag`, indicating that the graph supports in- and + out-edge operations. + ] + ] + [ + [`graph_traits::edge_parallel_category`] + [ + This is always `allow_parallel_edges_tag`, indicating that multiple edges + may be added between two vertices (i.e., graphs can be /multigraphs/). + ] + ] +] + +[h4 Member Functions] +[table + [[Function] [Description]] + [ + [ +`` +directed_graph(const GraphProperties& p = GraphProperties()) +`` + ] + [The default constructor creates a graph with no vertices or edges.] + ] + [ + [ +``directed_graph(const directed_graph& g) +`` + ] + [The copy constructor creates a copy of the given graph `g`.] + ] + [ + [ +`` +directed_graph(vertices_size_type n, + const GraphProperties& p = GraphProperties()) +`` + ] + [The default constructor creates a graph with `n` vertices and no edges.] + ] + [ + [ +``directed_graph& operator =(const directed_graph& g) +`` + ] + [Copies the edges and vertices of the graph `g`.] + ] +] + +[h4 Non-member Functions] +[h5 Non-member Accessors] +[table + [[Function] [Description]] + [ + [ +`` +std::pair +vertices(const directed_graph& g) +`` + ] + [Returns an iterator range providing access to the vertex list of `g`.] + ] + [ + [ +`` +std::pair +edges(const directed_graph& g) +`` + ] + [Returns an iterator range providing access to the edge list of `g`.] + ] + [ + [ +`` +std::pair +out_edges(vertex_descriptor v, + const directed_graph& g) +`` + ] + [ + Returns an iterator range providing access to the out-edges of + vertex `v` in the graph `g`. + ] + ] + [ + [ +`` +std::pair +in_edges(vertex_descriptor v, + const directed_graph& g) +`` + ] + [ + Returns an iterator range providing access to the in-edges of + vertex `v` in the graph `g`. + ] + ] + [ + [ +`` +std::pair +adjacent_vertices(vertex_descriptor v, + const directed_graph& g) +`` + ] + [ + Returns an iterator range providing access to the adjacenct vertices + of vertex `v` in the graph `g`. Note that this is functionally + equivalent to iterating over the targets of all out-edges of `v`. + ] + ] + [ + [ +`` +vertices_size_type +num_vertices(const directed_graph& g) +`` + ] + [Returns the number of vertices in the graph `g`.] + ] + [ + [ +`` +edge_size_type +num_edges(const directed_graph& g) +`` + ] + [Returns the number of edges the graph `g`.] + ] + [ + [ +`` +degree_size_type +degree(vertex_descriptor v, + const directed_graph& g) +`` + ] + [ + Returns the total degree of vertex `v` in the graph `g`. This is + functionally equivalent `out_degree(v,g) + in_degree(v,g)`. + ] + ] + [ + [ +`` +degree_size_type +out_degree(vertex_descriptor v, + const directed_graph& g) +`` + ] + [ + Returns the out-degree of vertex `v` in the graph `g`. In an + `directed_graph` this is equal to `in_degree(v, g)`. + ] + ] + [ + [ +`` +degree_size_type +in_degree(vertex_descriptor v, + const directed_graph& g) +`` + ] + [ + Returns the in-degree of vertex `v` in the graph `g`. In an + `directed_graph` this is equal to `out_degree(v, g)`. + ] + ] + [ + [ +`` +vertex_descriptor +vertex(vertices_size_type n + const directed_graph& g) +`` + ] + [ + Returns the /nth/ vertex in the graph `g`. With directed graphs, + this method is /O(n)/. As such its use with this type of graph is + discouraged. + ] + ] + [ + [ +`` +std::pair +edge(vertex_descriptor u, + vertex_descriptor v, + const directed_graph& g) +`` + ] + [ + If the edge /(u,v)/ is in `g`, then this function returns the + descriptor for the edge connecting `u` and `v` with boolean value + set to `true`. Otherwise, the boolean value is `false` and the + edge descriptor is invalid. + ] + ] + [ + [ +`` +vertex_size_type +get_vertex_index(vertex_descriptor v, + const directed_graph& g) +`` + ] + [ + Returns the vertex index of the given vertex descriptor v. Note + that indices are /not/ required to be in the range \[0, `num_vertices(g)`). + This function is an alias for `get(vertex_index,g,v)`. + ] + ] + [ + [ +`` +vertex_size_type +max_vertex_index(vertex_descriptor v, + const directed_graph& g) +`` + ] + [ + Returns the vertex index of the given vertex descriptor v. Note + that indices are /not/ required to be in the range \[0, `num_vertices(g)`). + This function is an alias for `get(vertex_index,g,v)`. + ] + ] +] + +[h5 Non-member Modifiers] +[table + [[Function] [Description]] + [ + [ +`` +vertex_descriptor +add_vertex(directed_graph& g) +`` + ] + [Adds a vertex to `g` and returns a descriptors for the new vertex.] + ] + [ + [ +`` +void +clear_vertex(vertex_descriptor v, + directed_graph& g) +`` + ] + [ + Removes all in- and out-edges of `v`, but leaves `v` in the graph `g`. + This is functioanlly equivalent to invoking `remove_edge()` on all + in- or out-edges of `v`, invalidating descriptors and iterators that + reference edges incident to `v`. + ] + ] + [ + [ +`` +void +clear_out_edges(vertex_descriptor v, + directed_graph& g) +`` + ] + [ + Removes all out-edges from vertex `v`, but does not remove the vertex + itself. This is functionally equivalent to calling `remove_edge()` for + all out-edges of `v`, invalidating any descriptors and iterators that + reference edges incident to that vertex. + ] + ] + [ + [ +`` +void +clear_in_edges(vertex_descriptor v, + directed_graph& g) +`` + ] + [ + Removes all in-edges from vertex `v`, but does not remove the vertex + itself. This is functionally equivalent to calling `remove_edge()` for + all in-edges of `v`, invalidating any descriptors and iterators that + reference edges incident to that vertex. + ] + ] + [ + [ +`` +vertex_descriptor +remove_vertex(vertex_descriptor v, + directed_graph& g) +`` + ] + [ + Removes vertex `v` from the graph `g`. It is assumed that `v` has no + incident edges before removal. To ensure this is, call `clear_vertex(v, g)` + before removing it. + + Assuming that the vertex indices were in the range \[0, `num_vertices(g)`) + before calling this method, this operation will invalidate all vertex indices + in the range (vertex_index(v, g), `num_vertices(g)`), requiring indices to + be renumbered using the `renumber_vertex_indices(g)` method. If possible, + prefer to remove groups of vertices at one time before renumbering since + renumbering is a /O(n)/ time operation. + ] + ] + [ + [ +`` +void +remove_vertex_and_renumber_indices(vertex_iterator i, + directed_graph& g) +`` + ] + [ + Removes the vertex indicated by the iterator `i` from the graph `g`. Like + the `remove_vertex(v,g)` function, it is expected that `*i` have no + incident edges at the time of removal. + + As indicated by the name, this method will also renumber vertex indices + after the removal of `*i`. This operation iterates over vertices after + `i`, decrementing their index by 1. If your program removes several + vertices at once, prefer to call several `remove_vertex(v,g)` methods, + followed by `renumber_vertices(g)` before using `g` in an algorithm. + ] + ] + [ + [ +`` +void +renumber_vertex_indices(directed_graph& g) +`` + ] + [ + Renumbers all interior vertex indices such that each vertex has an index + in the range \[0, `num_vertices(g)`). Generally, this function needs to + be called after removing vertices and before invoking different graph + algorithms. + ] + ] + [ + [ +`` +std::pair +add_edge(vertex_descriptor u, + vertex_descriptor v, + directed_graph& g) +`` + ] + [ + Adds the edge /(u,v)/ to the graph and returns a descriptor for the new + edge. For `directed_graph`s, the boolean value of the pair will always + be true. + ] + ] + [ + [ +`` +void +remove_edge(vertex_descriptor u, + vertex_descriptor v, + directed_graph& g) +`` + ] + [ + Removes the edge /(u,v)/from the graph. This operation invalidates any + descriptors or iterators referencing the edge. Note that `u` and `v` must + be valid descriptors and /(u,v)/ must be in the graph. If `g` is a multigraph + (with multiple edges between /(u,v)/, this mehtod will cause the removal of + all such edges connecting `u` and `v`. + ] + ] + [ + [ +`` +void +remove_edge(edge_descriptor e, + directed_graph& g) +`` + ] + [ + Removes the edge `e` from the graph. If multuple edges exist from + /(`source(e,g)`, `target(e,g)`)/, then this method will remove only + the single, specified edge. + ] + ] + [ + [ +`` +void +remove_edge(out_edge_iterator i, + directed_graph& g) +`` + ] + [ + This is functionally equivalent to `remove_edge(*i, g)`. + ] + ] + [ + [ +`` +void +remove_edge_if(Predicate p, + directed_graph& g) +`` + ] + [ + Removes all edges from the graph that satisfy `predicate`. That is, if + `p()` returns true when applied to an edge, then that edge is removed. + The affect on descriptor and iterator is the same as that of invoking + `remove_edge()` for on each of the removed vertices. + ] + ] + [ + [ +`` +template +void +remove_out_edge_if(vertex_descriptor v, + Predicate p, + directed_graph& g) +`` + ] + [ + Removes all edges out-edges from vertex`v` that satisfy `predicate`. + That is, if `p()` returns true when applied to an edge, then that edge + is removed. The affect on descriptor and iterator is the same as that + of invoking `remove_edge()` for on each of the removed vertices. + ] + ] + [ + [ +`` +template +void +remove_in_edge_if(vertex_descriptor v, + Predicate p, + directed_graph& g) +`` + ] + [ + Removes all edges in-edges from vertex`v` that satisfy `predicate`. + That is, if `p()` returns true when applied to an edge, then that edge + is removed. The affect on descriptor and iterator is the same as that + of invoking `remove_edge()` for on each of the removed vertices. + ] + ] +] + +[h5 Proprety Map Acessors] +[table + [[Function] [Description]] + [ + [ +`` +template +property_map::type +get(Property, directed_graph& g) +`` + +`` +template +property_map::const_type +get(Property, const directed_graph& g) +`` + ] + [ + Returns the property map object for the vertex property specified by the + type `Property`. This type must match one of the properties specified in + the `VertexProperties` template argument. + ] + ] + [ + [ +`` +template +typename + property_traits< + property_map::const_type + >::value_type +get(Property, + const directed_graph& g, + Descriptor d) +`` + ] + [ + Returns the property value specified by the type `Property` for either + the `vertex_descriptor` or `edge_descriptor` denoted by `d`. + ] + ] + [ + [ +`` +template +void +put(Property, + const directed_graph& g, + Descriptor d, + Value v) +`` + ] + [ + Sets the property value denoted by the type `Property` for either edge + or vertex descriptor `d` to the given value `v`. + ] + ] + [ + [ +`` +template +typename graph_property::type& +get_property(directed_graph& g, GraphProperty) +`` + +`` +template +const typename graph_property::type& +get_property(const directed_graph& g, GraphProperty) +`` + ] + [ + Returns the graph property specified by the type `GraphProperty` for + the graph `g`. + ] + ] + [ + [ +`` +template +void +set_property(const directed_graph& g, GraphProperty, Value v) +`` + ] + [ + Sets the graph proeprty specified by the type `GraphProperty` to + the given value `v`. Note that `GraphProperty` must be one of + the properties in the `GraphProperties` template argument. + ] + ] +] + +[h4 Rationale] +Unlike most graph classes in Boost.Graph, the `directed_graph` does not model the +[MutablePropertyGraph] concept. The reason for this is that it is relatively +difficult from a usability standpoint to easily deduce the type to be passed as a +property when adding vertices and edges - but especially vertices. + +[endsect] \ No newline at end of file diff --git a/quickbook/reference/distance_recorder.qbk b/quickbook/reference/distance_recorder.qbk new file mode 100644 index 00000000..1d38bc30 --- /dev/null +++ b/quickbook/reference/distance_recorder.qbk @@ -0,0 +1,99 @@ +[/ + / Copyright (c) 2007 Andrew Sutton + / + / 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) + /] + +[section Distance Recorder] + + template + class distance_recorder; + +This is an [EventVisitor] that records the distance of a vertex (using a property +map) from some source vertex during a graph search. When applied to edge /e = (u,v)/, +the distance of /v/ is recorded to be one more than the distance of /u/. The distance +recorder is typically used with the `on_tree_edge` or `on_relax_edge` events, and cannot +be used with vertex events. + +The [distance_recorder] class 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 `std::pair` to form +an [EventVisitorList]. + +[h4 Model Of] +[EventVisitor] + +[h4 Where Defined] +`boost/graph/visitors.hpp` + +[h4 Template Parameters] +[table + [[Parameter] [Description] [Default]] + [ + [`DistanceMap`] + [ + A [WritablePropertyMap] where the key type is of type `vertex_descriptor` + and the value type is numeric (usually an integer or the same type as the + edge weight). + ] + ] + [ + [`EventTag`] + [ + A tag used to specify when the recorder should be applied during the graph + algorithm. `EventTag` must be an edge event. + ] + ] +] + +[h4 Associated Types] +[table + [[Type] [Description]] + [ + [`distance_recorder::event_filter`] + [ + This type will be the same as the template parameter `EventTag`. + ] + ] +] + +[h4 Member Functions] +[table + [[Function] [Description]] + [ + [`distance_recorder(DistanceMap pa)`] + [Construct a distance recorder object with a predecessor property map `pa`.] + ] + [ + [ +`` +template +void operator()(Edge e, const Graph& g) +`` + ] + [ + Given edge `e` as /(u,v)/, this records the distance of `v` as one + plus the distance of `u`. + ] + ] +] + +[h4 Non-Member Functions] +[table + [[Function] [Description]] + [ + [ +`` +template +distance_recorder +record_distances(DistanceMap pa, EventTag) +`` + ] + [ + A convenience function for creating [distance_recorder] instances. + ] + ] +] + +[endsect] diff --git a/quickbook/reference/eccentricity.qbk b/quickbook/reference/eccentricity.qbk new file mode 100644 index 00000000..e2764982 --- /dev/null +++ b/quickbook/reference/eccentricity.qbk @@ -0,0 +1,337 @@ +[/ + / Copyright (c) 2007 Andrew Sutton + / + / 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) + /] + +[section Eccentricity] +[template ex_eccentricity[] [link + boost_graph.reference.algorithms.measures.eccentricity.examples.eccentricity__radius__and_diameter + Eccentricity Example]] + +[heading Overview] +The /eccentricity/ of a vertex is the maximum geodesic distance (shortest path) from +that vertex to any other vertex in the graph. Intuitively, vertices with low +eccentricity can reach all other vertices in the graph more "quickly" than vertices +with high eccentricity. Eccentricity values are used to help compute the /radius/ and +/diameter/. + +Note that if vertex /u/ is disconnected from any other vertex /v/ the distance from +/u/ to /v/ is infinite. This implies the eccentricity of /v/ is infinite as well. +If any vertex in a graph has infinite eccentricity, the graph also has an infinite +diameter. + +Consider the following social network represented by an undirected, unweighted +graph. + +[figure + images/reference/social_network.png + *Figure 1.* A network of friends +] + +Because the graph is small and relatively well, connected the eccentricies are +exaclty 2 or 3 for all vertices. The radius (the smaller of these numbers) +is 2, and the diameter is 3. See the [ex_eccentricity] for details on computing +eccentricity and related measures. + +[section [^eccentricity()]] + #include + + template + typename property_traits::value_type + eccentricity(const Graph& g, DistanceMap dm) + +The `eccentricity()` function computes the eccentricty of a single vertex +given the shortest paths to every other vertex in the graph. The distance map can +be computed using a shortest paths algorithms (e.g., [dijkstra_shortest_paths] or a +[breadth_first_search]. The output of this function is returned to the caller. + +[heading Parameters] +[table + [[Type] [Parameter] [Description]] + [ + [required, in] [`const Graph& g`] + [ + The graph for which the eccentricity measures are being comptued. + + *Requirements:* The `Graph` type must be a model of the + [VertexListGraph] concepts. + ] + ] + [ + [required, in] [`DistanceMap dm`] + [ + Given a vertex `v`, the `dm` parameter provides the length of the + shortest path between a vertex `u` and `v`. The vertex `u` is the + vertex for which the distance map was initially computed. + + *Requirements:* `DistanceMap` must be a model of [ReadablePropertyMap]. + The `key_type` of the distance map must be the same as the `vertex_descriptor` + of the `Graph` parameter. The `value_type` is required to be a model of + [NumericValue]. + ] + ] +] + +[heading Return Value] +The `eccentricity()` function returns the eccentricity of the vertex. If the graph +is unconnected, this returns the infinite value of the distance map's `value_type`. + +[heading Complexity] +The `eccentricity()` returns in linear with respect to the number of vertices +in the graph. +[endsect] + +[section [^eccentricities()]] + #include + + template + std::pair::value_type, + typename property_traits::value_type> + eccentricity(const Graph& g, DistanceMatrixMap dm, EccentricityMap em) + +The `eccentricities()` function computes the eccentricity of each vertix in the graph, +given a matrix that provides the shortest paths between all pairs of vertices. This +matrix can be computed as the output of an all-pairs shortest paths algorithm (e.g., [floyd_warshall_all_pairs_shortest_paths]) or repeated application of a +[breadth_first_search] (if the graph is unweighted). Theoutput of this function is +stored in the eccentricity property map. + +This function also computes the radius and diameter of the graph, returning those +values in a pair. + +[heading Parameters] +[table + [[Type] [Parameter] [Description]] + [ + [required, in] [`const Graph& g`] + [ + The graph for which the eccentricity measures are being comptued. + + *Requirements:* The `Graph` type must be a model of the + [VertexListGraph] concepts. + ] + ] + [ + [required, in] [`DistanceMatrixMap dm`] + [ + Given vertices /u/ and /v/, the `dm` parameter provides the length + of the shortest path between the two vertices. Note that the + distance between a vertex and itself should be 0 (i.e., `dm[u][u] == 0`). + + *Requirements:* `DistanceMatrixMap` must be a model of [ReadablePropertyMap]. + The `key_type` of the distance matrixc must be the same as the `vertex_descriptor` + of the `Graph` parameter. The `value_type` must be a [ReadWritePropertyMap] + whose `key_type` is also the `vertex_descriptor` of the `Graph` and + whose `value_type` is a model of [NumericValue]. + ] + ] + [ + [required, out] [`EccentricityMap em`] + [ + The eccentricity map `em` stores the computed eccentricity values for + each vertex in the graph. + + *Requirements:* The `EccentricityMap` type must model the [WritablePropertyMap] + concept. The `key_type` of the property map must be the `vertex_descriptor` + of the `Graph` parameter. The `value_type` must be the same type as the + `value_type` of the `DistanceMatrixMap` parameter. + ] + ] +] + +[heading Return] +The `eccentricities()` function returns a pair containing the radius and diameter +as the `first` and `second` elements respectively. + +[heading Complexity] +The `eccentricities()` function returns in ['O(n[super 2])] where /n/ is the number +of vertices in the graph. +[endsect] + +[section [^radius()]] + #include + + template + inline typename property_traits::value_type + radius(const Graph& g, EccentricityMap ecc) + +The `radius()` function returns the radius of the graph, which is defined as the +minimum eccentricity of any vertex in the graph. The radius is computed from the +eccentricities that have been previously computed using the [eccentricity] function. + +[heading Parameters] +[table + [[Type] [Parameter] [Description]] + [ + [required, in] [`const Graph& g`] + [ + The graph for which the eccentricity measures are being comptued. + + *Requirements:* The `Graph` type must be a model of the + [VertexListGraph] concepts. + ] + ] + [ + [required, out] [`EccentricityMap em`] + [ + The eccentricity map `em` provides access to the previously computed + eccentricities of all vertices in the graph. + + *Requirements:* The `EccentricityMap` type must model the [ReadablePropertyMap] + concept. The `key_type` of the property map must be the `vertex_descriptor` + of the `Graph` parameter. The `value_type` must model the [NumericValue] + concept. + ] + ] +] + +[heading Return Value] +The `radius()` function return the radius of the graph. The return type of +this function is the same as the `value_type` of the `EccentricityMap` parameter. + +[heading Complexity] +The `radius()` function returns in linear time with respect to the number +of vertices in the graph. +[endsect] + +[section [^diameter()]] + #include + + template + inline typename property_traits::value_type + diameter(const Graph& g, EccentricityMap ecc) + +The `diameter()` function returns the diameter of the graph, which is defined as the +maximum eccentricity of any vertex in the graph. The diameter is computed from the +eccentricities that have been previously computed using the [eccentricity] function. + +[heading Parameters] +[table + [[Type] [Parameter] [Description]] + [ + [required, in] [`const Graph& g`] + [ + The graph for which the eccentricity measures are being comptued. + + *Requirements:* The `Graph` type must be a model of the + [VertexListGraph] concepts. + ] + ] + [ + [required, out] [`EccentricityMap em`] + [ + The eccentricity map `em` provides access to the previously computed + eccentricities of all vertices in the graph. + + *Requirements:* The `EccentricityMap` type must model the [ReadablePropertyMap] + concept. The `key_type` of the property map must be the `vertex_descriptor` + of the `Graph` parameter. The `value_type` must model the [NumericValue] + concept. + ] + ] +] + +[heading Return Value] +The `diameter()` function return the diameter of the graph. If any vertices +are disconnected from the graph, the diameter will be infinite. The return type of +this function is the same as the `value_type` of the `EccentricityMap` parameter. + +[heading Complexity] +The `diameter()` function returns in linear time with respect to the number +of vertices in the graph. +[endsect] + +[section [^radius_and_diameter()]] + #include + + template + std::pair::value_type, + typename property_traits::value_type> + radius_and_diameter(const Graph& g, EccentricityMap ecc) + +The `radius_and_diameter()` function returns both the radius and diameter of the +graph as a pair such that the `first` element of the pair is the radius and the +`second` element is the diameter. These values are computed from the eccentricities +that have been previously computed using the [eccentricity] function. + +[heading Parameters] +[table + [[Type] [Parameter] [Description]] + [ + [required, in] [`const Graph& g`] + [ + The graph for which the eccentricity measures are being comptued. + + *Requirements:* The `Graph` type must be a model of the + [VertexListGraph] concepts. + ] + ] + [ + [required, out] [`EccentricityMap em`] + [ + The eccentricity map `em` provides access to the previously computed + eccentricities of all vertices in the graph. + + *Requirements:* The `EccentricityMap` type must model the [ReadablePropertyMap] + concept. The `key_type` of the property map must be the `vertex_descriptor` + of the `Graph` parameter. The `value_type` must model the [NumericValue] + concept. + ] + ] +] + +[heading Return Value] +The `radius_and_diameter()` funtion returns a pair containing both the radius (`first`) +and diameter (`second`) of the graph. The types of these values are the same as the +`value_type` of the `EccentricityMap`. + +[heading Complexity] +The `radius_radius_diameter()` returns in linear time with respect to the number of vertices +in the graph. +[endsect] + +[section Examples] +[heading Eccentricity, Radius, and Diameter] +This example computes the eccentricities for all vertices in a graph, and the radius +and diameter of the graph itself. This example includes the following files: + +* [^examples/eccentricity.cpp] +* [^examples/helper.hpp] + +[eccentricity_example] + +Note that we can also compute the radius and diameter separatel. For exmaple: + + // Compute the radius and diameter after computing eccentricites, + // but separately. + int r = radius(g, em); + int d = diameter(g, em); + + // Compute the radius and diameter after computing eccentricities, + // but in one step. + int r, d; + tie(r, d) = radius_diameter(g, em); + +For small graphs, choosing one method over the other makes little difference. For +large graphs, however, multiple iterations over the vertex set may result in lower +performance. + +If given the `social_network.graph` file as input, the output will be: + +[pre +Scott 2 +Jill 3 +Mary 3 +Bill 3 +Josh 3 +Frank 2 +Laurie 3 +Anne 3 +Howard 3 +radius: 2 +diamter: 3 +] +[endsect] + +[endsect] \ No newline at end of file diff --git a/quickbook/reference/edge_list.qbk b/quickbook/reference/edge_list.qbk new file mode 100644 index 00000000..5b8d997d --- /dev/null +++ b/quickbook/reference/edge_list.qbk @@ -0,0 +1,10 @@ +[/ + / Copyright (c) 2007 Andrew Sutton + / + / 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) + /] + +[section Edge List] + +[endsect] \ No newline at end of file diff --git a/quickbook/reference/exterior_vertex_property.qbk b/quickbook/reference/exterior_vertex_property.qbk new file mode 100644 index 00000000..d6783ed8 --- /dev/null +++ b/quickbook/reference/exterior_vertex_property.qbk @@ -0,0 +1,106 @@ +[/ + / Copyright (c) 2007 Andrew Sutton + / + / 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) + /] + +[section Exterior Vertex Property] + + template + class exterior_vertex_property; + +The `exterior_vertex_property` class is a utility for generically creating +and initializing exterior properties for graph classes. + +[note +In fact, this class is the /only/ way to generically create exterior properties +for graphs. +] + +[heading Notation] +The following expressions are used in this document: +[table + [[Expression] [Description]] + [[`G`] [A graph type modeling a refinement of the [Graph] concept.]] + [[`V`] [A value type that models the [SgiAssignable] concept.]] +] + +[heading Model Of] +[ExteriorProperty] + +[heading Template Parameters] +[table + [[Parameter] [Description]] + [ + [`Graph`] + [ + *Semantics:* Specifies the type of graph for which the property + is being declared. + + *Requirements:* `Graph` must model a refinement of the the + [Graph] concept. + ] + ] + [ + [`Value`] + [ + *Semantics:* Specifies the value type of the exterior property. + ] + ] +] + +[heading Where Defined] +`boost/graph/exterior_property.hpp` + +[heading Associated Types] +[table + [[Type] [Description]] + [ + [`P::value_type`] + [ + This is the same as the template parameter `Value`. + ] + ] + [ + [`P::key_type`] + [ + This is the same as `graph_traits::vertex_descriptor`. + ] + ] + [ + [`P::container_type`] + [ + This type selects the preferred property container based on the + type of graph such that values are accessed in constant time + on average. + ] + ] + [ + [`P::map_type`] + [ + This type selects the preferred property map type based on the + type of graph. + ] + ] +] + +[heading Examples] +Using the `exterior_vertex_property` it is possible to generically create +exterior properties for a graph. Consider the following template function: + + template + void + do_shortest_paths(const Graph& g, Weight w = ()) + { + typedef exterior_vertex_property DistanceProperty; + typedef DistanceProperty::container_type DistanceContainer; + typedef DistanceProeprty::map_type DistanceMap; + + DistanceContainer distances(num_vertices(g)); + DistanceMap dist(make_property_map(distances)); + + dijkstra_shortest_paths(g, *vertices(g).first, distance_map(dist)); + } + +[endsect] \ No newline at end of file diff --git a/quickbook/reference/mean_geodesic.qbk b/quickbook/reference/mean_geodesic.qbk new file mode 100644 index 00000000..6a7ded54 --- /dev/null +++ b/quickbook/reference/mean_geodesic.qbk @@ -0,0 +1,361 @@ +[/ + / Copyright (c) 2007 Andrew Sutton + / + / 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) + /] + +[section Mean Geodesic] +[template ex_mean_geodesic[] [link + boost_graph.reference.algorithms.measures.mean_geodesic.examples.mean_geodesic_distance + Mean Geodesic Example]] +[template ex_inclusive_mean_geodesic[] [link + boost_graph.reference.algorithms.measures.mean_geodesic.examples.inclusive_mean_geodesic_distance + Inclusive Mean Geodesic Example]] + +[heading Overview] +The /mean geodesic distance/ measure is used in large network analysis to identify +central vertices and as a measure of the /small-world phenomenon/. The mean geodesic +distance of a vertex is defined as the average of geodesic distances from that +vertex every /other/ vertex in the graph. It is computed as: + +[$images/eq/mean_geodesic.png] + +Where /d(u,v)/ is the shortest path (geodesic distance) from /u/ to /v/. Note +that this excludes /d(u,u)/ from the average, even if /d(u,u)/ is non-zero, which +is rare for social networks. Note that if any vertex in the graph is unreachable +from any other, then the graph is unconnected, and the distance between those two +unonnected vertices is infinite. This imlplies that the closeness of every vertex +in an unconnected (and undirected) graph is also infinite. This is not necessarily +the case for directed graphs. + +The mean geodesic distance is often used to quantify whether or not a graph exhibits +the so-called small-world phenomenon. If the mean geodesic distance of a graph is +small with respect to its density (the ratio of vertices to edges), then the graph +is said to exhibit the small-world phenomenon. This implies that vertices are +The mean geodesic distance of a graph, it's so-called /small-world distance/, is +the average of the mean geodesics for each vertex. It is computed as: + +[$images/eq/small_world.png] + +Note that computing the measure in this fashion means that the small-world distance +of the graph may lie outside the minimum and maximum mean geodesic distances of its +vertices. + +Consider a social network of friends, which is represented by an undirected graph. + +[figure + images/reference/social_network.png + *Figure 1.* A network of friends. +] + +In this network, Frank has the lowest mean geodesic distance with an average of +1.375. Scott and Laurie have the second lowest distances with values of 1.5 and +1.875 respectively. The small-world distance of this graph is approximately 1.92. +See the [ex_mean_geodesic] for details on computing the mean geodesic and small +world distances of undirected graphs. + +This framework also allows for a specialization of measures used to compute these +values. The default measures used in this framework implement the formulas given +above. In some instances, it may be worthwhile to redefine the measure. For example, +if a graph has meaningful non-zero distance-to-self, the averages should be computed +over all vertices instead of excluding the vertex for which distances are being +averaged. See the [ex_inclusive_mean_geodesic] for details on defining alternative +measures, and using weighted graphs to find shortest paths. + +[section [^mean_geodesic()]] + #include + + template + float mean_geodesic(const Graph& g, DistanceMap dm) + + template + ResultType mean_geodesic(const Graph& g, DistanceMap dm) + + template + typename Measure::result_type + mean_geodesic(const Graph& g, DistanceMap dm, Measure m) + +The `mean_geodesic()` function can be used to compute the mean geodesic distance +(its average distance to all other vertices) for a single vertex. This function +requires a distance map that contains the distance from one vertex (the source) to +all others in the graph. This distance map can be computed as the result of a +shortest paths algorithm such as [dijkstra_shortest_paths] or [bellman_ford_shortest_paths]. +If the graph is unweighted, distances can be recorded from a [breadth_first_search]. + +[heading Parameters] +[table + [[Type] [Parameter] [Description]] + [ + [template] [`ResultType`] + [ + The `ResultType` template parmeter explitly specifies the the + return type of the `closeness()` function. If not + given, the return type is `float`. + + *Requirements:* The return type is required to model the + [NumericValue] concept. + ] + ] + [ + [required, in] [`const Graph& g`] + [ + The graph for which vertex measures are being comptued. + + *Requirements:* The `Graph` type must be a model of the + [VertexListGraph] concepts. + ] + ] + [ + [required, in] [`DistanceMap dm`] + [ + Given a vertex `v`, the `dm` parameter provides the length of the + shortest path between a vertex `u` and `v`. The vertex `u` is the + vertex for which the distance map was initially computed. + + *Requirements:* `DistanceMap` must be a model of [ReadablePropertyMap]. + The `key_type` of the distance map must be the same as the `vertex_descriptor` + of the `Graph` parameter. The `value_type` is required to be a model of + [NumericValue]. + ] + ] + [ + [optional, in] [`Measure measure`] + [ + The 'measure' parameter is an instance of a closeness measure that + performs the final division for this computation. + + *Requirements:* The `Measure` type must be a model of the [DistanceMeasure] + concept. The `distance_type` must be the same type as the `value_type` + of the `DistanceMap` parameter. The `result_type` of the `Measure` must + model the [NumericValue] concept. + ] + ] +] + +[heading Return] +The `mean_geodesic()` function returns the average of geodesic distances +to other vertices from a source. If the source vertex is not connected to one other +in the graph, this value is infinite. + +[heading Complexity] +The `mean_geodesic()` function returns in /O(n*O(M))/ where /n/ is the number of +vertices in the graph and /O(M)/ is the complexity of the given measure. If no +measure is given, this function returns in linear time. +[endsect] + +[section [^all_mean_geodesics()]] + #include + + template + typename property_traits::value_type + all_mean_geodesics(const Graph& g, DistanceMatrixMap dm, GeodesicMap gm) + + template + typename property_traits::value_type + all_mean_geodesics(const Graph& g, DistanceMatrixMap dm, GeodesicMap gm, Measure m) + +The `all_mean_geodesics()` function computes the average distance of each vertex in a +graph to every other vertex using a matrix that contains the distances between +each pair of vertices. This matrix can be computed as the output of an all-pairs shortest +path algorithm (e.g., [floyd_warshall_all_pairs_shortest_paths] or [johnson_all_pairs_shortest_paths]) +or as the result of repeated [breadth_first_search]s (if the graph is unweighted). + +This function returns the average of all mean geodesic distances, also known as the +small-world distance. If any vertices have infinite mean geodesic distance, this +return value will be infinite. + +[heading Parameters] +[table + [[Type] [Parameter] [Description]] + [ + [required, in] [`const Graph& g`] + [ + The graph for which vertex measures are being comptued. + + *Requirements:* The `Graph` type must be a model of the + [VertexListGraph] concepts. + ] + ] + [ + [required, in] [`DistanceMatrixMap dm`] + [ + Given vertices /u/ and /v/, the `dm` parameter provides the length + of the shortest path between the two vertices. + + *Requirements:* `DistanceMatrixMap` must be a model of [ReadablePropertyMap]. + The `key_type` of the distance matrixc must be the same as the `vertex_descriptor` + of the `Graph` parameter. The `value_type` must be a [ReadWritePropertyMap] + whose `key_type` is also the `vertex_descriptor` of the `Graph` and whose + `value_type` is a model of [NumericValue]. + ] + ] + [ + [required, both] [`GeodesicMap gm`] + [ + The geodesic map `gm` stores the resulting mean geodesic distances for + each vertex in the graph. + + *Requirements:* The `GeodesicMap` type must be a model of the + [WritablePropertyMap] concept. The `key_type` of this parameter + must be the same as the `vertex_descriptor` of the `Graph` parameter, + and the `value_type` must be a model of the [NumericValue] concept. + ] + ] + [ + [optional, in] [`Measure measure`] + [ + The 'measure' parameter is an instance of a closeness measure operates + on the sum of distances of a vertex. + + *Requirements:* The `Measure` type must be a model of the [DistanceMeasure] + concept. The `distance_type` must be the same type as the `value_type` + of the `DistanceMap` or `DistanceMatrixMap`. The `result_type` of the + `Measure` must model the [NumericValue] concept. + ] + ] +] + +[heading Return] +The `all_mean_geodesics()` function returns the small-world distance for the graph. +This is the average of the mean geodesic distances of all vertices in the graph. +If any vertices have infinite mean geodesic distance, then the small-world distance +will also be infinite. + +[heading Complexity] +The `all_mean_geodesics()` function returns in ['O(n[super 2]*O(M))] where /n/ is the +number of vertices in the graph, and /O(M)/ is the complexity of the given measure. +If no measure is given, this function returns in quadratic time. +[endsect] + +[section [^small_world_distance()]] + #include + + template + typename Measure::result_type + small_world_distance(const Graph& g, GeodesicMap gm, Measure m) + + template + typename property_traits::value_type + small_world_distance(const Graph& g, GeodesicMap gm) + +The `small_world_distance()` function computes the mean geodesic distance for the +entire graph by averaging the mean geodesic distances of each vertex in the geodesic +distance map. Note that this function does not compute the mean geodesic distances +of each vertex. Those values must be computed by using the [mean_goedesic] function. + +[heading Parameters] +[table + [[Type] [Parameter] [Description]] + [ + [required, in] [`const Graph& g`] + [ + The graph for which vertex measures are being comptued. + + *Requirements:* The `Graph` type must be a model of the + [VertexListGraph] concepts. + ] + ] + [ + [required, both] [`GeodesicMap gm`] + [ + The geodesic map `gm` contains the previously computed mean geodesic + distances for each vertex in the graph. + + *Requirements:* The `GeodesicMap` type must model the [ReadablePropertyMap] + concept. The `key_type` of this parameter must be the same as the + `vertex_descriptor` of the `Graph` parameter, and the `value_type` must + be a model of the [NumericValue] concept. + ] + ] + [ + [optional, in] [`Measure measure`] + [ + The 'measure' parameter is an instance of a closeness measure that + performs the final division for this computation. + + *Requirements:* The `Measure` type must be a model of the [DistanceMeasure] + concept. The `distance_type` must be the same type as the `value_type` + of the `GeodesicMap`. The `result_type` must model the [NumericValue] + concept. + ] + ] +] + +[heading Return] +The `small_world_distance()` function returns the mean geodesic distance for the +entire graph - a common measure of the small-world property. If the graph is +unconnected, the mean geodesic distance is infinite. + +[heading Complexity] +The `small_world_distance()` function returns in /O(n*O(M))/ where /n/ is the number +of vertices in the graph and /O(M)/ is the complexity of the measure. If not measure +is given, then this function returns in linear time. +[endsect] + +[section Examples] +[heading Mean Geodesic Distance] +This example shows how to compute the mean geodesic distance for each vertex +in a social network, and the mean geodesic distance for the graph as a whole. +This example includes the files + +* [^examples/mean_geodesic.hpp] +* [^examples/helper.hpp] + +[mean_geodesic_example] + +In this example, the small world distance (`sw`) can be computed separetly from +the mean geodesic distances if need be. + + // Compute the small-world distance after computing mean geodesics + float sw = small_world_distance(g, gm); + +If given the file `social_network.graph` as input, the output of this program will +be: + +[pre +Scott 1.5 +Jill 2.125 +Mary 2 +Bill 2.125 +Josh 2 +Frank 1.375 +Laurie 1.875 +Anne 2.125 +Howard 2.125 +small world distance: 1.91667 +] + +Note that this program can be easily modified to work on directed graphs. In the +file `social_network.hpp`, simply replace `typedef undirected_graph ...` to +`typedef directed_graph ...`. + +[heading Inclusive Mean Geodesic Distance] +This example shows how to implement alternative measures for the [mean_geodesic] +and [graph_mean_geodesic] functions to account for non-zero length self-loop +distances. Mean geodesic distances are computed both ways and the results printed +to standard output. This example includes the files: + +* [^examples/mean_geodesic.hpp] +* [^examples/helper.hpp] + +[inclusive_mean_geodesic_example] + +If given the file `prob_network.graph` as input, the output of this program will +be: + +[pre +vertex excluding including +myspace 0.941667 0.807143 +digg 0.538333 0.461429 +blogger 0.496667 0.425714 +slashdot 0.721667 0.618571 +wikipedia 0.498333 0.427143 +blogspot 0.763333 0.654286 +bbc 0.818333 0.701429 +small world (excluding self-loops): 0.682619 +small world (including self-loops): 0.585102 +] + +[endsect] +[endsect] \ No newline at end of file diff --git a/quickbook/reference/predecessor_recorder.qbk b/quickbook/reference/predecessor_recorder.qbk new file mode 100644 index 00000000..056f197b --- /dev/null +++ b/quickbook/reference/predecessor_recorder.qbk @@ -0,0 +1,103 @@ +[/ + / Copyright (c) 2007 Andrew Sutton + / + / 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) + /] + +[section Predecessor Recorder] + + template + class predecessor_recorder; + +This is an [EventVisitor] that records the predecessor (or parent) of a vertex in +a predecessor 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 predecessor recorder is typically used with the `on_tree_edge` or +`on_relax_edge events`, and cannot be used with vertex events. + +[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 `std::pair` to form an [EventVisitorList]. + +Algorithms such as Dijkstra's and breadth-first search will not assign a predecessor +to the source vertex (which is the root of the search tree). Often times it is useful to +initialize the source vertex's 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, so that all the root nodes can be distinguished. + +[h4 Model Of] +[EventVisitor] + +[h4 Where Defined] +`boost/graph/visitors.hpp` + +[h4 Template Parameters] +[table + [[Parameter] [Description] [Default]] + [ + [`PredecessorMap`] + [ + A [WritablePropertyMap] where the key type and value type are of type + `vertex_descriptor`. + ] + ] + [ + [`EventTag`] + [ + A tag used to specify when the recorder should be applied during the graph + algorithm. `EventTag` must be an edge event. + ] + ] +] + +[h4 Associated Types] +[table + [[Type] [Description]] + [ + [`predecessor_recorder::event_filter`] + [ + This type will be the same as the template parameter `EventTag`. + ] + ] +] + +[h4 Member Functions] +[table + [[Function] [Description]] + [ + [`predecessor_recorder(PredecessorMap pa)`] + [Construct a predecessor recorder object with a predecessor property map `pa`.] + ] + [ + [ +`` +template +void operator()(Edge e, const Graph& g) +`` + ] + [ + Given edge `e` as /(u,v)/, this records `u` as the predecessor (parent) of `v`. + ] + ] +] + +[h4 Non-Member Functions] +[table + [[Function] [Description]] + [ + [ +`` +template +predecessor_recorder +record_predecessors(PredecessorMap pa, EventTag) +`` + ] + [ + A convenience function for creating [predecessor_recorder] instances. + ] + ] +] + +[endsect] diff --git a/quickbook/reference/property_writer.qbk b/quickbook/reference/property_writer.qbk new file mode 100644 index 00000000..349f9908 --- /dev/null +++ b/quickbook/reference/property_writer.qbk @@ -0,0 +1,103 @@ +[/ + / Copyright (c) 2007 Andrew Sutton + / + / 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) + /] + +[section Property Writer] + + template + class property_writer; + +This is an [EventVisitor] that can be used to output the property of a vertex +or edge at some event-point within an algorithm. + +The [property_writer] class 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 `std::pair` to +form an [EventVisitorList]. + +[h4 Model Of] +[EventVisitor] + +[h4 Where Defined] +`boost/graph/visitors.hpp` + +[h4 Template Parameters] +[table + [[Parameter] [Description] [Default]] + [ + [`PropertyMap`] + [ + A [ReadablePropertyMap] where the `key_type` is of type `vertex_descriptor` + of `edge_descriptor` (depending on the event tag) and the `value_type` type is + of the property is convertible to the `value_type` of the `OutputIterator`. + ] + ] + [ + [`OutputIterator`] + [ + The iterator type used to write the property values must be a model of + [SgiOutputIterator]. + ] + ] + [ + [`EventTag`] + [ + A tag used to specify when the property writer should be applied during the graph + algorithm. + ] + ] +] + +[h4 Associated Types] +[table + [[Type] [Description]] + [ + [`property_writer::event_filter`] + [ + This type will be the same as the template parameter `EventTag`. + ] + ] +] + +[h4 Member Functions] +[table + [[Function] [Description]] + [ + [`property_writer(PropertyMap pa, OutputIterator out)`] + [Construct a property writer object with a property map `pa` and an output iterator `out`.] + ] + [ + [ +`` +template +void operator()(X x, const Graph& g) +`` + ] + [ + This writes the property value for `x` to the output iterator. Specifically, + `*out++ = get(pa, x)`. + ] + ] +] + +[h4 Non-Member Functions] +[table + [[Function] [Description]] + [ + [ +`` +template +time_stamper +stamp_times(Property pa, OutputIterator out, EventTag) +`` + ] + [ + A convenience function for creating [property_writer] instances. + ] + ] +] + +[endsect] diff --git a/quickbook/reference/reference.qbk b/quickbook/reference/reference.qbk new file mode 100644 index 00000000..82118cfd --- /dev/null +++ b/quickbook/reference/reference.qbk @@ -0,0 +1,79 @@ +[/ + / Copyright (c) 2007 Andrew Sutton + / + / 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) + /] + +[section Reference] + +[section Graph Types] +[include undirected_graph.qbk] +[include directed_graph.qbk] +[include adjacency_list.qbk] +[include edge_list.qbk] +[endsect] + +[section Traits Classes] +[include exterior_vertex_property.qbk] +[endsect] + +[section Event Visitor List Adaptors] +[include bfs_visitor.qbk] +[include dfs_visitor.qbk] +[include dijkstra_visitor.qbk] +[include bellman_visitor.qbk] +[include astar_visitor.qbk] +[endsect] + +[section Event Visitors] +[include predecessor_recorder.qbk] +[include distance_recorder.qbk] +[include time_stamper.qbk] +[include property_writer.qbk] +[endsect] + +[section Algorithms] + +[section Fundamental] +[include breadth_first_search.qbk] +[include depth_first_search.qbk] +[endsect] + +[section Connectivity] +[include connected_components.qbk] +[include strong_components.qbk] +[endsect] + +[section Shortest Paths] +[endsect] + +[section Minimum Spanning Tree] +[endsect] + +[section Subgraph] +[include tiernan_all_cycles.qbk] +[include bron_kerbosch_all_cliques.qbk] +[endsect] + +[section Maximum Flow] +[endsect] + +[section Sparse Matrix Ordering] +[endsect] + +[section Layout] +[endsect] + +[section Measures] +[include degree_centrality.qbk] +[include closeness_centrality.qbk] +[include betweenness_centrality.qbk] +[include mean_geodesic.qbk] +[include eccentricity.qbk] +[include clustering_coefficient.qbk] +[endsect] [/Measures] + +[endsect] [/Algorithms] + +[endsect] [/Reference] \ No newline at end of file diff --git a/quickbook/reference/strong_components.qbk b/quickbook/reference/strong_components.qbk new file mode 100644 index 00000000..55f23543 --- /dev/null +++ b/quickbook/reference/strong_components.qbk @@ -0,0 +1,116 @@ +[/ + / Copyright (c) 2007 Andrew Sutton + / + / 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) + /] + +[section Strongly Connected Components] + + template + typename property_traits::value_type + strong_components(const Graph &g, ComponentMap c, + const bgl_named_params& params = ``/defaults/``); + +The `strong_components()` functions compute the strongly connected components of a +directed graph using Tarjan's algorithm based on DFS \[41\]. + +The output of the algorithm is recorded in the component property map, which will +contain numbers giving the component number assigned to each vertex. This algorithm +returns the number of strongly connected components in the graph. + +[heading Where Defined] +`boost/graph/strong_components.hpp` + +[heading Parameters] +[table + [[Type] [Parameter] [Description]] + [ + [in] [`const Graph& g`] + [ + The /directed/ graph for which connected components are being found. + This graph must be a model of VertexListGraph and Incidence Graph. + ] + ] + [ + [out] [`ComponentMap c`] + [ + The algorithm computes how many connected components are in the graph, + and assigning each component an integer label. The algorithm then records + which component each vertex in the graph belongs to by recording the + component number in the component property map. The ComponentMap type + must be a model of WritablePropertyMap. The value type shouch be an + integer type, preferably the same as the `vertices_size_type` of the + graph. The key type must be the graph's `vertex_descriptor` type. + ] + ] +] + +[heading Named Parameters] +[table + [[Type] [Parameter] [Description]] + [ + [util] [`root_map(RootMap root_map)`] + [ + This is used by the algorithm to record the candidate root vertex for each + vertex. By the end of the algorithm, there is a single root vertex for each + component and `get(root_map, v)` returns the root vertex for whichever + component vertex `v` is a member. The `RootMap` must be a ReadWritePropertyMap, + where the key type and the value type are the vertex descriptor type of the + graph. + + *Default* An iterator_property_map created from a `std::vector` of + `vertex_descriptor`s of size `num_vertices(g)` and using the `index_map` + for accessing root vertices. + ] + ] + [ + [util] [`discover_time_map(TimeMap time_map)`] + [ + This is used by the algorithm to keep track of the DFS ordering of the vertices. + The `TimeMap` must be a model of ReadWritePropertyMap and its value type must + be an integer type. The key type must be the vertex descriptor type of the graph. + + *Default* An iterator_property_map created from a `std::vector` of integers + of size `num_vertices(g)` and using the `index_map` for accessing root vertices. + ] + ] + [ + [util] [`color_map(ColorMap color)`] + [ + This is used by the algorithm to keep track of its progress through the + graph. The type ColorMap must be a model of ReadWritePropertyMap and + its key type must be the graph's `vertex_descriptor` type and the value + type of the color map must model ColorValue. + + *Default* An `iterator_property_map` create from a `std::vector` of + `default_color_type` of size `num_vertices(g)` and using `index_map` as + the index map (to access colors for a vertex). + ] + ] + [ + [in] [`vertex_index_map(VertexIndexMap index_map)`] + [ + This maps each vertex to an integer in the range \[0, `num_vertices(g)`). + This parameter is only necessary when the default color property map is + used. The type VertexIndexMap must be a model of ReadablePropertyMap. The + value type of the map must be an integer type. The vertex descriptor type + of the graph needs to be usable as the key type of the map. + + *Default* `get(vertex_index, g)`. Note if you use this default, make sure + that your graph has an interior `vertex_index` property. For example + `adjacency_list` with `VertexList=listS` does not have an interior + `vertex_index` property. + ] + ] +] + +[heading Complexity] +This algorithm runs in /O(V + E)/. + +[heading Notes] +This algorithm will not compile if passed a /directed/ graph. + +[heading Examples] + +[endsect] \ No newline at end of file diff --git a/quickbook/reference/tiernan_all_cycles.qbk b/quickbook/reference/tiernan_all_cycles.qbk new file mode 100644 index 00000000..2d4a8963 --- /dev/null +++ b/quickbook/reference/tiernan_all_cycles.qbk @@ -0,0 +1,299 @@ +[/ + / Copyright (c) 2007 Andrew Sutton + / + / 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) + /] + +[section Tiernan All Cycles] +[template ex_tiernan_printing_cycles[] [link + boost_graph.reference.algorithms.subgraph.tiernan_all_cycles.examples.printing_cycles + Printing Cycles Example]] +[template ex_tiernan_girth_circumference[] [link + boost_graph.reference.algorithms.subgraph.tiernan_all_cycles.examples.girth_and_circumference + Girth and Circumference Example]] + +[heading Overview] +This function uses the Tiernan algorithm to find all /cycles/ within a given graph, +invoking a visitor when each cycle is found. A cycle is a path (a sequence of +connected vertices) within a graph, and whose tail (the last vertex in the path) +is connected to its head (the first vertex in the path). + +Consider the directed graph in Figure 1. + +[figure + images/reference/prism_3_2.png + *Figure 1.* A directed graph. +] + +This graph has 11 distinct cycles. Some of the more obvious are: + +* 0, 1, 2 +* 3, 4, 5 +* 0, 3 +* 1, 4 +* 2, 5 + +For more details see the [ex_tiernan_printing_cycles]. + +The order in which cycles are visited is determined by the algorithm. It iterates +over each vertex in the order of its vertex indices. The algorithm identifies cycles +by first finding long paths and determining if they form cycles. Once the paths +have been examined, the algorithm backtracks along the path searching for alternate +cycles. The result (as shown in the output of the [ex_tiernan_printing_cycles]) is a +listing that visits longer cycles first in the lexicographical order of vertex +indices. Note that the order of visitation does /not/ imply anything about the +relative importance of the cycle within the graph. + +The Tiernan algorithm is designed to work on directed graphs, but works for undirected +graphs as well. When running on undirected graphs, however, the algorithm treats each +edge connecting two vertices /(u,v)/ as if it were two distinct edges /(u,v)/ and +/(v,u)/. As result the algorithm will report cycles in both directions. Consider the +following undirected graph in Figure 2. + +[figure + images/reference/triangle.png + *Figure 2.* An undirected triangle. +] + +If the Tiernan algorithm is run on this graph, it will visit the paths 0, 1, 2 and +0, 2, 1. + +There are two properties of a graph that are derived from knowing a graphs cycles: +/girth/ and /circumference/. The girth of a graph is defined as the minimum-length +cycle in the graph, and the circumference is defined as the largest-length cycle. +This module provides functions for computing these values using Tiernan's algorithm. +See the [ex_tiernan_girth_circumference] for details. + +[section [^tiernan_all_cycles()]] + #include + + template + void tiernan_all_cycles(const Graph& g, Visitor vis) + + template + void tiernan_all_cycles(const Graph& g, Visitor vis, std::size_t max) + + template + void tiernan_all_cycles(const Graph& g, Visitor vis, std::size_t min, std::size_t max) + +The `tiernan_all_cycles()` function visits all cycles in a graph. There are three +variants of this algorithm. The first will simply find and visit all cycles in the +target graph. The second variant allows the caller to specify an upper bound to the +length of cycles visited, and the third variant allows the user to specify both +upper and lower bounds on the lengths of paths being visited. The minimum cycle +length must be at least two. + +Note that the default minimum cycle length differs between directed and undirected +graphs. For directed graphs, the algorithm allows the discovery and visitation +of length-two cycles. For undirected graphs, the default minimum cycle length is +three. This prevents the algorithm from visiting every pair of connected vertices +in an undirected graph as a cycle. + +[heading Parameters] +[table + [[Type] [Parameter] [Description]] + [ + [required, in] [`const Graph& g`] + [ + The graph for which cliques are being visited. + + *Requirements:* The `Graph` type must be a model of the + [IncidenceGraph] and [VertexIndexGraph] concepts. + ] + ] + [ + [required, in] [`Visitor vis`] + [ + The visitor object to the algorithm. + + *Requirements:* This `Visitor` class must model the + [CliqueVisitor] class. + ] + ] + [ + [optional, in] [`std::size_t max`] + [ + The maximum-length path that will be visited by the algorithm. + + *Default:* `std::numeric_limits::max()`. + ] + ] + [ + [optional, in] [`std::size_t min`] + [ + The minimum-length path that will be visited by the algorithm. The + default minimum length path is determined by the type of graph. + + *Precondition:* `min >= 2` + + *Default:* If `Graph` is directed, this value defaults to 2. Otherwise + the default value is 3. + ] + ] +] + +[heading Complexity] +This function has a (loose) upper bound of ['O(2[super n])] where /n/ is the +number of vertices a graph. This bound is derived from the powerset of vertices +in /g/ and does not account for the vertex of origin or directionality of edges +connecting vertices in a path. If one considers the paths in a triangle {1, 2, 3} +and {3, 2, 1} to be distinct cycles within a graph, then this bound can potentially +be much greater. From a practical standpoint, it is unlikely that real graphs will +ever approach a number of paths remotely close to this number. + +This function requires ['O(n[super 2])] space where /n/ is the number of vertices +in a graph. +[endsect] + +[section [^tiernan_girth()]] + #include + + template + std::size_t tiernan_girth(const Graph& g) + +Comptutes the girth (the minimum length cycle) of the graph `g` by visiting all +cycles using Tiernan's algorithm. If the graph is acyclic, it has no cycles and +an infinite girth. If computing both girth and circumference, use the +[tiernan_girth_and_circumference] function since this computation can be fairly +time consuming. + +[heading Parameters] +[table + [[Type] [Parameter] [Description]] + [ + [required, in] [`const Graph& g`] + [ + The graph for which the girth is computed. + + *Requirements:* The `Graph` type must be a model of the + [IncidenceGraph] and [VertexIndexGraph] concepts. + ] + ] +] + +[heading Return] +The `tiernan_girth()` function returns the girth of the given graph. + +[heading Complexity] +The `tiernan_girth()` function has the same time complexity as the [tiernan_all_cycles] +function. +[endsect] + +[section [^tiernan_circumference()]] + #include + + template + std::size_t tiernan_circumference(const Graph& g) + +Comptutes the circumference (the maximum length cycle) of the graph `g` by visiting all +cycles using Tiernan's algorithm. If the graph is acyclic, it has no cycles and an +infinite circumference. If computing both girth and circumference, use the +[tiernan_girth_and_circumference] function since this computation can be fairly +time consuming. + +[heading Parameters] +[table + [[Type] [Parameter] [Description]] + [ + [required, in] [`const Graph& g`] + [ + The graph for which the circumference is being computed. + + *Requirements:* The `Graph` type must be a model of the + [IncidenceGraph] and [VertexIndexGraph] concepts. + ] + ] +] + +[heading Return] +The `tiernan_circumference()` function returns the girth of the given graph. + +[heading Complexity] +The `tiernan_circumference()` function has the same time complexity as the +[tiernan_all_cycles] function. +[endsect] + +[section [^tiernan_girth_and_circumference()]] + #include + + template + std::pair + tiernan_girth_and_circumference(const Graph& g) + +Comptutes the both the girth (minimum length cycle) and circumference (maximum length +cycle) of the graph `g` by visiting all cycles using Tiernan's algorithm. If the +graph is acyclic, it has no cycles and both girth and cicumference are infinite. + +[heading Parameters] +[table + [[Type] [Parameter] [Description]] + [ + [required, in] [`const Graph& g`] + [ + The graph for which the girth and circumference are being computed. + + *Preconditions:* The indices of vertices in the graph must be + in the range... + + *Requirements:* The `Graph` type must be a model of the + [IncidenceGraph] and [VertexIndexGraph] concepts. + ] + ] +] + +[heading Return] +The `tiernan_girth_and_circumference()` function returns the girth of the given graph. + +[heading Complexity] +The `tiernan_girth_and_circumference()` function has the same time complexity as the +[tiernan_all_cycles] function. +[endsect] + +[section Examples] +[heading Printing Cycles] +This example demonstrates the construction of a cycle visitor and its use with +the `tiernan_all_cycles()` function. This file includes the following files: + +* [^examples/tiernan_print_cycles.cpp] +* [^examples/helper.hpp] + +[tiernan_print_cycles] + +If this program is given the `prism_3_2.graph` file as input, it will print all +the cycles in the graph shown in Figure 1. + +[pre +0 1 2 5 3 +0 1 2 +0 1 4 5 3 +0 1 4 5 2 +0 3 4 5 2 +0 3 4 1 2 +0 3 +1 2 5 3 4 +1 4 +2 5 +3 4 5 +] + +[heading Girth and Circumference] +This example demonstrates the use of Tiernan's algorithm to compute the girth +and circumference of a directed graph. This example includes the following files: + +* [^examples/tiernan_girth_circumference.cpp] +* [^examples/helper.hpp] + +[tiernan_girth_circumference] + +If this program is given the `prism_3_2.graph` file as input, it will print the +following output: + +[pre +girth: 2 +circumference: 5 +] + +[endsect] + +[endsect] \ No newline at end of file diff --git a/quickbook/reference/time_stamper.qbk b/quickbook/reference/time_stamper.qbk new file mode 100644 index 00000000..1895a544 --- /dev/null +++ b/quickbook/reference/time_stamper.qbk @@ -0,0 +1,104 @@ +[/ + / Copyright (c) 2007 Andrew Sutton + / + / 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) + /] + +[section Time Stamper] + + template + class time_stamper; + +This is an [EventVisitor] that can be used to "stamp" a time at some event-point +within an algorithm. An example of this is recording the discover or finish time of +a vertex during a graph search. + +The [time_stamper] class 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 `std::pair` to +form an [EventVisitorList]. + +[h4 Model Of] +[EventVisitor] + +[h4 Where Defined] +`boost/graph/visitors.hpp` + +[h4 Template Parameters] +[table + [[Parameter] [Description] [Default]] + [ + [`TimeMap`] + [ + A [WritablePropertyMap] where the key type is of type `vertex_descriptor` + of `edge_descriptor` (depending on the event tag) and `TimeT` must be convertible + to the value type. + ] + ] + [ + [`TimeT`] + [ + The type of the time counter, which should be convertible to the `value_type` of + TimeMap. + ] + ] + [ + [`EventTag`] + [ + A tag used to specify when the time stamper should be applied during the graph + algorithm. + ] + ] +] + +[h4 Associated Types] +[table + [[Type] [Description]] + [ + [`time_stamper::event_filter`] + [ + This type will be the same as the template parameter `EventTag`. + ] + ] +] + +[h4 Member Functions] +[table + [[Function] [Description]] + [ + [`time_stamper(Timemap pa, TimeT& t)`] + [Construct a time stamper object with a timestamp property map `pa` and time counter `t`.] + ] + [ + [ +`` +template +void operator()(X x, const Graph& g) +`` + ] + [ + This records the current timestamp for the edge or vertex in the property map + and increments the time count. + ] + ] +] + +[h4 Non-Member Functions] +[table + [[Function] [Description]] + [ + [ +`` +template +time_stamper +stamp_times(TimeMap pa, TimeT& t, EventTag) +`` + ] + [ + A convenience function for creating [time_stamper] instances. + ] + ] +] + +[endsect] diff --git a/quickbook/reference/undirected_graph.qbk b/quickbook/reference/undirected_graph.qbk new file mode 100644 index 00000000..b9cc6082 --- /dev/null +++ b/quickbook/reference/undirected_graph.qbk @@ -0,0 +1,743 @@ +[/ + / Copyright (c) 2007 Andrew Sutton + / + / 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) + /] + +[section Undirected Graph] + + template + class undirected_graph; + +This section provides detailed information about the `undirected_graph` class, +its associated types, member functions and non-member interface. An undirected graph +is one in which edges have no direction - this is to say that edges can be "traveled" +in both directions. This class provides general purpose implementation of undirected +graphs and can be used with algorithms in the Boost Graph Library. + +[h4 Notation] +The following notation is used in this documentation. The following type names +are generally meant to mean the following: + +[table + [[Used Type] [Actual Type]] + [ + [`undirected_graph`] + [ + `undirected_graph` where `VP`, `EP` and `GP` are template + arguments that correspond to user-defined or default verex properties, + edge properties, and graph properties. + ] + ] + [ + [`vertex_descriptor`] + [`undirected_graph::vertex_descriptor`] + ] + [ + [`edge_descriptor`] + [`undirected_graph::edge_descriptor`] + ] + [ + [`vertex_iterator`] + [`undirected_graph::vertex_iterator`] + ] + [ + [`edge_iterator`] + [`undirected_graph::edge_iterator`] + ] +] + +Moreover, objects with the following names are generally expected to have the +following types. + +[table + [[Object Name] [Type]] + [[`g`] [`undirected_graph`]] + [[`u`, `v`] [`vertex_descriptor`]] + [[`e`] [`edge_descriptor`]] + [[`i`] [`vertex_iterator` or `edge_iterator`]] + [[`p`] [A property tag (usually a template parameter)]] + [[`d`] [A vertex or edge descriptor (usually a template parameter)]] + [[`v`] [The value of a property (usually a template parameter)]] +] + +[h4 Descriptor and Iterator Stability] +With the `undirected_graph` class, descriptors and iterators remain stable after +all operations except descriptors and iterators referencing the vertices and edges +that have been removed. Removing a vertex or edge will not invalidate descriptors +and iterators to other vertices or edges. + +For example, consider the following code: + + undirected_graph<> g; + undirected_graph<>::vertex_descriptor u = add_vertex(g); + undirected_graph<>::vertex_descriptor v = add_vertex(g); + undirected_graph<>::vertex_descriptor w = add_vertex(g); + remove_vertex(u); + add_edge(v, w, g); + +After running this program, the descriptor `u` will be invalid but `v` and `w` will +still be valid so the call to `add_edge(v,w,g)` is also valid. Note that this +property does not hold for all graph types. + +[h4 Vertex Indexing and Stability] +The `undirected_graph` class provides a built-in internal properties for vertex +types, and will provide semi-automated index management. Algorithms that use vertex +indices generally assume that they are in the range \[0, `num_vertices(g)`). With +the `undirected_graph` class vertex indices will be in this continuous range until +a vertex is removed from the graph. This is the only operation that invalidates +vertex indices, but the vertices will need to be renumbered using the +`renumber_vertex_indices(g)` function. + +The `remove_vertex_and_renumber_indices(vi,g)` function can be used to autmoatically +renumber indices after removing the vertex referenced by the given iterator. Because +this function runs in linear time, it should not be used for repeated removals. + +[h4 Function Names for Directed and Undirected Graphs] +Many of the operations in the Boost Graph library are named in accordance +with the concepts of directed graphs, specifically the use of out-edges as the +canonical adjacencty list for vertices. As a result, undirected graphs also +use the out-edge terminology to refern to its incident edges, but in-edge operations +are identical in behavior to out-edge operations. + +There are three sets of operations that have multiple names and duplicate behaviors: +`*degree()`-computing functions, `*_edge()`-iterating accessors, and the `remove_*_edge()` +predicate-based functions. These functions are grouped together in their reference +sections. + +This class also introduces two new functions, `incident_edges(g)` that returns an +iterator range to the incident edges of `g`, and `remove_incident_edges_if(v,p,g)`. +These are identical in behavior to their `in` and `out` counterparts. These +functions are only provided for semantic consistency so developers should be aware +that these new functions are /not/ defined for any other graph classes in the +Boost Graph Library. + +Developers of generic algoriths should be aware that, when generalizing an algorithm +for both directed and undirected graphs, it is better to use the `out_degree(g)` +function to access out-edges since it is guaranteed by every other graph class. + +[h5 Model Of] +[IncidenceGraph], [VertexListGraph], [EdgeListGraph], [AdjacencyGraph], +[MutableGraph], and [PropertyGraph]. + +[h4 Template Parameters] +There are only three parameters to the `undirected_graph` class. +[table + [[Parameter] [Description] [Default]] + [ + [`VertexProperties`] + [Specifies internal properties for vertices of the graph.] + [`no_property`] + ] + [ + [`EdgeProperties`] + [Specifies internal properties for edges of the graph.] + [`no_property`] + ] + [ + [`GraphProperties`] + [Specifies internal properties for the graph itself.] + [`no_property`] + ] +] + +Additionally, the `undirected_graph` class provides a non-constant time implementation +of the [AdjacencyMatrix] associated function `edge(u,v,g)`, but does not model +the concept. + +[h4 Where Defined] +`boost/graph/undirected_graph.hpp` + +[h4 Associated Types] +There are a number of useful types associated with the `undirected_graph` class. +Most of these are accessed through `graph_traits` or other template classes. +For convenience these types have been grouped by purpose. + +[h5 Descriptor Types] +[table + [[Type] [Description]] + [ + [`graph_traits::vertex_descriptor`] + [ + The type for the vertex descriptors associated with the graph. The `vertex_descriptor` + models the [Descriptor] and [NoConcept Hashable] concepts. + ] + ] + [ + [`graph_traits::edge_descriptor`] + [ + The type for the edge descriptors associated with the graph. The `edge_descriptor` + models the [Descriptor] and [NoConcept Hashable] concepts. + ] + ] +] + +Note that edge and vertex descriptors for the `unsigned_graph` can be used as keys for both +[SgiSortedAssociativeContainer]s and [SgiHashedAssociativeContainer]s such as `std::map` and +`std::tr1::unordered_map` respectively. + +[h5 Iterator Types] +[table + [[Type] [Description]] + [ + [`graph_traits::vertex_iterator`] + [ + The type for iterators returned by `vertices()`. Verex iterators are + models of the [SgiBidirectionalIterator] concept. + ] + ] + [ + [`graph_traits::edge_iterator`] + [ + The type for iterators returned by `edges()`. Edge iterators are + models of the [SgiBidirectionalIterator] concept. + ] + ] + [ + [`graph_traits::out_edge_iterator`] + [ + The type for iterators returned by `out_edges()`. Out-edge iterators + are models of the [SgiBidirectionalIterator] concept. + ] + ] + [ + [`graph_traits::in_edge_iterator`] + [ + The type for iterators returned by `in_edges()`. In-edge iterators + are models of the [SgiBidirectionalIterator] concept. + ] + ] + [ + [`graph_traits::adjacency_iterator`] + [ + The type for iterators returned by `adjacent_vertices`. Adjacency + iterators are models of the [SgiBidirectionalIterator] concept. + ] + ] +] + +[h5 Miscellaneous Types] +[table + [[Type] [Description]] + [ + [`graph_traits::vertices_size_type`] + [The type used for dealing with the number of vertices in the graph.] + ] + [ + [`graph_traits::edge_size_type`] + [The type used for dealing with the number of edges in the graph.] + ] + [ + [`graph_traits::degree_size_type`] + [The type used for dealing with the number of edges incident to a vertex in the graph.] + ] + [ + [`undirected_graph::vertex_index_type`] + [The integral type representing vertex indices (generally `unsigned int`).] + ] + [ + [ + `property_map::type` + + `property_map::const_type` + ] + [ + The property map type for vertex or edge properties in the graph. The specific + property is specified by the `Property` template argument, and must match one of + the properties specified in the `VertexProperties` or `EdgeProperties` for the + graph. + ] + ] + [ + [`graph_property::type`] + [ + The value type for the graph property specified by the `Property` parameter. + `Property` must be one of the types in the `GraphProperties` template argument. + ] + ] + [ + [`graph_traits::directed_category`] + [ + This is always `undirectedS`, indicating that the graph supports operations + for undirected graphs. + ] + ] + [ + [`graph_traits::edge_parallel_category`] + [ + This is always `allow_parallel_edges_tag`, indicating that multiple edges + may be added between two vertices (i.e., graphs can be /multigraphs/). + ] + ] +] + +[h4 Member Functions] +[table + [[Function] [Description]] + [ + [`undirected_graph(const GraphProperties& p = GraphProperties()`] + [The default constructor creates a graph with no vertices or edges.] + ] + [ + [`undirected_graph(const undirected_graph& x`)] + [The copy constructor creates a copy of the given graph `x`.] + ] + [ + [ +`` +undirected_graph(vertices_size_type n, + const GraphProperties& p = GraphProperties()) +`` + ] + [The default constructor creates a graph with `n` vertices and no edges.] + ] + [ + [`undirected_graph& operator =(const undirected_graph& x)`] + [Copies the edges and vertices of the graph `x`.] + ] +] + +[h4 Non-member Functions] +[h5 Non-member Accessors] +[table + [[Function] [Description]] + [ + [ +`` +std::pair +vertices(const undirected_graph& g) +`` + ] + [Returns an iterator range providing access to the vertex list of `g`.] + ] + [ + [ +`` +std::pair +edges(const undirected_graph& g) +`` + ] + [Returns an iterator range providing access to the edge list of `g`.] + ] + [ + [ +`` +std::pair +incident_edges(vertex_descriptor v, const undirected_graph& g) +`` + +`` +std::pair +out_edges(vertex_descriptor v, const undirected_graph& g) +`` + +`` +std::pair +in_edges(vertex_descriptor v, const undirected_graph& g) +`` + ] + [ + Returns an iterator range providing access to the incident edges + of the vertex `v`. Because `g` is an undirected graph, these three + functions are guaranteed to return identical iterator ranges. + ] + ] + [ + [ +`` +std::pair +adjacent_vertices(vertex_descriptor v, + const undirected_graph& g) +`` + ] + [ + Returns an iterator range providing access to the adjacenct vertices + of vertex `v` in the graph `g`. Note that this is functionally + equivalent to iterating over the targets of all incident edges of `v`. + ] + ] + [ + [ +`` +vertices_size_type +num_vertices(const undirected_graph& g) +`` + ] + [Returns the number of vertices in the graph `g`.] + ] + [ + [ +`` +edge_size_type +num_edges(const undirected_graph& g) +`` + ] + [Returns the number of edges the graph `g`.] + ] + [ + [ +`` +degree_size_type +degree(vertex_descriptor v, + const undirected_graph& g) +`` + +`` +degree_size_type +out_degree(vertex_descriptor v, + const undirected_graph& g) +`` + +`` +degree_size_type +in_degree(vertex_descriptor v, + const undirected_graph& g) +`` + ] + [ + Returns the degree of the vertex `v`, which is the number of + edges incident to it. Because `g` is undirected, all three + functions return equal values. + ] + ] + [ + [ +`` +vertex_descriptor +vertex(vertices_size_type n + const undirected_graph& g) +`` + ] + [ + Returns the /nth/ vertex in the graph `g`. With undirected graphs, + this method is /O(n)/. As such its use with this type of graph is + discouraged. + ] + ] + [ + [ +`` +std::pair +edge(vertex_descriptor u, + vertex_descriptor v, + const undirected_graph& g) +`` + ] + [ + If the edge (`u`,`v`) is in `g`, then this function returns the + descriptor for the edge connecting `u` and `v` with boolean value + set to `true`. Otherwise, the boolean value is `false` and the + edge descriptor is invalid. + ] + ] + [ + [ +`` +vertex_size_type +get_vertex_index(vertex_descriptor v, + const undirected_graph& g) +`` + ] + [ + Returns the vertex index of the given vertex descriptor v. Note + that indices are /not/ required to be in the range \[0, `num_vertices(g)`). + This function is an alias for `get(vertex_index,g,v)`. + ] + ] + [ + [ +`` +vertex_size_type +max_vertex_index(vertex_descriptor v, + const undirected_graph& g) +`` + ] + [ + Returns the vertex index of the given vertex descriptor v. Note + that indices are /not/ required to be in the range \[0, `num_vertices(g)`). + This function is an alias for `get(vertex_index,g,v)`. + ] + ] +] + +[h5 Non-member Modifiers] +[table + [[Function] [Description]] + [ + [ +`` +vertex_descriptor +add_vertex(undirected_graph& g) +`` + ] + [Adds a vertex to `g` and returns a descriptors for the new vertex.] + ] + [ + [ +`` +void +clear_vertex(vertex_descriptor v, + undirected_graph& g) +`` + ] + [ + Removes all in- and out-edges of `v`, but leaves `v` in the graph `g`. + This is functioanlly equivalent to invoking `remove_edge()` on all + in- or out-edges of `v`, potentially invalidating descriptors and + iterators. + ] + ] + [ + [ +`` +vertex_descriptor +remove_vertex(vertex_descriptor v, + undirected_graph& g) +`` + ] + [ + Removes vertex `v` from the graph `g`. It is assumed that `v` has no + incident edges before removal. To ensure this is, call `clear_vertex(v, g)` + before removing it. + + Assuming that the vertex indices were in the range \[0, `num_vertices(g)`) + before calling this method, this operation will invalidate all vertex indices + in the range (vertex_index(v, g), `num_vertices(g)`), requiring indices to + be renumbered using the `renumber_vertex_indices(g)` method. If possible, + prefer to remove groups of vertices at one time before renumbering since + renumbering is a /O(n)/ time operation. + ] + ] + [ + [ +`` +void +remove_vertex_and_renumber_indices(vertex_iterator i, + undirected_graph& g) +`` + ] + [ + Removes the vertex indicated by the iterator `i` from the graph `g`. Like + the `remove_vertex(v,g)` function, it is expected that `*i` have no + incident edges at the time of removal. + + As indicated by the name, this method will also renumber vertex indices + after the removal of `*i`. This operation iterates over vertices after + `i`, decrementing their index by 1. If your program removes several + vertices at once, prefer to call several `remove_vertex(v,g)` methods, + followed by `renumber_vertices(g)` before using `g` in an algorithm. + ] + ] + [ + [ +`` +void +renumber_vertex_indices(undirected_graph& g) +`` + ] + [ + Renumbers all interior vertex indices such that each vertex has an index + in the range \[0, `num_vertices(g)`). Generally, this function needs to + be called after removing vertices and before invoking graph algorithms. + ] + ] + [ + [ +`` +std::pair +add_edge(vertex_descriptor u, + vertex_descriptor v, + undirected_graph& g) +`` + ] + [ + Adds the edge /(u,v)/ to the graph and returns a descriptor for the new + edge. For `undirected_graph`s, the boolean value of the pair will always + be true. + ] + ] + [ + [ +`` +void +remove_edge(vertex_descriptor u, + vertex_descriptor v, + undirected_graph& g) +`` + ] + [ + Removes the edge /(u,v)/ from the graph. This operation invalidates any + descriptors or iterators referencing the edge. Note that `u` and `v` must + be valid descriptors and /(u,v)/ must be in the graph. If `g` is a multigraph + (with multiple edges between /(u,v)/, this mehtod will cause the removal of + all such edges connecting `u` and `v`. + ] + ] + [ + [ +`` +void +remove_edge(edge_descriptor e, + undirected_graph& g) +`` + ] + [ + Removes the edge `e` from the graph. If multuple edges exist from + (`source(e,g)`, `target(e,g)`), then this method will remove only + the single, specified edge. + ] + ] + [ + [ +`` +void +remove_edge(out_edge_iterator i, + undirected_graph& g) +`` + ] + [ + This is functionally equivalent to `remove_edge(*i, g)`. + ] + ] + [ + [ +`` +template void +remove_edge_if(Predicate p, undirected_graph& g) +`` + ] + [ + Removes all edges from the graph that satisfy `predicate`. That is, if + `p()` returns true when applied to an edge, then that edge is removed. + The affect on descriptor and iterator is the same as that of invoking + `remove_edge()` for on each of the removed vertices. + ] + ] + [ + [ +`` +template void +remove_incident_edge_if(vertex_descriptor v, Predicate p + undirected_graph& g) +`` + +`` +template void +remove_out_edge_if(vertex_descriptor v, Predicate p, + undirected_graph& g) +`` + +`` +template void +remove_in_edge_if(vertex_descriptor v, Predicate p, + undirected_graph& g) +`` + ] + [ + Removes all edges incident-edges from vertex`v` that satisfy `predicate`. + That is, if `p()` returns true when applied to an edge, then that edge + is removed. The affect on descriptor and iterator is the same as that + of invoking `remove_edge()` for on each of the removed vertices. + + Because this graph is undirected, these three funtions are identical + in behavior and run time. + ] + ] +] + +[h5 Proprety Map Acessors] +[table + [[Function] [Description]] + [ + [ +`` +template +property_map::type +get(Property, + const undirected_graph& g) +`` + ] + [ + Returns the property map object for the vertex property specified by the + type `Property`. This type must match one of the properties specified in + the `VertexProperties` template argument. + ] + ] + [ + [ +`` +template +typename + property_traits< + property_map::const_type + >::value_type +get(Property, + const undirected_graph& g, + Descriptor d) +`` + ] + [ + Returns the property value specified by the type `Property` for either + the `vertex_descriptor` or `edge_descriptor` denoted by `d`. + ] + ] + [ + [ +`` +template +void +put(Property, + const undirected_graph& g, + Descriptor d, + Value v) +`` + ] + [ + Sets the property value denoted by the type `Property` for either edge + or vertex descriptor `d` to the given value `v`. + ] + ] + [ + [ +`` +template +typename graph_property::type& +get_property(undirected_graph& g, GraphProperty) +`` + +`` +template +const typename graph_property::type& +get_property(const undirected_graph& g, GraphProperty) +`` + ] + [ + Returns the graph property specified by the type `GraphProperty` for + the graph `g`. Here, GraphProperty must be one of the properties + in the `GraphProperties` template argument. + ] + ] + [ + [ +`` +template +void +set_property(const undirected_graph& g, GraphProperty, Value v) +`` + ] + [ + Sets the graph proeprty specified by the type `GraphProperty` to + the given value `v`. Note that `GraphProperty` must be one of + the properties in the `GraphProperties` template argument. + ] + ] +] + +[h4 Rationale] +Unlike most graph classes in Boost.Graph, the `undirected_graph` does not model the +[MutablePropertyGraph] concept. The reason for this is that it is relatively +difficult (from a usability standpoint) to easily deduce the type to be passed as a +property when adding vertices and edges - but especially vertices. + +[endsect] \ No newline at end of file diff --git a/quickbook/sgi_concepts.qbk b/quickbook/sgi_concepts.qbk new file mode 100644 index 00000000..adb20233 --- /dev/null +++ b/quickbook/sgi_concepts.qbk @@ -0,0 +1,41 @@ +[/ + / Copyright (C) 2007-2009 Andrew Sutton + / + / 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 file defines templates that expand to links to the STL concepts. /] + +[/ Missing documentation /] +[template NoConcept[x] [^[x]]] + +[template SgiAssignable[] [@http://www.sgi.com/tech/stl/Assignable.html Assignable]] +[template SgiDefaultConstructible[] [@http://www.sgi.com/tech/stl/DefaultConstructible.html DefaultConstructible]] +[template SgiCopyConstructible[] [@http://www.sgi.com/tech/stl/CopyConstructible.html CopyConstructible]] +[template SgiEqualityComparable[] [@http://www.sgi.com/tech/stl/EqualityComparable.html EqualityComparable]] +[template SgiLessThanComparable[] [@http://www.sgi.com/tech/stl/LessThanComparable.html LessThanComparable]] + +[template SgiContainer[] [@http://www.sgi.com/tech/stl/Container.html Container]] +[template SgiForwardContainer[] [@http://www.sgi.com/tech/stl/ForwardContainer.html ForwardContainer]] +[template SgiReversibleContainer[] [@http://www.sgi.com/tech/stl/ReversibleContainer.html ReversibleContainer]] +[template SgiRandomAccessContainer[] [@http://www.sgi.com/tech/stl/RandomAccessContainer.html RandomAccessContainer]] + +[template SgiSequence[] [@http://www.sgi.com/tech/stl/Sequence.html Sequence]] +[template SgiFrontInsertionSequence[] [@http://www.sgi.com/tech/stl/FrontInsertionSequence.html FrontInsertionSequence]] +[template SgiBackInsertionSequence[] [@http://www.sgi.com/tech/stl/BackInsertionSequence.html BackInsertionSequence]] + +[template SgiAssociativeContainer[] [@http://www.sgi.com/tech/stl/AssociativeContainer.html AssociativeContainer]] +[template SgiSortedAssociativeContainer[] [@http://www.sgi.com/tech/stl/SortedAssociativeContainer.html SortedAssociativeContainer]] +[template SgiHashedAssociativeContainer[] [@http://www.sgi.com/tech/stl/HashedAssociativeContainer.html HashedAssociativeContainer]] + +[template SgiInputIterator[] [@http://www.sgi.com/tech/stl/InputIterator.html BidirectionalIterator]] +[template SgiOutputIterator[] [@http://www.sgi.com/tech/stl/OutputIterator.html OutputIterator]] +[template SgiForwardIterator[] [@http://www.sgi.com/tech/stl/ForwardIterator.html ForwardIterator]] +[template SgiBidirectionalIterator[] [@http://www.sgi.com/tech/stl/BidirectionalIterator.html BidirectionalIterator]] +[template SgiRandomAccessIterator[] [@http://www.sgi.com/tech/stl/RandomAccessIterator.html RandomAccessIterator]] + +[template SgiPredicate[] [@http://www.sgi.com/tech/stl/Predicate.html Predicate]] +[template SgiMonoid[] [@http://www.sgi.com/tech/stl/Monoid.html Monoid]] + +[template StdIndexable[] [link boostgraph [^Indexable]]] diff --git a/quickbook/theory.qbk b/quickbook/theory.qbk new file mode 100644 index 00000000..429d778d --- /dev/null +++ b/quickbook/theory.qbk @@ -0,0 +1,252 @@ +[/ + / Copyright (c) 2007 Andrew Sutton + / + / 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) + /] + +[section Review of Elementary Graph Theory] +This chapter is meant as a refresher on elementary graph theory. If the reader has some previous +acquaintance with graph algorithms, this chapter should be enough to get started. If the reader +has no previous background in graph algorithms we suggest a more thorough introduction such as +/Introduction to Algorithms/ by Cormen, Leiserson, and Rivest. + +[h2 The Graph Abstraction] +A graph is a mathematical abstraction that is useful for solving many kinds of problems. Fundamentally, +a graph consists of a set of vertices, and a set of edges, where an edge is something that connects two +vertices in the graph. More precisely, a graph is a pair (V,E), where V is a finite set and E is a binary +relation on V. V is called a vertex set whose elements are called vertices. E is a collection of edges, +where an edge is a pair (u,v) with u,v in V. In a directed graph, edges are ordered pairs, connecting a +source vertex to a target vertex. In an undirected graph edges are unordered pairs and connect the two +vertices in both directions, hence in an undirected graph (u,v) and (v,u) are two ways of writing the same +edge. + +This definition of a graph is vague in certain respects; it does not say what a vertex or edge represents. +They could be cities with connecting roads, or web-pages with hyperlinks. These details are left out of +the definition of a graph for an important reason; they are not a necessary part of the graph abstraction. +By leaving out the details we can construct a theory that is reusable, that can help us solve lots of +different kinds of problems. + +Back to the definition: a graph is a set of vertices and edges. For purposes of demonstration, let us +consider a graph where we have labeled the vertices with letters, and we write an edge simply as a pair +of letters. Now we can write down an example of a directed graph as follows: + + G = (V, E) + V = {v, b, x, z, a, y } + E = { (b,y), (b,y), (y,v), (z,a), (x,x), (b,x), (x,v), (a,z) } + +Figure 1 gives a pictorial view of this graph. The edge (x,x) is called a self-loop. Edges (b,y) and (b,y) +are parallel edges, which are allowed in a multigraph (but are normally not allowed in a directed or +undirected graph). + +[$../images/review_figure_1.png] + +Next we have a similar graph, though this time it is undirected. Figure 2 gives the pictorial view. +Self loops are not allowed in undirected graphs. This graph is the undirected version(b,y)), meaning it +has the same vertices and the same edges with their directions removed. Also the self edge has been +removed, and edges such as (a,z) and (z,a) are collapsed into one edge. One can go the other way, +and make a directed version of an undirected graph be replacing each edge by two edges, one pointing +in each direction. + + G = (V, E) + V = {v, b, x, z, a, y } + E = { (b,y), (y,v), (z,a), (b,x), (x,v) } + +[$../images/review_figure_2.png] + +Now for some more graph terminology. If some edge (u,v) is in graph , then vertex v is adjacent to vertex u. +In a directed graph, edge (u,v) is an out-edge of vertex u and an in-edge of vertex v. In an undirected graph +edge (u,v) is incident on vertices u and v. + +In Figure 1, vertex y is adjacent to vertex b (but b is not adjacent to y). The edge (b,y) is an out-edge +of b and an in-edge of y. In Figure 2, y is adjacent to b and vice-versa. The edge (y,b) is incident on +vertices y and b. + +In a directed graph, the number of out-edges of a vertex is its out-degree and the number of in-edges is +its in-degree. For an undirected graph, the number of edges incident to a vertex is its degree. In Figure 1, +vertex b has an out-degree of 3 and an in-degree of zero. In Figure 2, vertex b simply has a degree of 2. + +Now a path is a sequence of edges in a graph such that the target vertex of each edge is the source vertex +of the next edge in the sequence. If there is a path starting at vertex u and ending at vertex v we say +that v is reachable from u. A path is simple if none of the vertices in the sequence are repeated. The +path <(b,x), (x,v)> is simple, while the path <(a,z), (z,a)> is not. Also, the path <(a,z), (z,a)> is called +a cycle because the first and last vertex in the path are the same. A graph with no cycles is acyclic. + +A planar graph is a graph that can be drawn on a plane without any of the edges crossing over each other. +Such a drawing is called a plane graph. A face of a plane graph is a connected region of the plane +surrounded by edges. An important property of planar graphs is that the number of faces, edges, and +vertices are related through Euler's formula: |F| - |E| + |V| = 2. This means that a simple planar graph +has at most O(|V|) edges. + +[h2 Graph Data Structures] +The primary property of a graph to consider when deciding which data structure to use is sparsity - the +number of edges relative to the number of vertices in the graph. A graph where E is close to V2 is a +/dense graph/, whereas a graph where E = alpha V and alpha is much smaller than V is a /sparse graph/. For +dense graphs, the adjacency-matrix representation is usually the best choice, whereas for sparse graphs +the adjacency-list representation is a better choice. Also the edge-list representation is a space efficient +choice for sparse graphs that is appropriate in some situations. + +[h3 Adjacency Matrix Representation] +An adjacency-matrix representation of a graph is a 2-dimensional V x V array. Each element in the array +auv stores a Boolean value saying whether the edge (u,v) is in the graph. Figure 3 depicts an adjacency +matrix for the graph in Figure 1 (minus the parallel edge (b,y)). The ammount of space required to store +an adjacency-matrix is O(V2). Any edge can be accessed, added, or removed in O(1) time. To add or remove +a vertex requires reallocating and copying the whole graph, an O(V2) operation. The `adjacency_matrix<>` +class implements the Boost.Graph interface in terms of the adjacency-matrix data structure. + +[$../images/review_adjacency_matrix.gif] + +[h3 Adjacency List Representation] +An adjacency-list representation of a graph stores an out-edge sequence for each vertex. For sparse +graphs this saves space since only O(V + E) memory is required. In addition, the out-edges for each +vertex can be accessed more efficiently. Edge insertion is O(1), though accessing any given edge is +O(alpha), where alpha is the sparsity factor of the matrix (which is equal to the maximum number of +out-edges for any vertex in the graph). Figure 4 depicts an adjacency-list representation of the +graph in Figure 1. The adjacency_list class is an implementation of the adjacency-list representation. + +[$../images/review_adjacency_list.gif] + +[h3 Edge List Representation] +An edge-list representation of a graph is simply a sequence of edges, where each edge is represented +as a pair of vertex ID's. The memory required is only O(E). Edge insertion is typically O(1), though +accessing a particular edge is O(E) (not efficient). Figure 5 shows an edge-list representation of the +graph in Figure 1. The edge_list adaptor class can be used to create implementations of the edge-list +representation. + +[$../images/review_edge_list.gif] + +[h3 Other Respresentations] +Add something here to discuss optimized storage options for the graph. Specifically, we might +mention the compressed-sparse-row graph representation and its possible uses. + +[h2 Graph Algorithms] +Like all data structures, there are numerous algorithms that operate on them to solve various problems. +In fact, there are often several different approaches to solving the same problem, each with different +properties and complexities when running on graphs with different properties (e.g., directed vs. undirected +or sparse vs. dense). The following sections briefly discuss a few such problems and algorithms. + +[h3 Graph Search Algorithms] +Tree edges are edges in the search tree (or forest) constructed (implicitly or explicitly) by running a +graph search algorithm over a graph. An edge (u,v) is a tree edge if v was first discovered while +exploring (corresponding to the visitor explore() method) edge (u,v). Back edges connect vertices to +their ancestors in a search tree. So for edge (u,v) the vertex v must be the ancestor of vertex u. Self +loops are considered to be back edges. Forward edges are non-tree edges (u,v) that connect a vertex u +to a descendant v in a search tree. Cross edges are edges that do not fall into the above three categories. + +[h4 Breadth-First Search] +Breadth-first search (BFS) is a traversal through a graph that touches all of the vertices reachable +from a particular source vertex. In addition, the order of the traversal is such that the algorithm +will explore all of the neighbors of a vertex before proceeding on to the neighbors of its neighbors. +One way to think of breadth-first search is that it expands like a wave emanating from a stone dropped +into a pool of water. Vertices in the same ``wave'' are the same distance from the source vertex. A +vertex is discovered the first time it is encountered by the algorithm. A vertex is finished after +all of its neighbors are explored. Here's an example to help make this clear. A graph is shown in +Figure 6 and the BFS discovery and finish order for the vertices is shown below. + +[$../images/review_bfs.gif] + + order of discovery: s r w v t x u y + order of finish: s r w v t x u y + +We start at vertex , and first visit r and w (the two neighbors of ). Once both neighbors of are visited, +we visit the neighbor of r (vertex v), then the neighbors of w (the discovery order between r and w does +not matter) which are t and x. Finally we visit the neighbors of t and x, which are u and y. + +For the algorithm to keep track of where it is in the graph, and which vertex to visit next, BFS needs +to color the vertices (see the section on Property Maps for more details about attaching properties to +graphs). The place to put the color can either be inside the graph, or it can be passed into the algorithm +as an argument. + +[h4 Depth-First Search] +A depth-first search (DFS) visits all the vertices in a graph. When choosing which edge to explore next, +this algorithm always chooses to go ``deeper'' into the graph. That is, it will pick the next adjacent +unvisited vertex until reaching a vertex that has no unvisited adjacent vertices. The algorithm will then +backtrack to the previous vertex and continue along any as-yet unexplored edges from that vertex. After DFS +has visited all the reachable vertices from a particular source vertex, it chooses one of the remaining +undiscovered vertices and continues the search. This process creates a set of depth-first trees which together +form the depth-first forest. A depth-first search categorizes the edges in the graph into three categories: +tree-edges, back-edges, and forward or cross-edges (it does not specify which). There are typically many +valid depth-first forests for a given graph, and therefore many different (and equally valid) ways to +categorize the edges. + +One interesting property of depth-first search is that the discover and finish times for each vertex form +a parenthesis structure. If we use an open-parenthesis when a vertex is discovered, and a close-parenthesis +when a vertex is finished, then the result is a properly nested set of parenthesis. Figure 7 shows DFS applied +to an undirected graph, with the edges labeled in the order they were explored. Below we list the vertices of +the graph ordered by discover and finish time, as well as show the parenthesis structure. DFS is used as the +kernel for several other graph algorithms, including topological sort and two of the connected component +algorithms. It can also be used to detect cycles (see the Cylic Dependencies section of the File Dependency +Example). + +[$../images/review_dfs.gif] + + order of discovery: a b e d c f g h i + order of finish: d f c e b a + parenthesis: (a (b (e (d d) (c (f f) c) e) b) a) (g (h (i i) h) g) + +[h4 Minimum Spanning Tree Problem] +The minimum-spanning-tree (MST) problem is defined as follows: Given a graph /G=(V,E)/ find an acyclic +subset /T/ of /E/ that connects all of the vertices in the graph and whose total weight is minimized, where +the total weight is given by + +/w(T)/ = sum of /w(u,v)/ over all /(u,v)/ in T, where /w(u,v)/ is the weight on the edge /(u,v)/. + +/T/ is called the minimum spanning tree of /G/. It is important to note that a graph may have multiple MSTs. + +[h4 Shortest-Paths Algorithms] +One of the classic problems in graph theory is to find the shortest path between two vertices in a graph. +Formally, a path is a sequence of vertices in a graph G = (V, E) such that each vertex is +connected to the next vertex in the sequence (the edges (vi,vi+1) for i=0,1,...,k-1 are in the edge set E). +In the shortest-path problem, each edge is given a real-valued weight. We can therefore talk about the weight +of a path + +/w(p)/ = sum from /i=1..k/ of /w(vi-1,vi)/ + +The shortest path weight from vertex /u/ to /v/ is then + +/delta(u,v)/ = min /{ w(p) : u --> v }/ if there is a path from u to v +/delta(u,v)/ = infinity otherwise. + +A shortest path is any path who's path weight is equal to the shortest path weight. So there may be several +shortest paths within the same graph. + +There are several variants of the shortest path problem. Above we defined the single-pair problem, but there +is also the single-source problem (all shortest paths from one vertex to every other vertex in the graph), +the equivalent single-destination problem, and the all-pairs problem. It turns out that there are no +algorithms for solving the single-pair problem that are asymptotically faster than algorithms that solve +the single-source problem. + +A shortest-paths tree rooted at vertex in graph /G=(V,E)/ is a directed subgraph where /V'/ is a subset of +/V/ and /E'/ is a subset of /(E, V')/ is the set of vertices reachable from , /G'/ forms a rooted tree with +root , and for all /v/ in /V'/ the unique simple path from to /v/ in /G'/ is a shortest path from to /v/ in +/G/. The result of a single-source algorithm is a shortest-paths tree. + +[h4 Network Flow Algorithms] +A flow network is a directed graph /G=(V,E)/ with a source vertex /s/ and a sink vertex /t/. Each edge has +a positive real valued capacity function c and there is a flow function f defined over every vertex pair. +The flow function must satisfy three contraints: + +* /f(u,v) <= c(u,v)/ for all /(u,v)/ in /V/x /V/ (Capacity constraint) +* /f(u,v) = -f(v,u)/ for all /(u,v)/ in /V/ x /V/ (Skew symmetry) +* sum /v/ in /V/ /f(u,v)/ = 0 for all /u/ in /V/ - /{s,t}/ (Flow conservation) + +The flow of the network is the net flow entering the sink vertex t (which is equal to the net flow leaving +the source vertex s). + +/|f|/ = sum /u/ in /V/ /f(u,t)/ = sum /v/ in /V/ /f(s,v)/ + +The residual capacity of an edge is /r(u,v)/ = /c(u,v) - f(u,v)/. The edges with /r(u,v) > 0/ are residual +edges /Ef/ which induce the residual graph /Gf = (V, Ef)/. An edge with /r(u,v) = 0/ is saturated. + +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. A flow network is shown in Figure 8. Vertex A is the source +vertex and H is the target vertex. + +[$../images/review_flow.gif] + +Edges are labeled with the flow and capacity values. There is a long history of algorithms for solving the +maximum flow problem, with the first algorithm due to Ford and Fulkerson. The best general purpose algorithm +to date is the push-relabel algorithm of Goldberg which is based on the notion of a preflow introduced by +Karzanov. + +[endsect] \ No newline at end of file diff --git a/quickbook/tour.qbk b/quickbook/tour.qbk new file mode 100644 index 00000000..0a823ea7 --- /dev/null +++ b/quickbook/tour.qbk @@ -0,0 +1,508 @@ +[/ + / Copyright (c) 2007 Andrew Sutton + / + / 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) + /] + +[section A Quick tour of Boost.Graph] +The domain of graph data structures and algorithms is in some respects more complicated than +that of containers. The abstract iterator interface used by STL is not sufficiently rich to +encompass the numerous ways that graph algorithms may traverse a graph. Instead, we formulate an +abstract interface that serves the same purpose for graphs that iterators do for basic containers +(though iterators still play a large role). Figure 1 depicts the analogy between the STL and +Boost.Graph. + +[$../images/tour_analogy.gif] + +The graph abstraction consists of a set of vertices (or nodes), and a set of edges (or arcs) that +connect the vertices. Figure 2 depicts a directed graph with five vertices (labeled 0 through 4) +and 11 edges. The edges leaving a vertex are called the out-edges of the vertex. The edges +{(0,1),(0,2),(0,3),(0,4)} are all out-edges of vertex 0. The edges entering a vertex are called +the in-edges of the vertex. The edges {(0,4),(2,4),(3,4)} are all in-edges of vertex 4. + +[$../images/tour_graph.png] + +In the following sections we will use Boost.Graph to construct this example graph and manipulate it in +various ways. The complete source code for this example can be found in examples/quick_tour.cpp. Each +of the following sections discusses a "slice" of this example file. Excerpts from the output of the +example program will also be listed. + +[h2 Constructing the Graph] +In this example we will use the `adjacency_list<>` class to demonstrate the main ideas in the +Boost.Graph interface. The `adjacency_list<>` class provides a generalized version of the classic +"adjacency list" data structure. The `adjacency_list<>` is a template class with six template parameters, +though here we only fill in the first three parameters and use the defaults for the remainder. +The first two template arguments (`vecS`, `vecS`) determine the data structure used to represent the +out-edges for each vertex in the graph and the data structure used to represent the graph's vertex set +(see section Choosing the Edgelist and VertexList for information about the tradeoffs of the different +data structures). The third argument, `bidirectionalS`, selects a directed graph that provides access to +both out and in-edges. The other options for the third argument are `directedS` which selects a directed +graph with only out-edges, and `undirectedS` which selects an undirected graph. + +Once we have the graph type selected, we can create the graph in Figure 2 by declaring a graph object +and filling in edges using the add_edge() function of the MutableGraph interface (which `adjacency_list<>` +implements). We use the array of pairs edge_array merely as a convenient way to explicitly create the +edges for this example. + + #include // for std::cout + #include // for std::pair + #include // for std::for_each + #include + + using namespace std; + using namespace boost; + + int main(int, char*[]) + { + // create a typedef for the Graph type + typedef adjacency_list Graph; + + // Make convenient labels for the vertices + enum { A, B, C, D, E, N }; + const int num_vertices = N; + const char* name = "ABCDE"; + + // Create edges as pairs of of intengers + typedef pair Edge; + Edge edge_array[] = { + Edge(A,B), Edge(A,D), Edge(C,A), Edge(D,C), + Edge(C,E), Edge(B,D), Edge(D,E) + }; + const int num_edges = sizeof(edge_array) / sizeof(edge_array[0]); + + // Declare a graph object with N vertices + Graph g(num_vertices); + + // Add the edges to the graph + for (int i = 0; i < num_edges; ++i) { + add_edge(edge_array[i].first, edge_array[i].second, g); + } + + // ... continue below + return 0; + } + +Instead of calling the `add_edge()` function for each edge, we could use the edge iterator constructor +of the graph. This is typically more efficient than using `add_edge()`. Pointers to the `edge_array` can +be viewed as iterators, so we can call the iterator constructor by passing pointers to the beginning +and end of the array. + + Graph g(edges, edges + sizeof(edge_array) / sizeof(edge_array[0]), num_vertices); + +Instead of creating a graph with a certain number of vertices to begin with, it is also possible to +add and remove vertices with the `add_vertex()` and `remove_vertex()` functions, also of the /MutableGraph/ +interface. + +[h2 Accessing the Vertex Set] +Now that we have created a graph, we can use the graph interface to access the graph data in +different ways. First we can access all of the vertices in the graph using the `vertices()` function +of the /VertexListGraph/ interface. This function returns a `std::pair<>` of vertex iterators (the first +iterator points to the "beginning" of the vertices and the second iterator points "past the end"). +Dereferencing a vertex iterator gives a vertex object. The type of the vertex iterator is given by +the graph_traits class. Note that different graph classes can have different associated vertex +iterator types, which is why we need the `graph_traits<>` class. Given some graph type, the `graph_traits<>` +class will provide access to the vertex_iterator type. + +The following example prints out the index for each of the vertices in the graph. All vertex and +edge properties, including index, are accessed via property map objects. The `property_map<>` class is +used to obtain the property map type for a specific property (specified by `vertex_index_t`, one of the +Boost.Graph predefined properties) and function call `get(vertex_index, g)` returns the actual +property map object. + + + // ... + int main(int,char*[]) + { + // ... continued from above + + // Get the property map for vertex indices + typedef property_map::type IndexMap; + IndexMap index = get(vertex_index, g); + + cout << "vertices(g) = "; + typedef graph_traits::vertex_iterator vertex_iter; + pair vp; + for(vp = vertices(g); vp.first != vp.second; ++vp.first) { + cout << index[*vp.first] << " "; + } + cout << "\n"; + + // ... + return 0; + } + +The output is: + +[pre + vertices(g) = 0 1 2 3 4 +] + +[h2 Accessing the Edge Set] +The set of edges for a graph can be accessed with the edges() function of the /EdgeListGraph/ interface. +Similar to the `vertices()` function, this returns a pair of iterators, but in this case the iterators +are edge iterators. Dereferencing an edge 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. 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 +choice for Boost.Graph. + + // ... + int main(int,char*[]) + { + // ... continued from above + cout << "edges(g) = "; + graph_traits::edge_iterator ei, ei_end; + for(tie(ei, ei_end) = edges(g); ei != ei_end; ++ei) { + cout << "(" << index[source(*ei, g)] << "," << index[target(*ei, g)] << ") "; + } + cout << "\n"; + + // ... + return 0; + } + +The output is: +[pre + edges(g) = (0,1) (0,2) (0,3) (0,4) (2,0) (2,4) (3,0) (3,1) (3,4) (4,0) (4,1) +] + +[h2 The Adjacency Structure] +In the next few examples we will explore the adjacency structure of the graph from the point of +view of a particular vertex. We will look at the vertices' in-edges, out-edges, and its adjacent +vertices. We will encapsulate this in an "exercise vertex" function, and apply it to each vertex +in the graph. To demonstrate the STL-interoperability of Boost.Graph, we will use the STL `for_each()` +function to iterate through the vertices and apply the function. + + //... + int main(int,char*[]) + { + // ... + for_each(vertices(g).first, vertices(g).second, exercise_vertex(g)); + return 0; + } + +We use a functor for exercise_vertex instead of just a function because the graph object will be +needed when we access information about each vertex; using a functor gives us a place to keep a +reference to the graph object during the execution of the `std::for_each()`. Also we template the +functor on the graph type so that it is reusable with different graph classes. Here is the start +of the exercise_vertex functor: + + template struct exercise_vertex { + exercise_vertex(Graph& g_) : g(g_) + { } + + // ... + + Graph& g; + }; + +[h3 Vertex Descriptors] +The first thing we need to know in order to write the operator() method of the functor is the type +for the vertex objects of the graph. The vertex type will be the parameter to the `operator()` +method. To be precise, we do not deal with actual vertex objects, but rather with vertex descriptors. +Many graph representations (such as adjacency lists) do not store actual vertex objects, while +others do (e.g., pointer-linked graphs). This difference is hidden underneath the "black-box" +of the vertex descriptor object. The vertex descriptor is something provided by each graph type +that can be used to access information about the graph via the `out_edges()`, `in_edges()`, +`adjacent_vertices()`, and property map functions that are described in the following sections. The +vertex_descriptor type is obtained through the graph_traits class. The typename keyword used below +is necessary because the type on the left hand side of the scope :: operator (the `graph_traits` +type) is dependent on a template parameter (the `Graph` type). Here is how we define the functor's +apply method: + + template struct exercise_vertex { + // ... continued from above + + typedef typename graph_traits::vertex_descriptor Vertex; + + void operator()(const Vertex& v) const + { + // ... this is where we will "exercise" the vertex + } + + // ... + }; + +[h3 Out-Edges, In-Edges, and Edge Descriptors] +The out-edges of a vertex are accessed with the `out_edges()` function of the /IncidenceGraph/ +interface. The out_edges() function takes two arguments: the first argument is the vertex and +the second is the graph object. The function returns a pair of iterators which provide access +to all of the out-edges of a vertex (similar to how the vertices() function returned a pair of +iterators). The iterators are called out-edge iterators and dereferencing one of these iterators +gives an edge descriptor object. An edge descriptor plays the same kind of role as the vertex +descriptor object, it is a "black box" provided by the graph type. The following code snippet prints +the source-target pairs for each out-edge of vertex, v. + + template struct exercise_vertex { + //... continued from above + + void operator()(const Vertex& v) const + { + typedef graph_traits GraphTraits; + typedef typename property_map::type IndexMap; + IndexMap index = get(vertex_index, g); + + 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); out_i != out_end; ++out_i) { + e = *out_i; + Vertex src = source(e, g), tgt = target(e, g); + cout << "(" << index[src] << "," << index[targ] << ") "; + } + std::cout << "\n"; + + // ... + } + + // ... + }; + +For vertex 0 the output is: +[pre + out-edges: (0,1) (0,2) (0,3) (0,4) +] + +The `in_edges()` function of the BidirectionalGraph interface provides access to all the in-edges +of a vertex through in-edge iterators. The in_edges() function is only available for the +`adjacency_list<>` if `bidirectionalS` is supplied for the Directed template parameter. There is an +extra cost in space when `bidirectionalS` is specified instead of `directedS`. + + template struct exercise_vertex { + // ... continued from above + + void operator()(const Vertex& v) const + { + // ... + cout << "in-edges: "; + typedef typename graph_traits GraphTraits; + typename GraphTraits::in_edge_iterator in_i, in_end; + for (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); + cout << "(" << index[src] << "," << index[targ] << ") "; + } + cout << "\n"; + // ... + } + + // ... + }; + +For vertex 0 the output is: +[pr + in-edges: (2,0) (3,0) (4,0) +] + +[h3 Adjacent Vertices] +Given the out-edges of a vertex, the target vertices of these edges are adjacent to the source +vertex. Sometimes an algorithm does not need to look at the edges of the graph and only cares +about the vertices. Therefore the graph interface also includes the `adjacent_vertices()` function +of the AdjacencyGraph interface which provides direct access to the adjacent vertices. This function +returns a pair of adjacency iterators. Dereferencing an adjacency iterator gives a vertex descriptor +for an adjacent vertex. + + template struct exercise_vertex { + // ... continued from above + + void operator()(Vertex v) const + { + //... + cout << "adjacent vertices: "; + typename graph_traits::adjacency_iterator ai; + typename graph_traits::adjacency_iterator ai_end; + for(tie(ai, ai_end) = adjacent_vertices(v, g); ai != ai_end; ++ai) { + std::cout << index[*ai] << " "; + } + std::cout << "\n"; + } + + //... + }; + +For vertex 4 the output is: +[pre + adjacent vertices: 0 1 +] + +[Adding Some Color to your Graph] +Boost.Graph 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 be convenient to have the graph object also manage +the property storage. On the other hand, a property like vertex color may only be needed for the +duration of a single algorithm, and it would be better to have the property stored separately from +the graph object. The first kind of property is called an internally stored property while the second +kind is called an externally stored property. Boost.Graph uses a uniform mechanism to access both kinds of +properties inside its graph algorithms called the property map interface, described in Section +Property Map Concepts. In addition, the PropertyGraph concept defines the interface for obtaining +a property map object for an internally stored property. + +The Boost.Graph adjacency_list class allows users to specify internally stored properties through plug-in +template parameters of the graph class. How to do this is discussed in detail in Section Internal +Properties. Externally stored properties can be created in many different ways, although they are +ultimately passed as separate arguments to the graph algorithms. One straightforward way to store +properties is to create an array indexed by vertex or edge index. In the adjacency_list with `vecS` +specified for the VertexList template parameter, vertices are automatically assigned indices, which +can be accessed via the property map for the vertex_index_t. Edges are not automatically assigned +indices. However the property mechanism can be used to attach indices to the edges which can be +used to index into other externally stored properties. + +In the following example, we construct a graph and apply `dijkstra_shortest_paths()`. The complete +source code for the example is in examples/dijkstra-example.cpp. Dijkstra's algorithm computes the +shortest distance from the starting vertex to every other vertex in the graph. + +Dijkstra's algorithm requires that a weight property is associated with each edge and a distance +property with each vertex. Here we use an internal property for the weight and an external property +for the distance. For the weight property we use the property class and specify int as the type used +to represent weight values and edge_weight_t for the property tag (which is one of the Boost.Graph +predefined property tags). The weight property is then used as a template argument for `adjacency_list<>`. +The listS and vecS types are selectors that determine the data structure used inside the +`adjacency_list<>` (see Section Choosing the Edgelist and VertexList). The directedS type specifies +that the graph should be directed (versus undirected). The following code shows the specification of +the graph type and then the initialization of the graph. The edges and weights are passed to the +graph constructor in the form of iterators (a pointer qualifies as a /RandomAccessIterator/). + + typedef adjacency_list // edges have integer edge weight + > Graph; + typedef graph_traits::vertex_descriptor Vertex; + typedef std::pair E; + + const int num_nodes = 5; + E edges[] = { E(0,2), + E(1,1), E(1,3), E(1,4), + E(2,1), E(2,3), + E(3,4), + E(4,0), E(4,1) }; + int weights[] = { 1, 2, 1, 2, 7, 3, 1, 1, 1}; + + Graph G(edges + sizeof(edges) / sizeof(E), weights, num_nodes); + +For the external distance property we will use a std::vector for storage. Boost.Graph algorithms treat +random access iterators as property maps, so we can just pass the beginning iterator of the +distance vector to Dijkstra's algorithm. Continuing the above example, the following code shows +the creation of the distance vector, the call to Dijkstra's algorithm (implicitly using the +internal edge weight property), and then the output of the results. + + // vector for storing distance property + std::vector d(num_vertices(G)); + + // get the first vertex + Vertex s = *(vertices(G).first); + + // invoke variant 2 of Dijkstra's algorithm + dijkstra_shortest_paths(G, s, distance_map(&d[0])); + + std::cout << "distances from start vertex:" << ; + graph_traits::vertex_iterator vi; + for(vi = vertices(G).first; vi != vertices(G).second; ++vi) + std::cout << "distance(" << index(*vi) << ") = " + << d[*vi] << ; + std::cout << ; + +The output is: +[pre + distances from start vertex: + distance(0) = 0 + distance(1) = 6 + distance(2) = 1 + distance(3) = 4 + distance(4) = 5 +] + +[Extending Algorithms with Visitors] +Often times an algorithm in a library almost does what you need, but not quite. For example, in +the previous section we used Dijkstra's algorithm to calculate the shortest distances to each +vertex, but perhaps we also wanted to record the tree of shortest paths. One way to do this is +to record the predecessor (parent) for each node in the shortest-paths tree. + +It would be nice if we could avoid rewriting Dijkstra's algorithm, and just add that little bit +extra needed to record the predecessors [1]. In the STL, this kind of extensibility is provided +by functors, which are optional parameters to each algorithm. In Boost.Graph this role is +fulfilled by visitors. + +A visitor is like a functor, but instead of having just one "apply" method, it has several. +Each of these methods get invoked at certain well-defined points within the algorithm. The visitor +methods are explained in detail in Section Visitor Concepts. Boost.Graph provides a number of visitors +for some common tasks including a predecessor recording visitor. The user is encouraged to write +his or her own visitors as a way of extending Boost.Graph. Here we will take a quick look at the +implementation and use of the predecessor recorder. Since we will be using the +`dijkstra_shortest_paths()` algorithm, the visitor we create must be a Dijkstra Visitor. + +The functionality of the record_predecessors visitor is separated into two parts. For the storage +and access of the predecessor property, we will use a property map. The predecessor visitor will +then only be responsible for what parent to record. To implement this, we create a +`record_predecessors` class and template it on the predecessor property map `PredecessorMap`. Since +this visitor will only be filling in one of the visitor methods, we will inherit from +`dijkstra_visitor` which will provide empty methods for the rest. The constructor of the +`predecessor_recorder` will take the property map object and save it away in a data member. + + template + class record_predecessors : public dijkstra_visitor<> + { + public: + record_predecessors(PredecessorMap p) + : m_predecessor(p) + { } + + template + void edge_relaxed(Edge e, Graph& g) { + // set the parent of the target(e) to source(e) + put(m_predecessor, target(e, g), source(e, g)); + } + protected: + PredecessorMap m_predecessor; + }; + +The job of recording the predecessors is quite simple. When Dijkstra's algorithm relaxes an edge +(potentially adding it to the shortest-paths tree) we record the source vertex as the predecessor +of the target vertex. Later, if the edge is relaxed again the predecessor property will be +overwritten by the new predecessor. Here we use the put() function associated with the +property map to record the predecessor. The `edge_filter` of the visitor tells the algorithm when +to invoke the `explore()` method. In this case we only want to be notified about edges in the +shortest-paths tree so we specify `tree_edge_tag`. + +As a finishing touch, we create a helper function to make it more convenient to create predecessor +visitors. All Boost.Graph visitors have a helper function like this. + + template + record_predecessors + make_predecessor_recorder(PredecessorMap p) { + return record_predecessors(p); + } + +We are now ready to use the `record_predecessors` in Dijkstra's algorithm. Luckily, Boost.Graph's +Dijkstra's algorithm is already equipped to handle visitors, so we just pass in our new visitor. +In this example we only need to use one visitor, but Boost.Graph is also equipped to handle the use +of multiple visitors in the same algorithm (see Section Visitor Concepts). + + using std::vector; + using std::cout; + using std::endl; + vector p(num_vertices(G)); //the predecessor array + dijkstra_shortest_paths(G, s, distance_map(&d[0]). + visitor(make_predecessor_recorder(&p[0]))); + + cout << "parents in the tree of shortest paths:" << endl; + for(vi = vertices(G).first; vi != vertices(G).second; ++vi) { + cout << "parent(" << *vi; + if (p[*vi] == Vertex()) + cout << ") = no parent" << endl; + else + cout << ") = " << p[*vi] << endl; + } + +The output is: +[pre + parents in the tree of shortest paths: + parent(0) = no parent + parent(1) = 4 + parent(2) = 0 + parent(3) = 2 + parent(4) = 3 +] + +[endsect] \ No newline at end of file diff --git a/quickbook/tutorial.qbk b/quickbook/tutorial.qbk new file mode 100644 index 00000000..8f733c51 --- /dev/null +++ b/quickbook/tutorial.qbk @@ -0,0 +1,17 @@ +[/ + / Copyright (c) 2007 Andrew Sutton + / + / 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) + /] + +[section Tutorial] + +This section contains a tutorial for the Boost.Graph library. It builds on the +quick tour but discusses the concepts in much greater detail. + +[include tut_properties.qbk] + +[include tut_adjacency_list.qbk] + +[endsect] \ No newline at end of file From d7e37c7b5648fb0192541cc5b8478a38c02cb84e Mon Sep 17 00:00:00 2001 From: Andrew Sutton Date: Sat, 14 Feb 2009 13:56:37 +0000 Subject: [PATCH 096/224] Importing examples from SOC 2007 [SVN r51251] --- examples/Jamfile.v2 | 19 +++ examples/bron_kerbosch_clique_number.cpp | 36 +++++ examples/bron_kerbosch_print_cliques.cpp | 74 +++++++++++ examples/closeness_centrality.cpp | 85 ++++++++++++ examples/clustering_coefficient.cpp | 69 ++++++++++ examples/comm_network.graph | 12 ++ examples/degree_centrality.cpp | 67 ++++++++++ examples/eccentricity.cpp | 90 +++++++++++++ examples/helper.hpp | 113 ++++++++++++++++ examples/inclusive_mean_geodesic.cpp | 159 +++++++++++++++++++++++ examples/influence_prestige.cpp | 75 +++++++++++ examples/info_network.graph | 11 ++ examples/mean_geodesic.cpp | 90 +++++++++++++ examples/prism_3_2.graph | 16 +++ examples/prob_network.graph | 18 +++ examples/scaled_closeness_centrality.cpp | 115 ++++++++++++++++ examples/social_network.graph | 12 ++ examples/tiernan_girth_circumference.cpp | 40 ++++++ examples/tiernan_print_cycles.cpp | 68 ++++++++++ 19 files changed, 1169 insertions(+) create mode 100644 examples/Jamfile.v2 create mode 100644 examples/bron_kerbosch_clique_number.cpp create mode 100644 examples/bron_kerbosch_print_cliques.cpp create mode 100644 examples/closeness_centrality.cpp create mode 100644 examples/clustering_coefficient.cpp create mode 100644 examples/comm_network.graph create mode 100644 examples/degree_centrality.cpp create mode 100644 examples/eccentricity.cpp create mode 100644 examples/helper.hpp create mode 100644 examples/inclusive_mean_geodesic.cpp create mode 100644 examples/influence_prestige.cpp create mode 100644 examples/info_network.graph create mode 100644 examples/mean_geodesic.cpp create mode 100644 examples/prism_3_2.graph create mode 100644 examples/prob_network.graph create mode 100644 examples/scaled_closeness_centrality.cpp create mode 100644 examples/social_network.graph create mode 100644 examples/tiernan_girth_circumference.cpp create mode 100644 examples/tiernan_print_cycles.cpp diff --git a/examples/Jamfile.v2 b/examples/Jamfile.v2 new file mode 100644 index 00000000..92d1addf --- /dev/null +++ b/examples/Jamfile.v2 @@ -0,0 +1,19 @@ + +project + : requirements + ../../../ + $BOOST_ROOT + ; + +exe degree_centrality : degree_centrality.cpp ; +exe influence_prestige : influence_prestige.cpp ; +exe closeness_centrality : closeness_centrality.cpp ; +exe scaled_closeness_centrality : scaled_closeness_centrality.cpp ; +exe mean_geodesic : mean_geodesic.cpp ; +exe inclusive_mean_geodesic : inclusive_mean_geodesic.cpp ; +exe eccentricity : eccentricity.cpp ; +exe clustering_coefficient : clustering_coefficient.cpp ; +exe tiernan_print_cycles : tiernan_print_cycles.cpp ; +exe tiernan_girth_circumference : tiernan_girth_circumference.cpp ; +exe bron_kerbosch_print_cliques : bron_kerbosch_print_cliques.cpp ; +exe bron_kerbosch_clique_number : bron_kerbosch_clique_number.cpp ; diff --git a/examples/bron_kerbosch_clique_number.cpp b/examples/bron_kerbosch_clique_number.cpp new file mode 100644 index 00000000..46b5c7a0 --- /dev/null +++ b/examples/bron_kerbosch_clique_number.cpp @@ -0,0 +1,36 @@ +// (C) Copyright Andrew Sutton 2007 +// +// 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) + +//[code_bron_kerbosch_clique_number +#include + +#include +#include + +#include "helper.hpp" + +using namespace std; +using namespace boost; + +// Declare the graph type and its vertex and edge types. +typedef undirected_graph<> Graph; +typedef graph_traits::vertex_descriptor Vertex; +typedef graph_traits::edge_descriptor Edge; + +int +main(int argc, char *argv[]) +{ + // Create the graph and read it from standard input. + Graph g; + read_graph(g, cin); + + // Use the Bron-Kerbosch algorithm to find all cliques, and + size_t c = bron_kerbosch_clique_number(g); + cout << "clique number: " << c << endl; + + return 0; +} +//] diff --git a/examples/bron_kerbosch_print_cliques.cpp b/examples/bron_kerbosch_print_cliques.cpp new file mode 100644 index 00000000..93030edd --- /dev/null +++ b/examples/bron_kerbosch_print_cliques.cpp @@ -0,0 +1,74 @@ +// (C) Copyright Andrew Sutton 2007 +// +// 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) + +//[code_bron_kerbosch_print_cliques +#include + +#include +#include + +#include "helper.hpp" + +using namespace std; +using namespace boost; + +// The clique_printer is a visitor that will print the vertices that comprise +// a clique. Note that the vertices are not given in any specific order. +template +struct clique_printer +{ + clique_printer(OutputStream& stream) + : os(stream) + { } + + template + void clique(const Clique& c, const Graph& g) + { + // Iterate over the clique and print each vertex within it. + typename Clique::const_iterator i, end = c.end(); + for(i = c.begin(); i != end; ++i) { + os << g[*i].name << " "; + } + os << endl; + } + OutputStream& os; +}; + +// The Actor type stores the name of each vertex in the graph. +struct Actor +{ + string name; +}; + +// Declare the graph type and its vertex and edge types. +typedef undirected_graph Graph; +typedef graph_traits::vertex_descriptor Vertex; +typedef graph_traits::edge_descriptor Edge; + +// The name map provides an abstract accessor for the names of +// each vertex. This is used during graph creation. +typedef property_map::type NameMap; + +int +main(int argc, char *argv[]) +{ + // Create the graph and and its name map accessor. + Graph g; + NameMap nm(get(&Actor::name, g)); + + // Read the graph from standard input. + read_graph(g, nm, cin); + + // Instantiate the visitor for printing cliques + clique_printer vis(cout); + + // Use the Bron-Kerbosch algorithm to find all cliques, printing them + // as they are found. + bron_kerbosch_all_cliques(g, vis); + + return 0; +} +//] diff --git a/examples/closeness_centrality.cpp b/examples/closeness_centrality.cpp new file mode 100644 index 00000000..8258f6be --- /dev/null +++ b/examples/closeness_centrality.cpp @@ -0,0 +1,85 @@ +// (C) Copyright Andrew Sutton 2007 +// +// 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) + +//[closeness_centrality_example +#include +#include + +#include +#include +#include +#include +#include +#include "helper.hpp" + +using namespace std; +using namespace boost; + +// The Actor type stores the name of each vertex in the graph. +struct Actor +{ + string name; +}; + +// Declare the graph type and its vertex and edge types. +typedef undirected_graph Graph; +typedef graph_traits::vertex_descriptor Vertex; +typedef graph_traits::edge_descriptor Edge; + +// The name map provides an abstract accessor for the names of +// each vertex. This is used during graph creation. +typedef property_map::type NameMap; + +// Declare a matrix type and its corresponding property map that +// will contain the distances between each pair of vertices. +typedef exterior_vertex_property DistanceProperty; +typedef DistanceProperty::matrix_type DistanceMatrix; +typedef DistanceProperty::matrix_map_type DistanceMatrixMap; + +// Declare the weight map so that each edge returns the same value. +typedef constant_property_map WeightMap; + +// Declare a container and its corresponding property map that +// will contain the resulting closeness centralities of each +// vertex in the graph. +typedef boost::exterior_vertex_property ClosenessProperty; +typedef ClosenessProperty::container_type ClosenessContainer; +typedef ClosenessProperty::map_type ClosenessMap; + +int +main(int argc, char *argv[]) +{ + // Create the graph and a property map that provides access to[ + // tha actor names. + Graph g; + NameMap nm(get(&Actor::name, g)); + + // Read the graph from standard input. + read_graph(g, nm, cin); + + // Compute the distances between all pairs of vertices using + // the Floyd-Warshall algorithm. Note that the weight map is + // created so that every edge has a weight of 1. + DistanceMatrix distances(num_vertices(g)); + DistanceMatrixMap dm(distances, g); + WeightMap wm(1); + floyd_warshall_all_pairs_shortest_paths(g, dm, weight_map(wm)); + + // Compute the closeness centrality for graph. + ClosenessContainer cents(num_vertices(g)); + ClosenessMap cm(cents, g); + all_closeness_centralities(g, dm, cm); + + // 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) + << g[*i].name << get(cm, *i) << endl; + } + + return 0; +} +//] diff --git a/examples/clustering_coefficient.cpp b/examples/clustering_coefficient.cpp new file mode 100644 index 00000000..70f8e731 --- /dev/null +++ b/examples/clustering_coefficient.cpp @@ -0,0 +1,69 @@ +// (C) Copyright Andrew Sutton 2007 +// +// 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) + + +//[code_clustering_coefficient +#include +#include + +#include +#include +#include +#include "helper.hpp" + +using namespace std; +using namespace boost; + +// The Actor type stores the name of each vertex in the graph. +struct Actor +{ + string name; +}; + +// Declare the graph type and its vertex and edge types. +typedef undirected_graph Graph; +typedef graph_traits::vertex_descriptor Vertex; +typedef graph_traits::edge_descriptor Edge; + +// The name map provides an abstract accessor for the names of +// each vertex. This is used during graph creation. +typedef property_map::type NameMap; + +// The clustering property, container, and map define the containment +// and abstract accessor for the clustering coefficients of vertices. +typedef exterior_vertex_property ClusteringProperty; +typedef ClusteringProperty::container_type ClusteringContainer; +typedef ClusteringProperty::map_type ClusteringMap; + +int +main(int argc, char *argv[]) +{ + // Create the graph and a name map that provides access to + // then actor names. + Graph g; + NameMap nm(get(&Actor::name, g)); + + // Read the graph from standard input. + read_graph(g, nm, cin); + + // Compute the clustering coefficients of each vertex in the graph + // and the mean clustering coefficient which is returned from the + // computation. + ClusteringContainer coefs(num_vertices(g)); + ClusteringMap cm(coefs, g); + float cc = all_clustering_coefficients(g, cm); + + // 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) + << g[*i].name << get(cm, *i) << endl; + } + cout << "mean clustering coefficient: " << cc << endl; + + return 0; +} +//] diff --git a/examples/comm_network.graph b/examples/comm_network.graph new file mode 100644 index 00000000..d4a4a9f5 --- /dev/null +++ b/examples/comm_network.graph @@ -0,0 +1,12 @@ +Mary,Jill +Jill,Scott +Scott,Mary +Scott,Bill +Bill,Josh +Josh,Frank +Frank,Scott +Frank,Anne +Anne,Howard +Howard,Frank +Frank,Laurie +Laurie,Mary diff --git a/examples/degree_centrality.cpp b/examples/degree_centrality.cpp new file mode 100644 index 00000000..7da764e1 --- /dev/null +++ b/examples/degree_centrality.cpp @@ -0,0 +1,67 @@ +// (C) Copyright Andrew Sutton 2007 +// +// 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) + + +//[degree_centrality_example +#include +#include + +#include +#include +#include + +#include "helper.hpp" + +using namespace std; +using namespace boost; + +// The Actor type stores the name of each vertex in the graph. +struct Actor +{ + string name; +}; + +// Declare the graph type and its vertex and edge types. +typedef undirected_graph Graph; +typedef graph_traits::vertex_descriptor Vertex; +typedef graph_traits::edge_descriptor Edge; + +// The name map provides an abstract accessor for the names of +// each vertex. This is used during graph creation. +typedef property_map::type NameMap; + +// Declare a container type for degree centralities and its +// corresponding property map. +typedef exterior_vertex_property CentralityProperty; +typedef CentralityProperty::container_type CentralityContainer; +typedef CentralityProperty::map_type CentralityMap; + +int +main(int argc, char *argv[]) +{ + // Create the graph and a property map that provides access + // to the actor names. + Graph g; + NameMap nm(get(&Actor::name, g)); + + // Read the graph from standard input. + read_graph(g, nm, cin); + + // Compute the degree centrality for graph. + CentralityContainer cents(num_vertices(g)); + CentralityMap cm(cents, g); + all_degree_centralities(g, cm); + + // 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) + << g[*i].name << cm[*i] << endl; + } + + return 0; +} +//] diff --git a/examples/eccentricity.cpp b/examples/eccentricity.cpp new file mode 100644 index 00000000..c02bcd3c --- /dev/null +++ b/examples/eccentricity.cpp @@ -0,0 +1,90 @@ +// (C) Copyright Andrew Sutton 2007 +// +// 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) + + +//[eccentricity_example +#include +#include + +#include +#include +#include +#include +#include +#include "helper.hpp" + +using namespace std; +using namespace boost; + +// The Actor type stores the name of each vertex in the graph. +struct Actor +{ + string name; +}; + +// Declare the graph type and its vertex and edge types. +typedef undirected_graph Graph; +typedef graph_traits::vertex_descriptor Vertex; +typedef graph_traits::edge_descriptor Edge; + +// The name map provides an abstract accessor for the names of +// each vertex. This is used during graph creation. +typedef property_map::type NameMap; + +// Declare a matrix type and its corresponding property map that +// will contain the distances between each pair of vertices. +typedef exterior_vertex_property DistanceProperty; +typedef DistanceProperty::matrix_type DistanceMatrix; +typedef DistanceProperty::matrix_map_type DistanceMatrixMap; + +// Declare the weight map so that each edge returns the same value. +typedef constant_property_map WeightMap; + +// Declare a container and its corresponding property map that +// will contain the resulting eccentricities of each vertex in +// the graph. +typedef boost::exterior_vertex_property EccentricityProperty; +typedef EccentricityProperty::container_type EccentricityContainer; +typedef EccentricityProperty::map_type EccentricityMap; + +int +main(int argc, char *argv[]) +{ + // Create the graph and a name map that provides access to + // then actor names. + Graph g; + NameMap nm(get(&Actor::name, g)); + + // Read the graph from standard input. + read_graph(g, nm, cin); + + // Compute the distances between all pairs of vertices using + // the Floyd-Warshall algorithm. Note that the weight map is + // created so that every edge has a weight of 1. + DistanceMatrix distances(num_vertices(g)); + DistanceMatrixMap dm(distances, g); + WeightMap wm(1); + floyd_warshall_all_pairs_shortest_paths(g, dm, weight_map(wm)); + + // Compute the eccentricities for graph - this computation returns + // both the radius and diameter as well. + int r, d; + EccentricityContainer eccs(num_vertices(g)); + EccentricityMap em(eccs, g); + tie(r, d) = all_eccentricities(g, dm, em); + + // 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) + << g[*i].name << get(em, *i) << endl; + } + cout << "radius: " << r << endl; + cout << "diamter: " << d << endl; + + return 0; +} +//] diff --git a/examples/helper.hpp b/examples/helper.hpp new file mode 100644 index 00000000..c6cf2238 --- /dev/null +++ b/examples/helper.hpp @@ -0,0 +1,113 @@ +// (C) Copyright Andrew Sutton 2007 +// +// 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_EXAMPLE_HELPER_HPP +#define BOOST_GRAPH_EXAMPLE_HELPER_HPP + +#include +#include +#include +#include + +#include + +template +typename boost::graph_traits::vertex_descriptor +add_named_vertex(Graph& g, NameMap nm, const std::string& name, VertexMap& vm) +{ + typedef typename boost::graph_traits::vertex_descriptor Vertex; + typedef typename VertexMap::iterator Iterator; + + Vertex v; + Iterator iter; + bool inserted; + tie(iter, inserted) = vm.insert(make_pair(name, Vertex())); + if(inserted) { + // The name was unique so we need to add a vertex to the graph + v = add_vertex(g); + iter->second = v; + put(nm, v, name); // store the name in the name map + } + else { + // We had alread inserted this name so we can return the + // associated vertex. + v = iter->second; + } + return v; +} + +template +inline std::map::vertex_descriptor> +read_graph(Graph& g, NameMap nm, InputStream& is) +{ + typedef typename boost::graph_traits::vertex_descriptor Vertex; + std::map verts; + for(std::string line; std::getline(is, line); ) { + if(line.empty()) continue; + std::size_t index = line.find_first_of(','); + std::string first(line, 0, index); + std::string second(line, index + 1); + + Vertex u = add_named_vertex(g, nm, first, verts); + Vertex v = add_named_vertex(g, nm, second, verts); + add_edge(u, v, g); + } + return verts; +} + +template +inline std::map::vertex_descriptor> +read_graph(Graph& g, InputStream& is) +{ + typedef typename boost::graph_traits::vertex_descriptor Vertex; + typedef boost::null_property_map NameMap; + return read_graph(g, NameMap(), is); +} + +template +inline std::map::vertex_descriptor> +read_weighted_graph(Graph& g, NameMap nm, WeightMap wm, InputStream& is) +{ + typedef typename boost::graph_traits::vertex_descriptor Vertex; + typedef typename boost::graph_traits::edge_descriptor Edge; + std::map verts; + for(std::string line; std::getline(is, line); ) { + if(line.empty()) continue; + std::size_t i = line.find_first_of(','); + std::size_t j = line.find_first_of(',', i + 1); + std::string first(line, 0, i); + std::string second(line, i + 1, j - i - 1); + std::string prob(line, j + 1); + + // convert the probability to a float + std::stringstream ss(prob); + float p; + ss >> p; + + // add the vertices to the graph + Vertex u = add_named_vertex(g, nm, first, verts); + Vertex v = add_named_vertex(g, nm, second, verts); + + // add the edge and set the weight + Edge e = add_edge(u, v, g).first; + put(wm, e, p); + } + return verts; +} + + +template +inline std::map::vertex_descriptor> +read_weighted_graph(Graph& g, WeightMap wm, InputStream& is) +{ + typedef typename boost::graph_traits::vertex_descriptor Vertex; + typedef boost::null_property_map NameMap; + + return read_weighted_graph(g, NameMap(), wm, is); +} + + +#endif diff --git a/examples/inclusive_mean_geodesic.cpp b/examples/inclusive_mean_geodesic.cpp new file mode 100644 index 00000000..23ab4850 --- /dev/null +++ b/examples/inclusive_mean_geodesic.cpp @@ -0,0 +1,159 @@ +// (C) Copyright Andrew Sutton 2007 +// +// 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) + +//[inclusive_mean_geodesic_example +#include +#include + +#include +#include +#include +#include +#include +#include "helper.hpp" + +using namespace std; +using namespace boost; + +// This template structure defines the function that we will apply +// to compute both the per-vertex mean geodesic distances and the +// graph's mean geodesic distance. +template > +struct inclusive_average +{ + typedef DistanceType distance_type; + typedef ResultType result_type; + + result_type operator ()(distance_type d, const Graph& g) + { + if(d == numeric_values::infinity()) { + return numeric_values::infinity(); + } + else { + return div(result_type(d), result_type(num_vertices(g))); + } + } + Divides div; +}; + +// The Page type stores the name of each vertex in the graph and +// represents web pages that can be navigated to. +struct WebPage +{ + string name; +}; + +// The Link type stores an associated probability of traveling +// from one page to another. +struct Link +{ + float probability; +}; + +// Declare the graph type and its vertex and edge types. +typedef directed_graph Graph; +typedef graph_traits::vertex_descriptor Vertex; +typedef graph_traits::edge_descriptor Edge; + +// The name map provides an abstract accessor for the names of +// each vertex. This is used during graph creation. +typedef property_map::type NameMap; + +// Declare a matrix type and its corresponding property map that +// will contain the distances between each pair of vertices. +typedef exterior_vertex_property DistanceProperty; +typedef DistanceProperty::matrix_type DistanceMatrix; +typedef DistanceProperty::matrix_map_type DistanceMatrixMap; + +// Declare the weight map as an accessor into the bundled +// edge property. +typedef property_map::type WeightMap; + +// Declare a container and its corresponding property map that +// will contain the resulting mean geodesic distances of each +// vertex in the graph. +typedef exterior_vertex_property GeodesicProperty; +typedef GeodesicProperty::container_type GeodesicContainer; +typedef GeodesicProperty::map_type GeodesicMap; + +static float exclusive_geodesics(const Graph&, DistanceMatrixMap, GeodesicMap); +static float inclusive_geodesics(const Graph&, DistanceMatrixMap, GeodesicMap); + +int +main(int argc, char *argv[]) +{ + // Create the graph, a name map that providse abstract access + // to the web page names, and the weight map as an accessor to + // the edge weights (or probabilities). + Graph g; + NameMap nm(get(&WebPage::name, g)); + WeightMap wm(get(&Link::probability, g)); + + // Read the weighted graph from standard input. + read_weighted_graph(g, nm, wm, cin); + + // Compute the distances between all pairs of vertices using + // the Floyd-Warshall algorithm. The weight map was created + // above so it could be populated when the graph was read in. + DistanceMatrix distances(num_vertices(g)); + DistanceMatrixMap dm(distances, g); + floyd_warshall_all_pairs_shortest_paths(g, dm, weight_map(wm)); + + // Create the containers and the respective property maps that + // will contain the mean geodesics averaged both including + // self-loop distances and excluding them. + GeodesicContainer exclude(num_vertices(g)); + GeodesicContainer include(num_vertices(g)); + GeodesicMap exmap(exclude, g); + GeodesicMap inmap(include, g); + + float ex = exclusive_geodesics(g, dm, exmap); + float in = inclusive_geodesics(g, dm, inmap); + + // 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; + graph_traits::vertex_iterator i, end; + for(tie(i, end) = vertices(g); i != end; ++i) { + cout << setw(12) << setiosflags(ios::left) + << g[*i].name + << 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; + + return 0; +} + +float +exclusive_geodesics(const Graph& g, DistanceMatrixMap dm, GeodesicMap gm) +{ + // Compute the mean geodesic distances, which excludes distances + // of self-loops by default. Return the measure for the entire graph. + return all_mean_geodesics(g, dm, gm); +} + + +float +inclusive_geodesics(const Graph &g, DistanceMatrixMap dm, GeodesicMap gm) +{ + // Create a new measure object for computing the mean geodesic + // distance of all vertices. This measure will actually be used + // for both averages. + inclusive_average m; + + // Compute the mean geodesic distance using the inclusive average + // to account for self-loop distances. Return the measure for the + // entire graph. + return all_mean_geodesics(g, dm, gm, m); +} +//] diff --git a/examples/influence_prestige.cpp b/examples/influence_prestige.cpp new file mode 100644 index 00000000..348b0d16 --- /dev/null +++ b/examples/influence_prestige.cpp @@ -0,0 +1,75 @@ +// (C) Copyright Andrew Sutton 2007 +// +// 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) + +//[influence_prestige_example +#include +#include + +#include +#include +#include + +#include "helper.hpp" + +using namespace std; +using namespace boost; + +// The Actor type stores the name of each vertex in the graph. +struct Actor +{ + string name; +}; + +// Declare the graph type and its vertex and edge types. +typedef directed_graph Graph; +typedef graph_traits::vertex_descriptor Vertex; +typedef graph_traits::edge_descriptor Edge; + +// The name map provides an abstract accessor for the names of +// each vertex. This is used during graph creation. +typedef property_map::type NameMap; + +// Declare a container type for influence and prestige (both +// of which are degree centralities) and its corresponding +// property map. +typedef exterior_vertex_property CentralityProperty; +typedef CentralityProperty::container_type CentralityContainer; +typedef CentralityProperty::map_type CentralityMap; + +int +main(int argc, char *argv[]) +{ + // Create the graph and a property map that provides + // access to the actor names. + Graph g; + NameMap nm(get(&Actor::name, g)); + + // Read the graph from standard input. + read_graph(g, nm, cin); + + // Compute the influence for the graph. + CentralityContainer influence(num_vertices(g)); + CentralityMap im(influence, g); + all_influence_values(g, im); + + // Compute the influence for the graph. + CentralityContainer prestige(num_vertices(g)); + CentralityMap pm(prestige, g); + all_prestige_values(g, pm); + + // Print the degree centrality of each vertex + graph_traits::vertex_iterator i, end; + for(tie(i, end) = vertices(g); i != end; ++i) { + Vertex v = *i; + cout << setiosflags(ios::left) << setw(12) + << g[v].name << "\t" + << im[v] << "\t" + << pm[v] << endl; + } + + return 0; +} +//] diff --git a/examples/info_network.graph b/examples/info_network.graph new file mode 100644 index 00000000..8cc8b4d5 --- /dev/null +++ b/examples/info_network.graph @@ -0,0 +1,11 @@ +myspace,digg +blogger,digg +blogger,slahsdot +blogger,wikipedia +digg,slashdot +digg,wikipedia +blogspot,slashdot +blogspot,wikipedia +slashdot,bbc +slashdot,wikipedia +bbc,wikipedia \ No newline at end of file diff --git a/examples/mean_geodesic.cpp b/examples/mean_geodesic.cpp new file mode 100644 index 00000000..a6b31a78 --- /dev/null +++ b/examples/mean_geodesic.cpp @@ -0,0 +1,90 @@ +// (C) Copyright Andrew Sutton 2007 +// +// 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) + +//[mean_geodesic_example +#include +#include + +#include +#include +#include +#include +#include +#include "helper.hpp" + +using namespace std; +using namespace boost; + +// The Actor type stores the name of each vertex in the graph. +struct Actor +{ + string name; +}; + +// Declare the graph type and its vertex and edge types. +typedef undirected_graph Graph; +typedef graph_traits::vertex_descriptor Vertex; +typedef graph_traits::edge_descriptor Edge; + +// The name map provides an abstract accessor for the names of +// each vertex. This is used during graph creation. +typedef property_map::type NameMap; + +// Declare a matrix type and its corresponding property map that +// will contain the distances between each pair of vertices. +typedef exterior_vertex_property DistanceProperty; +typedef DistanceProperty::matrix_type DistanceMatrix; +typedef DistanceProperty::matrix_map_type DistanceMatrixMap; + +// Declare the weight map so that each edge returns the same value. +typedef constant_property_map WeightMap; + +// Declare a container and its corresponding property map that +// will contain the resulting mean geodesic distances of each +// vertex in the graph. +typedef exterior_vertex_property GeodesicProperty; +typedef GeodesicProperty::container_type GeodesicContainer; +typedef GeodesicProperty::map_type GeodesicMap; + +int +main(int argc, char *argv[]) +{ + // Create the graph and a property map that provides access + // to the actor names. + Graph g; + NameMap nm(get(&Actor::name, g)); + + // Read the graph from standad input. + read_graph(g, nm, cin); + + // Compute the distances between all pairs of vertices using + // the Floyd-Warshall algorithm. Note that the weight map is + // created so that every edge has a weight of 1. + DistanceMatrix distances(num_vertices(g)); + DistanceMatrixMap dm(distances, g); + WeightMap wm(1); + floyd_warshall_all_pairs_shortest_paths(g, dm, weight_map(wm)); + + // Compute the mean geodesic distances for each vertex in + // the graph and get the average mean geodesic distace (the + // so-called small-world distance) as a result. + GeodesicContainer geodesics(num_vertices(g)); + GeodesicMap gm(geodesics, g); + float sw = all_mean_geodesics(g, dm, gm); + + // 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) { + cout << setw(12) << setiosflags(ios::left) + << g[*i].name << get(gm, *i) << endl; + } + cout << "small world distance: " << sw << endl; + + + return 0; +} +//] diff --git a/examples/prism_3_2.graph b/examples/prism_3_2.graph new file mode 100644 index 00000000..dcb84c86 --- /dev/null +++ b/examples/prism_3_2.graph @@ -0,0 +1,16 @@ +0,1 +1,2 +2,0 + +3,4 +4,5 +5,3 + +0,3 +3,0 + +1,4 +4,1 + +2,5 +5,2 \ No newline at end of file diff --git a/examples/prob_network.graph b/examples/prob_network.graph new file mode 100644 index 00000000..c5cf790b --- /dev/null +++ b/examples/prob_network.graph @@ -0,0 +1,18 @@ +myspace,myspace,.5 +myspace,digg,.5 +blogger,digg,.33 +blogger,slashdot,.33 +blogger,wikipedia,.33 +digg,slashdot,.33 +digg,wikipedia,.33 +digg,digg,.33 +blogspot,slashdot,.5 +blogspot,wikipedia,.5 +slashdot,bbc,.5 +slashdot,wikipedia,.5 +bbc,wikipedia,.5 +bbc,bbc,.5 +wikipedia,wikipedia,.25 +wikipedia,blogger,.25 +wikipedia,myspace,.25 +wikipedia,blogspot,.25 \ No newline at end of file diff --git a/examples/scaled_closeness_centrality.cpp b/examples/scaled_closeness_centrality.cpp new file mode 100644 index 00000000..c7581cc0 --- /dev/null +++ b/examples/scaled_closeness_centrality.cpp @@ -0,0 +1,115 @@ +// (C) Copyright Andrew Sutton 2007 +// +// 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) + +//[scaled_closeness_centrality_example +#include +#include + +#include +#include +#include +#include +#include +#include "helper.hpp" + +using namespace std; +using namespace boost; + +// This template struct provides a generic version of a "scaling" +// closeness measure. Specifically, this implementation divides +// the number of vertices in the graph by the sum of geodesic +// distances of each vertex. This measure allows customization +// of the distance type, result type, and even the underlying +// divide operation. +template > +struct scaled_closeness_measure +{ + typedef Distance distance_type; + typedef Result result_type; + + Result operator ()(Distance d, const Graph& g) + { + if(d == numeric_values::infinity()) { + return numeric_values::zero(); + } + else { + return div(Result(num_vertices(g)), Result(d)); + } + } + Divide div; +}; + +// The Actor type stores the name of each vertex in the graph. +struct Actor +{ + std::string name; +}; + +// Declare the graph type and its vertex and edge types. +typedef undirected_graph Graph; +typedef graph_traits::vertex_descriptor Vertex; +typedef graph_traits::edge_descriptor Edge; + +// The name map provides an abstract accessor for the names of +// each vertex. This is used during graph creation. +typedef property_map::type NameMap; + +// Declare a matrix type and its corresponding property map that +// will contain the distances between each pair of vertices. +typedef exterior_vertex_property DistanceProperty; +typedef DistanceProperty::matrix_type DistanceMatrix; +typedef DistanceProperty::matrix_map_type DistanceMatrixMap; + +// Declare the weight map so that each edge returns the same value. +typedef constant_property_map WeightMap; + +// Declare a container and its corresponding property map that +// will contain the resulting closeness centralities of each +// vertex in the graph. +typedef boost::exterior_vertex_property ClosenessProperty; +typedef ClosenessProperty::container_type ClosenessContainer; +typedef ClosenessProperty::map_type ClosenessMap; + +int +main(int argc, char *argv[]) +{ + // Create the graph and a property map that provides access + // to the actor names. + Graph g; + NameMap nm(get(&Actor::name, g)); + + // Read the graph from standard input. + read_graph(g, nm, cin); + + // Compute the distances between all pairs of vertices using + // the Floyd-Warshall algorithm. Note that the weight map is + // created so that every edge has a weight of 1. + DistanceMatrix distances(num_vertices(g)); + DistanceMatrixMap dm(distances, g); + WeightMap wm(1); + floyd_warshall_all_pairs_shortest_paths(g, dm, weight_map(wm)); + + // Create the scaled closeness measure. + scaled_closeness_measure m; + + // Compute the degree centrality for graph + ClosenessContainer cents(num_vertices(g)); + ClosenessMap cm(cents, g); + all_closeness_centralities(g, dm, cm, m); + + // 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) + << g[*i].name << get(cm, *i) << endl; + } + + return 0; +} +//] diff --git a/examples/social_network.graph b/examples/social_network.graph new file mode 100644 index 00000000..33779ba1 --- /dev/null +++ b/examples/social_network.graph @@ -0,0 +1,12 @@ +Scott,Jill +Mary,Scott +Jill,Mary +Bill,Scott +Josh,Bill +Scott,Frank +Laurie,Frank +Mary,Laurie +Anne,Frank +Howard,Anne +Frank,Howard +Josh,Frank \ No newline at end of file diff --git a/examples/tiernan_girth_circumference.cpp b/examples/tiernan_girth_circumference.cpp new file mode 100644 index 00000000..06a996ab --- /dev/null +++ b/examples/tiernan_girth_circumference.cpp @@ -0,0 +1,40 @@ +// (C) Copyright Andrew Sutton 2007 +// +// 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) + +//[tiernan_girth_circumference +#include + +#include +#include + +#include "helper.hpp" + +using namespace std; +using namespace boost; + +// Declare the graph type and its vertex and edge types. +typedef directed_graph<> Graph; +typedef graph_traits::vertex_descriptor Vertex; +typedef graph_traits::edge_descriptor Edge; + +int +main(int argc, char *argv[]) +{ + // Create the graph and read it from standard input. + Graph g; + read_graph(g, cin); + + // Compute the girth and circumference simulataneously + size_t girth, circ; + tie(girth, circ) = tiernan_girth_and_circumference(g); + + // Print the result + cout << "girth: " << girth << endl; + cout << "circumference: " << circ << endl; + + return 0; +} +//] diff --git a/examples/tiernan_print_cycles.cpp b/examples/tiernan_print_cycles.cpp new file mode 100644 index 00000000..c4375615 --- /dev/null +++ b/examples/tiernan_print_cycles.cpp @@ -0,0 +1,68 @@ +// (C) Copyright Andrew Sutton 2007 +// +// 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) + +//[tiernan_print_cycles +#include + +#include +#include + +#include "helper.hpp" + +using namespace std; +using namespace boost; + +// The cycle_printer is a visitor that will print the path that comprises +// the cycle. Note that the back() vertex of the path is not the same as +// the front(). It is implicit in the listing of vertices that the back() +// vertex is connected to the front(). +template +struct cycle_printer +{ + cycle_printer(OutputStream& stream) + : os(stream) + { } + + template + void cycle(const Path& p, const Graph& g) + { + // Get the property map containing the vertex indices + // so we can print them. + typedef typename property_map::const_type IndexMap; + IndexMap indices = get(vertex_index, g); + + // Iterate over path printing each vertex that forms the cycle. + typename Path::const_iterator i, end = p.end(); + for(i = p.begin(); i != end; ++i) { + os << get(indices, *i) << " "; + } + os << endl; + } + OutputStream& os; +}; + +// Declare the graph type and its vertex and edge types. +typedef directed_graph<> Graph; +typedef graph_traits::vertex_descriptor Vertex; +typedef graph_traits::edge_descriptor Edge; + +int +main(int argc, char *argv[]) +{ + // Create the graph and read it from standard input. + Graph g; + read_graph(g, cin); + + // Instantiate the visitor for printing cycles + cycle_printer vis(cout); + + // Use the Tiernan algorithm to visit all cycles, printing them + // as they are found. + tiernan_all_cycles(g, vis); + + return 0; +} +//] From 71e23c23049e04021b5d6f6a153bc733732d6827 Mon Sep 17 00:00:00 2001 From: Andrew Sutton Date: Sat, 14 Feb 2009 14:26:02 +0000 Subject: [PATCH 097/224] Fixing doc build, updating doc headers [SVN r51252] --- quickbook/Jamfile.v2 | 74 +++---------------- quickbook/concepts/a_star_visitor.qbk | 2 +- quickbook/concepts/adjacency_graph.qbk | 2 +- quickbook/concepts/adjacency_matrix.qbk | 2 +- quickbook/concepts/bellman_ford_visitor.qbk | 2 +- quickbook/concepts/bfs_visitor.qbk | 2 +- quickbook/concepts/bidirectional_graph.qbk | 2 +- quickbook/concepts/clique_visitor.qbk | 2 +- quickbook/concepts/concepts.qbk | 2 +- quickbook/concepts/cycle_visitor.qbk | 2 +- quickbook/concepts/degree_measure.qbk | 2 +- quickbook/concepts/descriptor.qbk | 2 +- quickbook/concepts/dfs_visitor.qbk | 2 +- quickbook/concepts/dijkstra_visitor.qbk | 2 +- quickbook/concepts/distance_measure.qbk | 2 +- quickbook/concepts/edge_index_graph.qbk | 7 +- quickbook/concepts/edge_list_graph.qbk | 2 +- quickbook/concepts/event_visitor.qbk | 2 +- quickbook/concepts/event_visitor_list.qbk | 2 +- quickbook/concepts/graph.qbk | 2 +- quickbook/concepts/graphs.qbk | 2 +- quickbook/concepts/incidence_graph.qbk | 2 +- quickbook/concepts/mutable_graph.qbk | 4 +- quickbook/concepts/mutable_property_graph.qbk | 2 +- quickbook/concepts/numeric_value.qbk | 2 +- quickbook/concepts/property_graph.qbk | 2 +- quickbook/concepts/utility.qbk | 2 +- quickbook/concepts/vertex_index_graph.qbk | 7 +- quickbook/concepts/vertex_list_graph.qbk | 2 +- quickbook/concepts/visitor.qbk | 2 +- quickbook/concepts/visitors.qbk | 2 +- quickbook/reference/reference.qbk | 2 + 32 files changed, 45 insertions(+), 103 deletions(-) diff --git a/quickbook/Jamfile.v2 b/quickbook/Jamfile.v2 index ddc0aeb0..d821b3e4 100644 --- a/quickbook/Jamfile.v2 +++ b/quickbook/Jamfile.v2 @@ -3,7 +3,6 @@ # 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) -using quickbook ; xml graph : graph.qbk ; @@ -11,74 +10,21 @@ boostbook standalone : graph : - # HTML options first: - # Use graphics not text for navigation: - navig.graphics=1 - # How far down we chunk nested sections, basically all of them: - # Setting this to 4 will put all reference functions into the - # same page... and make all external links to those pages bounce - # to the top of them. + boost.root=../../../.. + boost.libraries=../../../../libs/libraries.htm + # boost.logo=../boost.png + + html.stylesheet=../../../../doc/html/boostbook.css + + # ToC and chunking chunk.section.depth=5 - # Don't put the first section on the same page as the TOC: chunk.first.sections=1 - # How far down sections get TOC's toc.section.depth=5 - # Max depth in each TOC: - # I could increase this, but that makes the top-level ToC - # extremely long. toc.max.depth=3 - # How far down we go with TOC's generate.section.toc.level=5 - # Logo location: - boost.logo=../boost.png + + # Misc options + navig.graphics=1 annotation.support=1 - # The page style - page.style="'website'" - # Show chapters select box - grouped.links.chapters.show="'true'" - # GroupedLinks xml definition chapters location - grouped.links.chapters.xml="'boost_libs_grouped_links.xml'" - # Select the base url for the chapters GroupedLinks - grouped.links.chapters.url="'http://www.boost.org/libs/'" - # Show sections select box - grouped.links.sections.show="'true'" - # GroupedLinks xml definition sections location - grouped.links.sections.xml="'sections_grouped_links.xml'" - # Select the base url for the chapters GroupedLinks - grouped.links.sections.url="'./'" - # Show the Google Search Box - search.box.show="'true'" - # Location of the cse defintion - search.box.cse.definition.src="'http://www.drivehq.com/web/matias.capeletto/bimap/doc/html/context8.xml'" - - # PDF Options: - # TOC Generation: this is needed for FOP-0.9 and later: - # fop1.extensions=1 - xep.extensions=1 - # TOC generation: this is needed for FOP 0.2, but must not be set to zero for FOP-0.9! - fop.extensions=0 - # No indent on body text: - body.start.indent=0pt - # Margin size: - page.margin.inner=0.5in - # Margin size: - page.margin.outer=0.5in - # Yes, we want graphics for admonishments: - admon.graphics=1 - # Set this one for PDF generation *only*: - # default pnd graphics are awful in PDF form, - # better use SVG's instead: - #admon.graphics.extension=".svg" ; - - - - - - - - - - - diff --git a/quickbook/concepts/a_star_visitor.qbk b/quickbook/concepts/a_star_visitor.qbk index 3c5fdeb2..c0f48917 100644 --- a/quickbook/concepts/a_star_visitor.qbk +++ b/quickbook/concepts/a_star_visitor.qbk @@ -1,5 +1,5 @@ [/ - / Copyright (c) 2007 Andrew Sutton + / Copyright (C) 2007-2009 Andrew Sutton / / 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) diff --git a/quickbook/concepts/adjacency_graph.qbk b/quickbook/concepts/adjacency_graph.qbk index 50369665..da1e2e3e 100644 --- a/quickbook/concepts/adjacency_graph.qbk +++ b/quickbook/concepts/adjacency_graph.qbk @@ -1,5 +1,5 @@ [/ - / Copyright (c) 2007 Andrew Sutton + / Copyright (C) 2007-2009 Andrew Sutton / / 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) diff --git a/quickbook/concepts/adjacency_matrix.qbk b/quickbook/concepts/adjacency_matrix.qbk index 17f64da9..27b740ce 100644 --- a/quickbook/concepts/adjacency_matrix.qbk +++ b/quickbook/concepts/adjacency_matrix.qbk @@ -1,5 +1,5 @@ [/ - / Copyright (c) 2007 Andrew Sutton + / Copyright (C) 2007-2009 Andrew Sutton / / 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) diff --git a/quickbook/concepts/bellman_ford_visitor.qbk b/quickbook/concepts/bellman_ford_visitor.qbk index fc3cbed5..e929e191 100644 --- a/quickbook/concepts/bellman_ford_visitor.qbk +++ b/quickbook/concepts/bellman_ford_visitor.qbk @@ -1,5 +1,5 @@ [/ - / Copyright (c) 2007 Andrew Sutton + / Copyright (C) 2007-2009 Andrew Sutton / / 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) diff --git a/quickbook/concepts/bfs_visitor.qbk b/quickbook/concepts/bfs_visitor.qbk index a4e5a308..e8621518 100644 --- a/quickbook/concepts/bfs_visitor.qbk +++ b/quickbook/concepts/bfs_visitor.qbk @@ -1,5 +1,5 @@ [/ - / Copyright (c) 2007 Andrew Sutton + / Copyright (C) 2007-2009 Andrew Sutton / / 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) diff --git a/quickbook/concepts/bidirectional_graph.qbk b/quickbook/concepts/bidirectional_graph.qbk index a645c3f4..57b68cf1 100644 --- a/quickbook/concepts/bidirectional_graph.qbk +++ b/quickbook/concepts/bidirectional_graph.qbk @@ -1,5 +1,5 @@ [/ - / Copyright (c) 2007 Andrew Sutton + / Copyright (C) 2007-2009 Andrew Sutton / / 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) diff --git a/quickbook/concepts/clique_visitor.qbk b/quickbook/concepts/clique_visitor.qbk index 00bc977a..40185d1f 100644 --- a/quickbook/concepts/clique_visitor.qbk +++ b/quickbook/concepts/clique_visitor.qbk @@ -1,5 +1,5 @@ [/ - / Copyright (c) 2007 Andrew Sutton + / Copyright (C) 2007-2009 Andrew Sutton / / 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) diff --git a/quickbook/concepts/concepts.qbk b/quickbook/concepts/concepts.qbk index f4a39927..d23f3ad6 100644 --- a/quickbook/concepts/concepts.qbk +++ b/quickbook/concepts/concepts.qbk @@ -1,5 +1,5 @@ [/ - / Copyright (c) 2007 Andrew Sutton + / Copyright (C) 2007-2009 Andrew Sutton / / 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) diff --git a/quickbook/concepts/cycle_visitor.qbk b/quickbook/concepts/cycle_visitor.qbk index 4511d836..2a3233a8 100644 --- a/quickbook/concepts/cycle_visitor.qbk +++ b/quickbook/concepts/cycle_visitor.qbk @@ -1,5 +1,5 @@ [/ - / Copyright (c) 2007 Andrew Sutton + / Copyright (C) 2007-2009 Andrew Sutton / / 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) diff --git a/quickbook/concepts/degree_measure.qbk b/quickbook/concepts/degree_measure.qbk index 1b59b14d..7c758b71 100644 --- a/quickbook/concepts/degree_measure.qbk +++ b/quickbook/concepts/degree_measure.qbk @@ -1,5 +1,5 @@ [/ - / Copyright (c) 2007 Andrew Sutton + / Copyright (C) 2007-2009 Andrew Sutton / / 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) diff --git a/quickbook/concepts/descriptor.qbk b/quickbook/concepts/descriptor.qbk index fa79cd89..a13fcb7d 100644 --- a/quickbook/concepts/descriptor.qbk +++ b/quickbook/concepts/descriptor.qbk @@ -1,5 +1,5 @@ [/ - / Copyright (c) 2007 Andrew Sutton + / Copyright (C) 2007-2009 Andrew Sutton / / 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) diff --git a/quickbook/concepts/dfs_visitor.qbk b/quickbook/concepts/dfs_visitor.qbk index 487abd9d..6ae79193 100644 --- a/quickbook/concepts/dfs_visitor.qbk +++ b/quickbook/concepts/dfs_visitor.qbk @@ -1,5 +1,5 @@ [/ - / Copyright (c) 2007 Andrew Sutton + / Copyright (C) 2007-2009 Andrew Sutton / / 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) diff --git a/quickbook/concepts/dijkstra_visitor.qbk b/quickbook/concepts/dijkstra_visitor.qbk index 09b03639..aa331a13 100644 --- a/quickbook/concepts/dijkstra_visitor.qbk +++ b/quickbook/concepts/dijkstra_visitor.qbk @@ -1,5 +1,5 @@ [/ - / Copyright (c) 2007 Andrew Sutton + / Copyright (C) 2007-2009 Andrew Sutton / / 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) diff --git a/quickbook/concepts/distance_measure.qbk b/quickbook/concepts/distance_measure.qbk index a5232e2a..f12f0747 100644 --- a/quickbook/concepts/distance_measure.qbk +++ b/quickbook/concepts/distance_measure.qbk @@ -1,5 +1,5 @@ [/ - / Copyright (c) 2007 Andrew Sutton + / Copyright (C) 2007-2009 Andrew Sutton / / 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) diff --git a/quickbook/concepts/edge_index_graph.qbk b/quickbook/concepts/edge_index_graph.qbk index d736f2f6..20c5b9d2 100644 --- a/quickbook/concepts/edge_index_graph.qbk +++ b/quickbook/concepts/edge_index_graph.qbk @@ -1,5 +1,5 @@ [/ - / Copyright (c) 2007 Andrew Sutton + / Copyright (C) 2007-2009 Andrew Sutton / / 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) @@ -77,10 +77,7 @@ this concept must also provide functions that allow them to re-index the edges. [ [Edge Index Property] [`get(edge_index,g)`] - [ - `P::type` or[br] - `P::const_type` - ] + [`P::type` or `P::const_type`] [ Returns the property map that provides read/write access to the edge indices of the graph. diff --git a/quickbook/concepts/edge_list_graph.qbk b/quickbook/concepts/edge_list_graph.qbk index 2d0de24b..a4bfdff5 100644 --- a/quickbook/concepts/edge_list_graph.qbk +++ b/quickbook/concepts/edge_list_graph.qbk @@ -1,5 +1,5 @@ [/ - / Copyright (c) 2007 Andrew Sutton + / Copyright (C) 2007-2009 Andrew Sutton / / 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) diff --git a/quickbook/concepts/event_visitor.qbk b/quickbook/concepts/event_visitor.qbk index f623362e..eda894c7 100644 --- a/quickbook/concepts/event_visitor.qbk +++ b/quickbook/concepts/event_visitor.qbk @@ -1,5 +1,5 @@ [/ - / Copyright (c) 2007 Andrew Sutton + / Copyright (C) 2007-2009 Andrew Sutton / / 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) diff --git a/quickbook/concepts/event_visitor_list.qbk b/quickbook/concepts/event_visitor_list.qbk index 0846cdfc..a335fddd 100644 --- a/quickbook/concepts/event_visitor_list.qbk +++ b/quickbook/concepts/event_visitor_list.qbk @@ -1,5 +1,5 @@ [/ - / Copyright (c) 2007 Andrew Sutton + / Copyright (C) 2007-2009 Andrew Sutton / / 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) diff --git a/quickbook/concepts/graph.qbk b/quickbook/concepts/graph.qbk index 3c5fdeb2..c0f48917 100644 --- a/quickbook/concepts/graph.qbk +++ b/quickbook/concepts/graph.qbk @@ -1,5 +1,5 @@ [/ - / Copyright (c) 2007 Andrew Sutton + / Copyright (C) 2007-2009 Andrew Sutton / / 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) diff --git a/quickbook/concepts/graphs.qbk b/quickbook/concepts/graphs.qbk index 15eba8c1..a58e3bd5 100644 --- a/quickbook/concepts/graphs.qbk +++ b/quickbook/concepts/graphs.qbk @@ -1,5 +1,5 @@ [/ - / Copyright (c) 2007 Andrew Sutton + / Copyright (C) 2007-2009 Andrew Sutton / / 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) diff --git a/quickbook/concepts/incidence_graph.qbk b/quickbook/concepts/incidence_graph.qbk index 329541c1..3c892e44 100644 --- a/quickbook/concepts/incidence_graph.qbk +++ b/quickbook/concepts/incidence_graph.qbk @@ -1,5 +1,5 @@ [/ - / Copyright (c) 2007 Andrew Sutton + / Copyright (C) 2007-2009 Andrew Sutton / / 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) diff --git a/quickbook/concepts/mutable_graph.qbk b/quickbook/concepts/mutable_graph.qbk index 338ddea8..900d9ca3 100644 --- a/quickbook/concepts/mutable_graph.qbk +++ b/quickbook/concepts/mutable_graph.qbk @@ -1,5 +1,5 @@ -b[/ - / Copyright (c) 2007 Andrew Sutton +[/ + / Copyright (C) 2007-2009 Andrew Sutton / / 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) diff --git a/quickbook/concepts/mutable_property_graph.qbk b/quickbook/concepts/mutable_property_graph.qbk index 4a7e58b0..74f3ee12 100644 --- a/quickbook/concepts/mutable_property_graph.qbk +++ b/quickbook/concepts/mutable_property_graph.qbk @@ -1,5 +1,5 @@ [/ - / Copyright (c) 2007 Andrew Sutton + / Copyright (C) 2007-2009 Andrew Sutton / / 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) diff --git a/quickbook/concepts/numeric_value.qbk b/quickbook/concepts/numeric_value.qbk index 360a00fa..53c63fd2 100644 --- a/quickbook/concepts/numeric_value.qbk +++ b/quickbook/concepts/numeric_value.qbk @@ -1,5 +1,5 @@ [/ - / Copyright (c) 2007 Andrew Sutton + / Copyright (C) 2007-2009 Andrew Sutton / / 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) diff --git a/quickbook/concepts/property_graph.qbk b/quickbook/concepts/property_graph.qbk index 054f409e..f8148ceb 100644 --- a/quickbook/concepts/property_graph.qbk +++ b/quickbook/concepts/property_graph.qbk @@ -1,5 +1,5 @@ [/ - / Copyright (c) 2007 Andrew Sutton + / Copyright (C) 2007-2009 Andrew Sutton / / 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) diff --git a/quickbook/concepts/utility.qbk b/quickbook/concepts/utility.qbk index b1f66680..88bde678 100644 --- a/quickbook/concepts/utility.qbk +++ b/quickbook/concepts/utility.qbk @@ -1,5 +1,5 @@ [/ - / Copyright (c) 2007 Andrew Sutton + / Copyright (C) 2007-2009 Andrew Sutton / / 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) diff --git a/quickbook/concepts/vertex_index_graph.qbk b/quickbook/concepts/vertex_index_graph.qbk index a56064ca..1fe8c5e6 100644 --- a/quickbook/concepts/vertex_index_graph.qbk +++ b/quickbook/concepts/vertex_index_graph.qbk @@ -1,5 +1,5 @@ [/ - / Copyright (c) 2007 Andrew Sutton + / Copyright (C) 2007-2009 Andrew Sutton / / 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) @@ -77,10 +77,7 @@ this concept must also provide functions that allow them to re-index the vertice [ [Vertex Index Property] [`get(vertex_index,g)`] - [ - `P::type` or[br] - `P::const_type` - ] + [`P::type` or `P::const_type`] [ Returns the property map that provides read/write access to the vertex indices of the graph. diff --git a/quickbook/concepts/vertex_list_graph.qbk b/quickbook/concepts/vertex_list_graph.qbk index 01cacd86..82704272 100644 --- a/quickbook/concepts/vertex_list_graph.qbk +++ b/quickbook/concepts/vertex_list_graph.qbk @@ -1,5 +1,5 @@ [/ - / Copyright (c) 2007 Andrew Sutton + / Copyright (C) 2007-2009 Andrew Sutton / / 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) diff --git a/quickbook/concepts/visitor.qbk b/quickbook/concepts/visitor.qbk index b6d51997..26b1598e 100644 --- a/quickbook/concepts/visitor.qbk +++ b/quickbook/concepts/visitor.qbk @@ -1,5 +1,5 @@ [/ - / Copyright (c) 2007 Andrew Sutton + / Copyright (C) 2007-2009 Andrew Sutton / / 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) diff --git a/quickbook/concepts/visitors.qbk b/quickbook/concepts/visitors.qbk index 5babc1b3..16ac9431 100644 --- a/quickbook/concepts/visitors.qbk +++ b/quickbook/concepts/visitors.qbk @@ -1,5 +1,5 @@ [/ - / Copyright (c) 2007 Andrew Sutton + / Copyright (C) 2007-2009 Andrew Sutton / / 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) diff --git a/quickbook/reference/reference.qbk b/quickbook/reference/reference.qbk index 82118cfd..4c835013 100644 --- a/quickbook/reference/reference.qbk +++ b/quickbook/reference/reference.qbk @@ -19,11 +19,13 @@ [endsect] [section Event Visitor List Adaptors] +[/ [include bfs_visitor.qbk] [include dfs_visitor.qbk] [include dijkstra_visitor.qbk] [include bellman_visitor.qbk] [include astar_visitor.qbk] +/] [endsect] [section Event Visitors] From dd5aff7029aeb2ef9e800a76cd7e8534d8d84511 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=BCrgen=20Hunold?= Date: Tue, 3 Mar 2009 07:56:36 +0000 Subject: [PATCH 098/224] Fix: Avoid compiler warning if BOOST_NO_HASH is already defined. [SVN r51550] --- test/subgraph_bundled.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/test/subgraph_bundled.cpp b/test/subgraph_bundled.cpp index c1c5aed1..6b5b326c 100644 --- a/test/subgraph_bundled.cpp +++ b/test/subgraph_bundled.cpp @@ -8,7 +8,9 @@ #include -#define BOOST_NO_HASH +#if !defined(BOOST_NO_HASH) +# define BOOST_NO_HASH +#endif #include #include From eaf4275c610c5ea7a3b0d142df9d0340c13d429b Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Wed, 1 Apr 2009 16:01:43 +0000 Subject: [PATCH 099/224] Renamed some functions to work better on some compilers [SVN r52108] --- test/csr_graph_test.cpp | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/test/csr_graph_test.cpp b/test/csr_graph_test.cpp index 67bea538..6bd3e334 100644 --- a/test/csr_graph_test.cpp +++ b/test/csr_graph_test.cpp @@ -169,7 +169,7 @@ void check_consistency(const CSRGraphT& g) { } template -void test(const OrigGraph& g) +void graph_test(const OrigGraph& g) { // Check copying of a graph CSRGraphT g2(g); @@ -308,12 +308,12 @@ void test(const OrigGraph& g) get(boost::edge_index, g3)))); } -void test(int nnodes, double density, int seed) +void graph_test(int nnodes, double density, int seed) { boost::minstd_rand gen(seed); std::cout << "Testing " << nnodes << " density " << density << std::endl; GraphT g(ERGen(gen, nnodes, density), ERGen(), nnodes); - test(g); + graph_test(g); } void test_graph_properties() @@ -377,13 +377,13 @@ int test_main(int argc, char* argv[]) { std::cout << "Testing empty graph" << std::endl; CSRGraphT g; - test(g); + graph_test(g); } - // test(1000, 0.05, seed); - // test(1000, 0.0, seed); - // test(1000, 0.1, seed); - test(1000, 0.001, seed); - test(1000, 0.0005, seed); + // graph_test(1000, 0.05, seed); + // graph_test(1000, 0.0, seed); + // graph_test(1000, 0.1, seed); + graph_test(1000, 0.001, seed); + graph_test(1000, 0.0005, seed); { std::cout << "Testing partially constructed CSR graph" << std::endl; CSRGraphT g; @@ -398,7 +398,7 @@ int test_main(int argc, char* argv[]) for (boost::tie(ei, ei_end) = edges(g); ei != ei_end; ++ei) { BOOST_CHECK(edge_from_index(get(boost::edge_index, g, *ei), g) == *ei); } - test(g); + graph_test(g); } test_graph_properties(); From 5a3b472a508ab4b2f42cb57b24137f0a8458fb28 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Wed, 1 Apr 2009 16:03:21 +0000 Subject: [PATCH 100/224] First batch of merges from Parallel BGL [SVN r52110] --- include/boost/graph/adjacency_list.hpp | 5 +- .../boost/graph/betweenness_centrality.hpp | 6 +- include/boost/graph/breadth_first_search.hpp | 9 +- .../graph/compressed_sparse_row_graph.hpp | 27 +++ include/boost/graph/depth_first_search.hpp | 3 - include/boost/graph/detail/adjacency_list.hpp | 8 +- .../boost/graph/dijkstra_shortest_paths.hpp | 8 +- include/boost/graph/erdos_renyi_generator.hpp | 46 ++--- include/boost/graph/fruchterman_reingold.hpp | 6 +- include/boost/graph/graph_utility.hpp | 27 +++ include/boost/graph/graphviz.hpp | 2 +- include/boost/graph/named_function_params.hpp | 5 + include/boost/graph/plod_generator.hpp | 180 +++++++++++++----- include/boost/graph/properties.hpp | 52 +++-- 14 files changed, 274 insertions(+), 110 deletions(-) diff --git a/include/boost/graph/adjacency_list.hpp b/include/boost/graph/adjacency_list.hpp index 2b7b5d05..eedda09d 100644 --- a/include/boost/graph/adjacency_list.hpp +++ b/include/boost/graph/adjacency_list.hpp @@ -285,14 +285,13 @@ namespace boost { typedef typename parallel_edge_traits::type edge_parallel_category; + typedef std::size_t vertices_size_type; typedef void* vertex_ptr; typedef typename mpl::if_::type vertex_descriptor; + vertices_size_type, vertex_ptr>::type vertex_descriptor; typedef detail::edge_desc_impl edge_descriptor; - typedef std::size_t vertices_size_type; - private: // Logic to figure out the edges_size_type struct dummy {}; diff --git a/include/boost/graph/betweenness_centrality.hpp b/include/boost/graph/betweenness_centrality.hpp index 0262ad97..890103f3 100644 --- a/include/boost/graph/betweenness_centrality.hpp +++ b/include/boost/graph/betweenness_centrality.hpp @@ -417,6 +417,7 @@ namespace detail { namespace graph { WeightMap weight_map, 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 > incoming(V); std::vector distance(V); std::vector dependency(V); - std::vector path_count(V); + std::vector path_count(V); brandes_betweenness_centrality( g, centrality, edge_centrality_map, @@ -452,6 +453,7 @@ namespace detail { namespace graph { EdgeCentralityMap edge_centrality_map, 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 > incoming(V); std::vector distance(V); std::vector dependency(V); - std::vector path_count(V); + std::vector path_count(V); brandes_betweenness_centrality( g, centrality, edge_centrality_map, diff --git a/include/boost/graph/breadth_first_search.hpp b/include/boost/graph/breadth_first_search.hpp index d8ffd7fe..a4240ced 100644 --- a/include/boost/graph/breadth_first_search.hpp +++ b/include/boost/graph/breadth_first_search.hpp @@ -21,6 +21,7 @@ #include #include #include +#include namespace boost { @@ -219,16 +220,14 @@ namespace boost { const bgl_named_params& params, detail::error_property_not_found) { - std::vector color_vec(num_vertices(g)); - default_color_type c = white_color; null_visitor null_vis; bfs_helper (g, s, - make_iterator_property_map - (color_vec.begin(), + make_two_bit_color_map + (num_vertices(g), choose_const_pmap(get_param(params, vertex_index), - g, vertex_index), c), + g, vertex_index)), choose_param(get_param(params, graph_visitor), make_bfs_visitor(null_vis)), params); diff --git a/include/boost/graph/compressed_sparse_row_graph.hpp b/include/boost/graph/compressed_sparse_row_graph.hpp index d093b6a5..f9a35030 100644 --- a/include/boost/graph/compressed_sparse_row_graph.hpp +++ b/include/boost/graph/compressed_sparse_row_graph.hpp @@ -27,6 +27,7 @@ #include #include #include +#include #ifdef BOOST_GRAPH_NO_BUNDLED_PROPERTIES # error The Compressed Sparse Row graph only supports bundled properties. @@ -157,6 +158,15 @@ class compressed_sparse_row_graph : m_rowstart(1, EdgeIndex(0)), m_column(0), m_property(), m_last_source(0) {} + // With numverts vertices + compressed_sparse_row_graph(vertices_size_type numverts) + : inherited_vertex_properties(numverts), m_rowstart(numverts + 1), + m_column(0), m_last_source(numverts) + { + for (Vertex v = 0; v < numverts + 1; ++v) + m_rowstart[v] = 0; + } + // From number of vertices and sorted list of edges template compressed_sparse_row_graph(InputIterator edge_begin, InputIterator edge_end, @@ -339,6 +349,23 @@ class csr_edge_descriptor bool operator>(const csr_edge_descriptor& e) const {return idx > e.idx;} bool operator<=(const csr_edge_descriptor& e) const {return idx <= e.idx;} bool operator>=(const csr_edge_descriptor& e) const {return idx >= e.idx;} + + template + void serialize(Archiver& ar, const unsigned int /*version*/) + { + ar & src & idx; + } +}; + +template +struct hash > +{ + std::size_t operator()(csr_edge_descriptor const& x) const + { + std::size_t hash = hash_value(x.src); + hash_combine(hash, x.idx); + return hash; + } }; // Construction functions diff --git a/include/boost/graph/depth_first_search.hpp b/include/boost/graph/depth_first_search.hpp index 6a0abb9a..b1377409 100644 --- a/include/boost/graph/depth_first_search.hpp +++ b/include/boost/graph/depth_first_search.hpp @@ -19,7 +19,6 @@ #include #include #include - #include #include @@ -357,8 +356,6 @@ namespace boost { vis.start_vertex(u, g); detail::depth_first_visit_impl(g, u, vis, color, func); } - - } // namespace boost diff --git a/include/boost/graph/detail/adjacency_list.hpp b/include/boost/graph/detail/adjacency_list.hpp index b85f307d..ae6db307 100644 --- a/include/boost/graph/detail/adjacency_list.hpp +++ b/include/boost/graph/detail/adjacency_list.hpp @@ -387,7 +387,7 @@ namespace boost { ++first; incidence_iterator i = first; if (first != last) - for (; i != last; ++i) + for (++i; i != last; ++i) if (!pred(*i)) { *first.base() = *i.base(); ++first; @@ -786,14 +786,14 @@ namespace boost { typedef typename EdgeList::value_type StoredEdge; typename EdgeList::iterator i = el.begin(), end = el.end(); for (; i != end; ++i) { - if((*i).get_target() == v) { + if ((*i).get_target() == v) { // NOTE: Wihtout this skip, this loop will double-delete properties // of loop edges. This solution is based on the observation that // the incidence edges of a vertex with a loop are adjacent in the // out edge list. This *may* actually hold for multisets also. bool skip = (next(i) != end && i->get_iter() == next(i)->get_iter()); g.m_edges.erase((*i).get_iter()); - if(skip) ++i; + if (skip) ++i; } } detail::erase_from_incidence_list(el, v, cat); @@ -2297,7 +2297,7 @@ namespace boost { // VertexList and vertex_iterator typedef typename container_gen::type SeqVertexList; - typedef boost::integer_range RandVertexList; + typedef boost::integer_range RandVertexList; typedef typename mpl::if_::type VertexList; diff --git a/include/boost/graph/dijkstra_shortest_paths.hpp b/include/boost/graph/dijkstra_shortest_paths.hpp index 6233e08b..0b7d1cfe 100644 --- a/include/boost/graph/dijkstra_shortest_paths.hpp +++ b/include/boost/graph/dijkstra_shortest_paths.hpp @@ -127,7 +127,7 @@ namespace boost { template void examine_edge(Edge e, Graph& g) { if (m_compare(get(m_weight, e), m_zero)) - throw negative_edge(); + boost::throw_exception(negative_edge()); m_vis.examine_edge(e, g); } template @@ -165,7 +165,7 @@ namespace boost { struct vertex_property_map_generator_helper { typedef boost::vector_property_map type; static type build(const Graph& g, const IndexMap& index, boost::scoped_array& array_holder) { - return make_vector_property_map(index); + return boost::make_vector_property_map(index); } }; @@ -200,7 +200,7 @@ namespace boost { struct default_color_map_generator_helper { typedef boost::vector_property_map type; static type build(const Graph& g, const IndexMap& index) { - return make_vector_property_map(index); + return boost::make_vector_property_map(index); } }; @@ -291,7 +291,7 @@ namespace boost { typedef d_ary_heap_indirect MutableQueue; MutableQueue Q(distance, index_in_heap, compare); -#endif +#endif // Relaxed heap detail::dijkstra_bfs_visitor diff --git a/include/boost/graph/erdos_renyi_generator.hpp b/include/boost/graph/erdos_renyi_generator.hpp index 605b0e17..0352284f 100644 --- a/include/boost/graph/erdos_renyi_generator.hpp +++ b/include/boost/graph/erdos_renyi_generator.hpp @@ -123,16 +123,16 @@ namespace boost { sorted_erdos_renyi_iterator() : gen(), rand_vertex(0.5), n(0), allow_self_loops(false), - src((std::numeric_limits::max)()), tgt(0), prob(0) {} + src((std::numeric_limits::max)()), tgt(0), prob(0) {} sorted_erdos_renyi_iterator(RandomGenerator& gen, vertices_size_type n, - double prob = 0.0, + double prob = 0.0, bool allow_self_loops = false) : gen(), // The "1.0 - prob" in the next line is to work around a Boost.Random // (and TR1) bug in the specification of geometric_distribution. It // should be replaced by "prob" when the issue is fixed. rand_vertex(1.0 - prob), - n(n), allow_self_loops(allow_self_loops), src(0), tgt(0), prob(prob) + n(n), allow_self_loops(allow_self_loops), src(0), tgt(0), prob(prob) { this->gen.reset(new uniform_01(gen)); @@ -182,27 +182,27 @@ namespace boost { vertices_size_type increment = rand_vertex(*gen); tgt += increment; if (is_undirected) { - // Update src and tgt based on position of tgt - // Basically, we want the greatest src_increment such that (in \bbQ): - // src_increment * (src + allow_self_loops + src_increment - 1/2) <= tgt - // The result of the LHS of this, evaluated with the computed - // src_increment, is then subtracted from tgt - double src_minus_half = (src + allow_self_loops) - 0.5; - double disc = src_minus_half * src_minus_half + 2 * tgt; - double src_increment_fp = floor(sqrt(disc) - src_minus_half); - vertices_size_type src_increment = vertices_size_type(src_increment_fp); - if (src + src_increment >= n) { - src = n; - } else { - tgt -= (src + allow_self_loops) * src_increment + - src_increment * (src_increment - 1) / 2; - src += src_increment; - } + // Update src and tgt based on position of tgt + // Basically, we want the greatest src_increment such that (in \bbQ): + // src_increment * (src + allow_self_loops + src_increment - 1/2) <= tgt + // The result of the LHS of this, evaluated with the computed + // src_increment, is then subtracted from tgt + double src_minus_half = (src + allow_self_loops) - 0.5; + double disc = src_minus_half * src_minus_half + 2 * tgt; + double src_increment_fp = floor(sqrt(disc) - src_minus_half); + vertices_size_type src_increment = vertices_size_type(src_increment_fp); + if (src + src_increment >= n) { + src = n; + } else { + tgt -= (src + allow_self_loops) * src_increment + + src_increment * (src_increment - 1) / 2; + src += src_increment; + } } else { - // Number of out edge positions possible from each vertex in this graph - vertices_size_type possible_out_edges = n - (allow_self_loops ? 0 : 1); - src += (std::min)(n - src, tgt / possible_out_edges); - tgt %= possible_out_edges; + // Number of out edge positions possible from each vertex in this graph + vertices_size_type possible_out_edges = n - (allow_self_loops ? 0 : 1); + src += (std::min)(n - src, tgt / possible_out_edges); + tgt %= possible_out_edges; } // Set end of graph code so (src, tgt) will be the same as for the end // sorted_erdos_renyi_iterator diff --git a/include/boost/graph/fruchterman_reingold.hpp b/include/boost/graph/fruchterman_reingold.hpp index 10a4807b..e9763758 100644 --- a/include/boost/graph/fruchterman_reingold.hpp +++ b/include/boost/graph/fruchterman_reingold.hpp @@ -95,7 +95,7 @@ struct grid_force_pairs #ifndef BOOST_NO_STDC_NAMESPACE using std::sqrt; #endif // BOOST_NO_STDC_NAMESPACE - two_k = Dim(2) * sqrt(width*height / num_vertices(g)); + two_k = Dim(2) * sqrt(width * height / num_vertices(g)); } template @@ -106,6 +106,10 @@ struct grid_force_pairs typedef std::list bucket_t; typedef std::vector buckets_t; +#ifndef BOOST_NO_STDC_NAMESPACE + using std::sqrt; +#endif // BOOST_NO_STDC_NAMESPACE + std::size_t columns = std::size_t(width / two_k + Dim(1)); std::size_t rows = std::size_t(height / two_k + Dim(1)); buckets_t buckets(rows * columns); diff --git a/include/boost/graph/graph_utility.hpp b/include/boost/graph/graph_utility.hpp index 018442b9..0bbe5947 100644 --- a/include/boost/graph/graph_utility.hpp +++ b/include/boost/graph/graph_utility.hpp @@ -420,6 +420,33 @@ namespace boost { make_list(const T1& t1, const T2& t2, const T3& t3, const T4& t4, const T5& t5) { return std::make_pair(t1, std::make_pair(t2, std::make_pair(t3, std::make_pair(t4, t5)))); } + namespace graph { + + // Functor for remove_parallel_edges: edge property of the removed edge is added to the remaining + template + struct add_removed_edge_property + { + add_removed_edge_property(EdgeProperty ep) : ep(ep) {} + + template + void operator() (Edge stay, Edge away) + { + put(ep, stay, get(ep, stay) + get(ep, away)); + } + EdgeProperty ep; + }; + + // Same as above: edge property is capacity here + template + struct add_removed_edge_capacity + : add_removed_edge_property::type> + { + typedef add_removed_edge_property::type> base; + add_removed_edge_capacity(Graph& g) : base(get(edge_capacity, g)) {} + }; + + } // namespace graph + } /* namespace boost */ #endif /* BOOST_GRAPH_UTILITY_HPP*/ diff --git a/include/boost/graph/graphviz.hpp b/include/boost/graph/graphviz.hpp index b010dd84..ccaacf35 100644 --- a/include/boost/graph/graphviz.hpp +++ b/include/boost/graph/graphviz.hpp @@ -725,7 +725,7 @@ class mutate_graph_impl : public mutate_graph if(!result.second) { // In the case of no parallel edges allowed - throw bad_parallel_edge(source, target); + boost::throw_exception(bad_parallel_edge(source, target)); } else { bgl_edges.insert(std::make_pair(edge, result.first)); } diff --git a/include/boost/graph/named_function_params.hpp b/include/boost/graph/named_function_params.hpp index db77ae3b..39f837c1 100644 --- a/include/boost/graph/named_function_params.hpp +++ b/include/boost/graph/named_function_params.hpp @@ -646,6 +646,11 @@ namespace boost { return Params(c); } + namespace detail { + struct unused_tag_type {}; + } + typedef bgl_named_params no_named_parameters; + //=========================================================================== // Functions for extracting parameters from bgl_named_params diff --git a/include/boost/graph/plod_generator.hpp b/include/boost/graph/plod_generator.hpp index 9a63ec8f..4e557cf0 100644 --- a/include/boost/graph/plod_generator.hpp +++ b/include/boost/graph/plod_generator.hpp @@ -1,4 +1,4 @@ -// Copyright 2004 The Trustees of Indiana University. +// Copyright 2004-2006 The Trustees of Indiana University. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at @@ -17,27 +17,112 @@ #include #include #include +#include namespace boost { + template + class out_directed_plod_iterator + { + public: + typedef std::forward_iterator_tag iterator_category; + typedef std::pair value_type; + typedef const value_type& reference; + typedef const value_type* pointer; + typedef std::ptrdiff_t difference_type; - template - class plod_iterator + out_directed_plod_iterator() : gen(0), at_end(true) { } + + out_directed_plod_iterator(RandomGenerator& gen, std::size_t n, + double alpha, double beta, + bool allow_self_loops) + : gen(&gen), n(n), alpha(alpha), beta(beta), + allow_self_loops(allow_self_loops), at_end(false), degree(0), + current(0, 0) + { + using std::pow; + + uniform_int x(0, n-1); + std::size_t xv = x(gen); + degree = (xv == 0? 0 : std::size_t(beta * pow(xv, -alpha))); + } + + reference operator*() const { return current; } + pointer operator->() const { return ¤t; } + + out_directed_plod_iterator& operator++() + { + using std::pow; + + uniform_int x(0, n-1); + + // Continue stepping through source nodes until the + // (out)degree is > 0 + while (degree == 0) { + // Step to the next source node. If we've gone past the + // number of nodes we're responsible for, we're done. + if (++current.first >= n) { + at_end = true; + return *this; + } + + std::size_t xv = x(*gen); + degree = (xv == 0? 0 : std::size_t(beta * pow(xv, -alpha))); + } + + do { + current.second = x(*gen); + } while (current.first == current.second && !allow_self_loops); + --degree; + + return *this; + } + + out_directed_plod_iterator operator++(int) + { + out_directed_plod_iterator temp(*this); + ++(*this); + return temp; + } + + bool operator==(const out_directed_plod_iterator& other) const + { + return at_end == other.at_end; + } + + bool operator!=(const out_directed_plod_iterator& other) const + { + return !(*this == other); + } + + private: + RandomGenerator* gen; + std::size_t n; + double alpha; + double beta; + bool allow_self_loops; + bool at_end; + std::size_t degree; + value_type current; + }; + + template + class undirected_plod_iterator { typedef std::vector > out_degrees_t; - typedef typename graph_traits::directed_category directed_category; public: - typedef std::input_iterator_tag iterator_category; - typedef std::pair value_type; - typedef const value_type& reference; - typedef const value_type* pointer; - typedef void difference_type; + typedef std::input_iterator_tag iterator_category; + typedef std::pair value_type; + typedef const value_type& reference; + typedef const value_type* pointer; + typedef std::ptrdiff_t difference_type; - plod_iterator() + undirected_plod_iterator() : gen(0), out_degrees(), degrees_left(0), allow_self_loops(false) { } - plod_iterator(RandomGenerator& gen, std::size_t n, - double alpha, double beta, bool allow_self_loops = false) + undirected_plod_iterator(RandomGenerator& gen, std::size_t n, + double alpha, double beta, + bool allow_self_loops = false) : gen(&gen), n(n), out_degrees(new out_degrees_t), degrees_left(0), allow_self_loops(allow_self_loops) { @@ -46,60 +131,42 @@ namespace boost { uniform_int x(0, n-1); for (std::size_t i = 0; i != n; ++i) { std::size_t xv = x(gen); - std::size_t degree = (xv == 0? 0 : std::size_t(beta * pow(xv, -alpha))); - if (degree != 0) { - out_degrees->push_back(std::make_pair(i, degree)); - } + std::size_t degree = (xv == 0? 0 : std::size_t(beta * pow(xv, -alpha))); + if (degree == 0) degree = 1; + else if (degree >= n) degree = n-1; + out_degrees->push_back(std::make_pair(i, degree)); degrees_left += degree; } - next(directed_category()); + next(); } reference operator*() const { return current; } pointer operator->() const { return ¤t; } - - plod_iterator& operator++() + + undirected_plod_iterator& operator++() { - next(directed_category()); + next(); return *this; } - plod_iterator operator++(int) + undirected_plod_iterator operator++(int) { - plod_iterator temp(*this); + undirected_plod_iterator temp(*this); ++(*this); return temp; } - bool operator==(const plod_iterator& other) const + bool operator==(const undirected_plod_iterator& other) const { return degrees_left == other.degrees_left; } - bool operator!=(const plod_iterator& other) const + bool operator!=(const undirected_plod_iterator& other) const { return !(*this == other); } private: - void next(directed_tag) - { - uniform_int x(0, out_degrees->size()-1); - std::size_t source; - do { - source = x(*gen); - } while ((*out_degrees)[source].second == 0); - current.first = (*out_degrees)[source].first; - do { - current.second = x(*gen); - } while (current.first == current.second && !allow_self_loops); - --degrees_left; - if (--(*out_degrees)[source].second == 0) { - (*out_degrees)[source] = out_degrees->back(); - out_degrees->pop_back(); - } - } - - void next(undirected_tag) + void next() { std::size_t source, target; while (true) { @@ -107,7 +174,7 @@ namespace boost { new edges, so we just add some random edge and set the degrees left = 0 to signal termination. */ if (out_degrees->size() < 2) { - uniform_int x(0, n); + uniform_int x(0, n-1); current.first = x(*gen); do { current.second = x(*gen); @@ -156,6 +223,31 @@ namespace boost { value_type current; }; + + template + class plod_iterator + : public mpl::if_::directed_category, + directed_tag>, + out_directed_plod_iterator, + undirected_plod_iterator >::type + { + typedef typename mpl::if_< + is_convertible< + typename graph_traits::directed_category, + directed_tag>, + out_directed_plod_iterator, + undirected_plod_iterator >::type + inherited; + + public: + plod_iterator() : inherited() { } + + plod_iterator(RandomGenerator& gen, std::size_t n, + double alpha, double beta, bool allow_self_loops = false) + : inherited(gen, n, alpha, beta, allow_self_loops) { } + }; + } // end namespace boost #endif // BOOST_GRAPH_PLOD_GENERATOR_HPP diff --git a/include/boost/graph/properties.hpp b/include/boost/graph/properties.hpp index e3816e36..2ce8e26a 100644 --- a/include/boost/graph/properties.hpp +++ b/include/boost/graph/properties.hpp @@ -15,7 +15,10 @@ #include #include #include - +#include +#include +#include +#include #if BOOST_WORKAROUND(BOOST_MSVC, < 1300) // Stay out of the way of the concept checking class @@ -35,12 +38,12 @@ namespace boost { static default_color_type red() { return red_color; } static default_color_type black() { return black_color; } }; - + // These functions are now obsolete, replaced by color_traits. inline default_color_type white(default_color_type) { return white_color; } inline default_color_type gray(default_color_type) { return gray_color; } inline default_color_type green(default_color_type) { return green_color; } - inline default_color_type red(default_color_type) { return red_color; } + 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 @@ -90,22 +93,29 @@ namespace boost { BOOST_DEF_PROPERTY(vertex, name); BOOST_DEF_PROPERTY(graph, name); BOOST_DEF_PROPERTY(vertex, distance); + BOOST_DEF_PROPERTY(vertex, distance2); BOOST_DEF_PROPERTY(vertex, color); BOOST_DEF_PROPERTY(vertex, degree); BOOST_DEF_PROPERTY(vertex, in_degree); BOOST_DEF_PROPERTY(vertex, out_degree); BOOST_DEF_PROPERTY(vertex, current_degree); - BOOST_DEF_PROPERTY(vertex, priority); + BOOST_DEF_PROPERTY(vertex, priority); BOOST_DEF_PROPERTY(vertex, discover_time); BOOST_DEF_PROPERTY(vertex, finish_time); BOOST_DEF_PROPERTY(vertex, predecessor); BOOST_DEF_PROPERTY(vertex, rank); BOOST_DEF_PROPERTY(vertex, centrality); BOOST_DEF_PROPERTY(vertex, lowpoint); + BOOST_DEF_PROPERTY(vertex, potential); + BOOST_DEF_PROPERTY(vertex, update); BOOST_DEF_PROPERTY(edge, reverse); BOOST_DEF_PROPERTY(edge, capacity); + BOOST_DEF_PROPERTY(edge, flow); BOOST_DEF_PROPERTY(edge, residual_capacity); BOOST_DEF_PROPERTY(edge, centrality); + BOOST_DEF_PROPERTY(edge, discover_time); + BOOST_DEF_PROPERTY(edge, update); + BOOST_DEF_PROPERTY(edge, finished); BOOST_DEF_PROPERTY(graph, visitor); // These tags are used for property bundles @@ -223,7 +233,7 @@ namespace boost { template class graph_property { public: - typedef typename property_value::type type; }; @@ -239,9 +249,9 @@ namespace boost { }; template - class degree_property_map + class degree_property_map : public put_get_helper::degree_size_type, - degree_property_map > + degree_property_map > { public: typedef typename graph_traits::vertex_descriptor key_type; @@ -262,7 +272,7 @@ namespace boost { } //======================================================================== - // Iterator Property Map Generating Functions contributed by + // Iterator Property Map Generating Functions contributed by // Kevin Vanhorn. (see also the property map generating functions // in boost/property_map.hpp) @@ -281,8 +291,8 @@ namespace boost { make_iterator_vertex_map(RandomAccessIterator iter, const PropertyGraph& g) { return make_iterator_property_map(iter, get(vertex_index, g)); - } - + } + // Use this next function when vertex_descriptor is known to be an // integer type, with values ranging from 0 to num_vertices(g). // @@ -297,7 +307,7 @@ namespace boost { make_iterator_vertex_map(RandomAccessIterator iter) { return make_iterator_property_map(iter, identity_property_map()); - } + } #endif template @@ -312,7 +322,7 @@ namespace boost { { assert(c.size() >= num_vertices(g)); return make_iterator_vertex_map(c.begin(), g); - } + } template inline iterator_property_map< @@ -329,17 +339,17 @@ namespace boost { #if defined (BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) # 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 T value_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_) {} @@ -351,11 +361,15 @@ namespace boost { namespace detail { template - struct is_vertex_bundle : is_convertible {}; + struct is_vertex_bundle + : mpl::and_, + mpl::and_ >, + mpl::not_ > > > + { }; } - + template - struct property_map + struct property_map { private: typedef graph_traits traits; @@ -376,7 +390,6 @@ namespace boost { const_type; }; #endif - } // namespace boost #if BOOST_WORKAROUND(BOOST_MSVC, < 1300) @@ -385,5 +398,4 @@ namespace boost { # undef RandomAccessIterator #endif - #endif /* BOOST_GRAPH_PROPERTIES_HPPA */ From cef7692b91196704b14ff2914ddc0385d7121647 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Wed, 1 Apr 2009 18:07:00 +0000 Subject: [PATCH 101/224] Merged more changes from Parallel BGL [SVN r52116] --- .../boost/graph/betweenness_centrality.hpp | 19 +- include/boost/graph/breadth_first_search.hpp | 61 ++- include/boost/graph/connected_components.hpp | 10 +- .../boost/graph/dijkstra_shortest_paths.hpp | 36 +- include/boost/graph/dimacs.hpp | 403 ++++++++++++++++++ include/boost/graph/fruchterman_reingold.hpp | 243 +++++++---- include/boost/graph/graph_stats.hpp | 136 ++++++ include/boost/graph/graphviz.hpp | 44 +- include/boost/graph/mesh_graph_generator.hpp | 158 +++++++ include/boost/graph/metis.hpp | 339 +++++++++++++++ include/boost/graph/named_function_params.hpp | 40 +- include/boost/graph/overloading.hpp | 46 ++ include/boost/graph/page_rank.hpp | 8 +- include/boost/graph/point_traits.hpp | 26 ++ include/boost/graph/properties.hpp | 11 + include/boost/graph/random_layout.hpp | 18 +- include/boost/graph/ssca_graph_generator.hpp | 164 +++++++ include/boost/graph/st_connected.hpp | 82 ++++ include/boost/graph/strong_components.hpp | 7 +- include/boost/graph/vertex_and_edge_range.hpp | 141 ++++++ test/layout_test.cpp | 26 +- 21 files changed, 1884 insertions(+), 134 deletions(-) create mode 100644 include/boost/graph/dimacs.hpp create mode 100644 include/boost/graph/graph_stats.hpp create mode 100644 include/boost/graph/mesh_graph_generator.hpp create mode 100644 include/boost/graph/metis.hpp create mode 100644 include/boost/graph/overloading.hpp create mode 100644 include/boost/graph/point_traits.hpp create mode 100644 include/boost/graph/ssca_graph_generator.hpp create mode 100644 include/boost/graph/st_connected.hpp create mode 100644 include/boost/graph/vertex_and_edge_range.hpp diff --git a/include/boost/graph/betweenness_centrality.hpp b/include/boost/graph/betweenness_centrality.hpp index 890103f3..741436c6 100644 --- a/include/boost/graph/betweenness_centrality.hpp +++ b/include/boost/graph/betweenness_centrality.hpp @@ -11,6 +11,7 @@ #include #include +#include #include #include #include @@ -369,7 +370,8 @@ brandes_betweenness_centrality(const Graph& g, DistanceMap distance, // d DependencyMap dependency, // delta PathCountMap path_count, // sigma - VertexIndexMap vertex_index) + VertexIndexMap vertex_index + BOOST_GRAPH_ENABLE_IF_MODELS_PARM(Graph,vertex_list_graph_tag)) { detail::graph::brandes_unweighted_shortest_paths shortest_paths; @@ -394,7 +396,8 @@ brandes_betweenness_centrality(const Graph& g, DependencyMap dependency, // delta PathCountMap path_count, // sigma VertexIndexMap vertex_index, - WeightMap weight_map) + WeightMap weight_map + BOOST_GRAPH_ENABLE_IF_MODELS_PARM(Graph,vertex_list_graph_tag)) { detail::graph::brandes_dijkstra_shortest_paths shortest_paths(weight_map); @@ -514,7 +517,8 @@ namespace detail { namespace graph { template void brandes_betweenness_centrality(const Graph& g, - const bgl_named_params& params) + const bgl_named_params& params + BOOST_GRAPH_ENABLE_IF_MODELS_PARM(Graph,vertex_list_graph_tag)) { typedef bgl_named_params named_params; @@ -531,7 +535,8 @@ brandes_betweenness_centrality(const Graph& g, template void -brandes_betweenness_centrality(const Graph& g, CentralityMap centrality) +brandes_betweenness_centrality(const Graph& g, CentralityMap centrality + BOOST_GRAPH_ENABLE_IF_MODELS_PARM(Graph,vertex_list_graph_tag)) { detail::graph::brandes_betweenness_centrality_dispatch2( g, centrality, dummy_property_map(), get(vertex_index, g)); @@ -540,7 +545,8 @@ brandes_betweenness_centrality(const Graph& g, CentralityMap centrality) template void brandes_betweenness_centrality(const Graph& g, CentralityMap centrality, - EdgeCentralityMap edge_centrality_map) + EdgeCentralityMap edge_centrality_map + BOOST_GRAPH_ENABLE_IF_MODELS_PARM(Graph,vertex_list_graph_tag)) { detail::graph::brandes_betweenness_centrality_dispatch2( g, centrality, edge_centrality_map, get(vertex_index, g)); @@ -570,7 +576,8 @@ relative_betweenness_centrality(const Graph& g, CentralityMap centrality) // Compute the central point dominance of a graph. template typename property_traits::value_type -central_point_dominance(const Graph& g, CentralityMap centrality) +central_point_dominance(const Graph& g, CentralityMap centrality + BOOST_GRAPH_ENABLE_IF_MODELS_PARM(Graph,vertex_list_graph_tag)) { using std::max; diff --git a/include/boost/graph/breadth_first_search.hpp b/include/boost/graph/breadth_first_search.hpp index a4240ced..e59f89d8 100644 --- a/include/boost/graph/breadth_first_search.hpp +++ b/include/boost/graph/breadth_first_search.hpp @@ -21,6 +21,8 @@ #include #include #include +#include +#include #include namespace boost { @@ -101,6 +103,8 @@ namespace boost { breadth_first_visit(g, s, Q, vis, color); } + namespace graph { struct bfs_visitor_event_not_overridden {}; } + template class bfs_visitor { @@ -109,40 +113,75 @@ namespace boost { bfs_visitor(Visitors vis) : m_vis(vis) { } template - void initialize_vertex(Vertex u, Graph& g) { + graph::bfs_visitor_event_not_overridden + initialize_vertex(Vertex u, Graph& g) + { invoke_visitors(m_vis, u, g, ::boost::on_initialize_vertex()); + return graph::bfs_visitor_event_not_overridden(); } + template - void discover_vertex(Vertex u, Graph& g) { + graph::bfs_visitor_event_not_overridden + discover_vertex(Vertex u, Graph& g) + { invoke_visitors(m_vis, u, g, ::boost::on_discover_vertex()); + return graph::bfs_visitor_event_not_overridden(); } + template - void examine_vertex(Vertex u, Graph& g) { + graph::bfs_visitor_event_not_overridden + examine_vertex(Vertex u, Graph& g) + { invoke_visitors(m_vis, u, g, ::boost::on_examine_vertex()); + return graph::bfs_visitor_event_not_overridden(); } + template - void examine_edge(Edge e, Graph& g) { + graph::bfs_visitor_event_not_overridden + examine_edge(Edge e, Graph& g) + { invoke_visitors(m_vis, e, g, ::boost::on_examine_edge()); + return graph::bfs_visitor_event_not_overridden(); } + template - void tree_edge(Edge e, Graph& g) { + graph::bfs_visitor_event_not_overridden + tree_edge(Edge e, Graph& g) + { invoke_visitors(m_vis, e, g, ::boost::on_tree_edge()); + return graph::bfs_visitor_event_not_overridden(); } + template - void non_tree_edge(Edge e, Graph& g) { + graph::bfs_visitor_event_not_overridden + non_tree_edge(Edge e, Graph& g) + { invoke_visitors(m_vis, e, g, ::boost::on_non_tree_edge()); + return graph::bfs_visitor_event_not_overridden(); } + template - void gray_target(Edge e, Graph& g) { + graph::bfs_visitor_event_not_overridden + gray_target(Edge e, Graph& g) + { invoke_visitors(m_vis, e, g, ::boost::on_gray_target()); + return graph::bfs_visitor_event_not_overridden(); } + template - void black_target(Edge e, Graph& g) { + graph::bfs_visitor_event_not_overridden + black_target(Edge e, Graph& g) + { invoke_visitors(m_vis, e, g, ::boost::on_black_target()); + return graph::bfs_visitor_event_not_overridden(); } + template - void finish_vertex(Vertex u, Graph& g) { + graph::bfs_visitor_event_not_overridden + finish_vertex(Vertex u, Graph& g) + { invoke_visitors(m_vis, u, g, ::boost::on_finish_vertex()); + return graph::bfs_visitor_event_not_overridden(); } BOOST_GRAPH_EVENT_STUB(on_initialize_vertex,bfs) @@ -175,7 +214,9 @@ namespace boost { typename graph_traits::vertex_descriptor s, ColorMap color, BFSVisitor vis, - const bgl_named_params& params) + const bgl_named_params& params, + BOOST_GRAPH_ENABLE_IF_MODELS(VertexListGraph, vertex_list_graph_tag, + void)* = 0) { typedef graph_traits Traits; // Buffer default diff --git a/include/boost/graph/connected_components.hpp b/include/boost/graph/connected_components.hpp index df9084ce..326e62da 100644 --- a/include/boost/graph/connected_components.hpp +++ b/include/boost/graph/connected_components.hpp @@ -15,7 +15,7 @@ #include #include #include - +#include #include namespace boost { @@ -58,7 +58,8 @@ namespace boost { template inline typename property_traits::value_type connected_components(const Graph& g, ComponentMap c, - const bgl_named_params& params) + const bgl_named_params& params + BOOST_GRAPH_ENABLE_IF_MODELS_PARM(Graph, vertex_list_graph_tag)) { if (num_vertices(g) == 0) return 0; @@ -77,14 +78,15 @@ namespace boost { template inline typename property_traits::value_type - connected_components(const Graph& g, ComponentMap c) + connected_components(const Graph& g, ComponentMap c + BOOST_GRAPH_ENABLE_IF_MODELS_PARM(Graph, vertex_list_graph_tag)) { if (num_vertices(g) == 0) return 0; typedef typename graph_traits::vertex_descriptor Vertex; function_requires< WritablePropertyMapConcept >(); typedef typename boost::graph_traits::directed_category directed; - BOOST_STATIC_ASSERT((boost::is_same::value)); + // BOOST_STATIC_ASSERT((boost::is_same::value)); typedef typename property_traits::value_type comp_type; // c_count initialized to "nil" (with nil represented by (max)()) diff --git a/include/boost/graph/dijkstra_shortest_paths.hpp b/include/boost/graph/dijkstra_shortest_paths.hpp index 0b7d1cfe..c454517b 100644 --- a/include/boost/graph/dijkstra_shortest_paths.hpp +++ b/include/boost/graph/dijkstra_shortest_paths.hpp @@ -6,6 +6,12 @@ // accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) //======================================================================= +// +// +// Revision History: +// 04 April 2001: Added named parameter variant. (Jeremy Siek) +// 01 April 2001: Modified to use new header. (JMaddock) +// #ifndef BOOST_GRAPH_DIJKSTRA_HPP #define BOOST_GRAPH_DIJKSTRA_HPP @@ -17,6 +23,7 @@ #include #include #include +#include #include #include #include @@ -30,6 +37,28 @@ namespace boost { + /** + * @brief Updates a particular value in a queue used by Dijkstra's + * algorithm. + * + * This routine is called by Dijkstra's algorithm after it has + * decreased the distance from the source vertex to the given @p + * vertex. By default, this routine will just call @c + * Q.update(vertex). However, other queues may provide more + * specialized versions of this routine. + * + * @param Q the queue that will be updated. + * @param vertex the vertex whose distance has been updated + * @param old_distance the previous distance to @p vertex + */ + template + inline void + dijkstra_queue_update(Buffer& Q, Vertex vertex, DistanceType old_distance) + { + (void)old_distance; + Q.update(vertex); + } + #ifdef BOOST_GRAPH_DIJKSTRA_TESTING // This is a misnomer now: it now just refers to the "default heap", which is // currently d-ary (d=4) but can be changed by a #define. @@ -107,17 +136,20 @@ namespace boost { } template void gray_target(Edge e, Graph& g) { + D old_distance = get(m_distance, target(e, g)); + bool decreased = relax(e, g, m_weight, m_predecessor, m_distance, m_combine, m_compare); if (decreased) { - m_Q.update(target(e, g)); + dijkstra_queue_update(m_Q, target(e, g), old_distance); m_vis.edge_relaxed(e, g); } else m_vis.edge_not_relaxed(e, g); } template - void initialize_vertex(Vertex /*u*/, Graph& /*g*/) { } + void initialize_vertex(Vertex u, Graph& g) + { m_vis.initialize_vertex(u, g); } template void non_tree_edge(Edge, Graph&) { } template diff --git a/include/boost/graph/dimacs.hpp b/include/boost/graph/dimacs.hpp new file mode 100644 index 00000000..4f8c1f4f --- /dev/null +++ b/include/boost/graph/dimacs.hpp @@ -0,0 +1,403 @@ +// Copyright 2005 The Trustees of Indiana University. + +// 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) + +// Authors: Alex Breuer +// Andrew Lumsdaine +#ifndef BOOST_GRAPH_DIMACS_HPP +#define BOOST_GRAPH_DIMACS_HPP + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost { namespace graph { + +class dimacs_exception : public std::exception {}; + +class dimacs_basic_reader { +public: + typedef std::size_t vertices_size_type; + typedef std::size_t edges_size_type; + typedef double vertex_weight_type; + typedef double edge_weight_type; + typedef std::pair edge_type; + enum incr_mode {edge, edge_weight}; + + dimacs_basic_reader( std::istream& in, bool want_weights = true ) : + inpt( in ), seen_edges( 0 ), want_weights(want_weights) + { + while( getline( inpt, buf ) && !buf.empty() && buf[0] == 'c' ); + + if( buf[0] != 'p' ) { + boost::throw_exception(dimacs_exception()); + } + + std::stringstream instr( buf ); + std::string junk; + + instr >> junk >> junk >> num_vertices >> num_edges; + read_edge_weights.push( -1 ); + incr( edge_weight ); + } + + //for a past the end iterator + dimacs_basic_reader() : inpt( std::cin ), num_vertices( 0 ), + num_edges( 0 ), seen_edges( 0 ), want_weights(false) {} + + edge_type edge_deref() { + assert( !read_edges.empty() ); + return read_edges.front(); + } + + inline edge_type* edge_ref() { + assert( !read_edges.empty() ); + return &read_edges.front(); + } + + inline edge_weight_type edge_weight_deref() { + 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() ); + read_edges.pop(); + } + else if( mode == edge_weight ) { + assert( !read_edge_weights.empty() ); + read_edge_weights.pop(); + } + + if( (mode == edge && read_edges.empty()) || + (mode == edge_weight && read_edge_weights.empty() )) { + + if( seen_edges > num_edges ) { + boost::throw_exception(dimacs_exception()); + } + + while( getline( inpt, buf ) && !buf.empty() && buf[0] == 'c' ); + + if( !inpt.eof() ) { + int source, dest, weight; + read_edge_line((char*) buf.c_str(), source, dest, weight); + + seen_edges++; + source--; + dest--; + + read_edges.push( edge_type( source, dest ) ); + if (want_weights) { + read_edge_weights.push( weight ); + } + } + assert( read_edges.size() < 100 ); + assert( read_edge_weights.size() < 100 ); + } + + // the 1000000 just happens to be about how many edges can be read in + // 10s +// if( !(seen_edges % 1000000) && !process_id( pg ) && mode == edge ) { +// std::cout << "read " << seen_edges << " edges" << std::endl; +// } + return *this; + } + + inline bool done_edges() { + return inpt.eof() && read_edges.size() == 0; + } + + inline bool done_edge_weights() { + return inpt.eof() && read_edge_weights.size() == 0; + } + + inline vertices_size_type n_vertices() { + return num_vertices; + } + + inline vertices_size_type processed_edges() { + return seen_edges - read_edges.size(); + } + + inline vertices_size_type processed_edge_weights() { + return seen_edges - read_edge_weights.size(); + } + + inline vertices_size_type n_edges() { + return num_edges; + } + +protected: + bool read_edge_line(char *linebuf, int &from, int &to, int &weight) + { + char *fs = NULL, *ts = NULL, *ws = NULL; + char *tmp = linebuf + 2; + + fs = tmp; + if ('e' == linebuf[0]) { + while (*tmp != '\n' && *tmp != '\0') { + if (*tmp == ' ') { + *tmp = '\0'; + ts = ++tmp; + break; + } + tmp++; + } + *tmp = '\0'; + if (NULL == fs || NULL == ts) return false; + from = atoi(fs); to = atoi(ts); weight = 0; + + } else if ('a' == linebuf[0]) { + while (*tmp != '\n' && *tmp != '\0') { + if (*tmp == ' ') { + *tmp = '\0'; + ts = ++tmp; + break; + } + tmp++; + } + while (*tmp != '\n' && *tmp != '\0') { + if (*tmp == ' ') { + *tmp = '\0'; + ws = ++tmp; + break; + } + tmp++; + } + while (*tmp != '\n' && *tmp != '\0') tmp++; + *tmp = '\0'; + if (fs == NULL || ts == NULL || ws == NULL) return false; + from = atoi(fs); to = atoi(ts) ; + if (want_weights) weight = atoi(ws); else weight = 0; + + } else { + return false; + } + + return true; + } + + std::queue read_edges; + std::queue read_edge_weights; + + std::istream& inpt; + std::string buf; + vertices_size_type num_vertices, num_edges, seen_edges; + bool want_weights; +}; + +#if 0 +class dimacs_indexed_reader : public dimacs_basic_reader { +public: + dimacs_indexed_reader( std::istream& in, std::istream& idx ) : + dimacs_basic_reader( in ), + index( idx ), start( 0 ), stop( 0 ), still_reading( true ) { + + int n = process_id( pg ); + std::stringstream instr; + + while( getline( index, buf ) ) { + instr.str( buf ); + instr.clear(); + long p, begin, end; + + instr >> p >> begin >> end; + + if( p == n ) { + start = begin; + stop = end; + break; + } + } + + std::cerr << "start is " << start << " stop is " << stop << std::endl; + assert( start != 0 && stop != 0 ); + inpt.seekg( start, std::ios::beg ); + + //what a kludge! + seen_edges = 0; + read_edges.pop(); + incr( dimacs_basic_reader::edge_weight ); + } + + dimacs_indexed_reader() : dimacs_basic_reader(), index( std::cin ) { + } + bool done_edges() { + return (stop < 0 ? (long)inpt.tellg() == stop && read_edges.size() == 0 : (long)inpt.tellg()) + >= stop && read_edges.size() == 0; + } + + inline dimacs_indexed_reader incr( incr_mode mode ) { + if( mode == edge ) { + assert( !read_edges.empty() ); + read_edges.pop(); + } + else if( mode == edge_weight ) { + assert( !read_edge_weights.empty() ); + read_edge_weights.pop(); + } + + if( (mode == edge && read_edges.empty()) || + (mode == edge_weight && read_edge_weights.empty() )) { + + if( seen_edges > num_edges ) { + boost::throw_exception(dimacs_exception()); + } + + while( getline( inpt, buf ) && !buf.empty() && buf[0] == 'c' ); + + if( still_reading && !inpt.eof() ) { + std::stringstream instr( buf ); + vertices_size_type source, dest; + edge_weight_type weight; + instr >> buf >> source >> dest >> weight; + seen_edges++; + + // take care of indexing + source--; + dest--; + + read_edges.push( edge_type( source, dest ) ); + read_edge_weights.push( weight ); + } + still_reading = stop < 0 ? (long)inpt.tellg() != stop : (long)inpt.tellg() < stop; + assert( read_edges.size() < 100 ); + assert( read_edge_weights.size() < 100 ); + } + + // the 1000000 just happens to be about how many edges can be read in + // 10s + if( !(seen_edges % 1000000) && !process_id( pg ) && mode == edge ) { + // std::cout << "read " << seen_edges << " edges" << std::endl; + } + return *this; + } + +private: + std::istream& index; + long start, stop; + bool still_reading; +}; +#endif + +template +class dimacs_edge_iterator { +public: + typedef dimacs_basic_reader::edge_type edge_type; + typedef dimacs_basic_reader::incr_mode incr_mode; + + typedef std::input_iterator_tag iterator_category; + typedef edge_type value_type; + typedef value_type reference; + typedef edge_type* pointer; + typedef std::ptrdiff_t difference_type; + + dimacs_edge_iterator( T& reader ) : + reader( reader ) {} + + inline dimacs_edge_iterator& operator++() { + reader.incr( dimacs_basic_reader::edge ); + return *this; + } + + inline edge_type operator*() { + return reader.edge_deref(); + } + + inline edge_type* operator->() { + return reader.edge_ref(); + } + + // don't expect this to do the right thing if you're not comparing against a + // general past-the-end-iterator made with the default constructor for + // dimacs_basic_reader + inline bool operator==( dimacs_edge_iterator arg ) { + if( reader.n_vertices() == 0 ) { + return arg.reader.done_edges(); + } + else if( arg.reader.n_vertices() == 0 ) { + return reader.done_edges(); + } + else { + return false; + } + return false; + } + + inline bool operator!=( dimacs_edge_iterator arg ) { + if( reader.n_vertices() == 0 ) { + return !arg.reader.done_edges(); + } + else if( arg.reader.n_vertices() == 0 ) { + return !reader.done_edges(); + } + else { + return true; + } + return true; + } + +private: + T& reader; +}; + +template +class dimacs_edge_weight_iterator { +public: + typedef dimacs_basic_reader::edge_weight_type edge_weight_type; + typedef dimacs_basic_reader::incr_mode incr_mode; + + dimacs_edge_weight_iterator( T& reader ) : reader( reader ) {} + + inline dimacs_edge_weight_iterator& operator++() { + reader.incr( dimacs_basic_reader::edge_weight ); + return *this; + } + + inline edge_weight_type operator*() { + return reader.edge_weight_deref(); + } + + // don't expect this to do the right thing if you're not comparing against a + // general past-the-end-iterator made with the default constructor for + // dimacs_basic_reader + inline bool operator==( dimacs_edge_weight_iterator arg ) { + if( reader.n_vertices() == 0 ) { + return arg.reader.done_edge_weights(); + } + else if( arg.reader.n_vertices() == 0 ) { + return reader.done_edge_weights(); + } + else { + return false; + } + return false; + } + + inline bool operator!=( dimacs_edge_weight_iterator arg ) { + if( reader.n_vertices() == 0 ) { + return !arg.reader.done_edge_weights(); + } + else if( arg.reader.n_vertices() == 0 ) { + return !reader.done_edge_weights(); + } + else { + return true; + } + return true; + } +private: + T& reader; +}; + +} } // end namespace boost::graph +#endif diff --git a/include/boost/graph/fruchterman_reingold.hpp b/include/boost/graph/fruchterman_reingold.hpp index e9763758..14235284 100644 --- a/include/boost/graph/fruchterman_reingold.hpp +++ b/include/boost/graph/fruchterman_reingold.hpp @@ -1,4 +1,4 @@ -// Copyright 2004 The Trustees of Indiana University. +// Copyright 2004, 2005 The Trustees of Indiana University. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at @@ -12,13 +12,20 @@ #include #include #include -#include #include #include #include // for std::min and std::max +#include // for std::accumulate +#include // for std::sqrt and std::fabs +#include // for hypot (not in ) +#include + +#include // for drand48 namespace boost { + bool vertex_migration = false; + struct square_distance_attractive_force { template T @@ -84,13 +91,17 @@ struct all_force_pairs } }; -template +template struct grid_force_pairs { + typedef typename property_traits::value_type Point; + typedef double Dim; + template explicit - grid_force_pairs(Dim width, Dim height, PositionMap position, const Graph& g) - : width(width), height(height), position(position) + grid_force_pairs(const Point& origin, const Point& extent, + PositionMap position, const Graph& g) + : width(extent.x), height(extent.y), position(position) { #ifndef BOOST_NO_STDC_NAMESPACE using std::sqrt; @@ -147,8 +158,12 @@ struct grid_force_pairs // Repulse vertices in this bucket bucket_t& other_bucket = buckets[other_row * columns + other_column]; - for (v = other_bucket.begin(); v != other_bucket.end(); ++v) - apply_force(*u, *v); + for (v = other_bucket.begin(); v != other_bucket.end(); ++v) { + Dim delta_x = position[*u].x - position[*v].x; + Dim delta_y = position[*u].y - position[*v].y; + Dim dist = hypot(delta_x, delta_y); + if (dist < two_k) apply_force(*u, *v); + } } } } @@ -161,11 +176,13 @@ struct grid_force_pairs Dim two_k; }; -template -inline grid_force_pairs -make_grid_force_pairs(Dim width, Dim height, const PositionMap& position, - const Graph& g) -{ return grid_force_pairs(width, height, position, g); } +template +inline grid_force_pairs +make_grid_force_pairs + (typename property_traits::value_type const& origin, + typename property_traits::value_type const& extent, + const PositionMap& position, const Graph& g) +{ return grid_force_pairs(origin, extent, position, g); } template void @@ -204,17 +221,47 @@ scale_graph(const Graph& g, PositionMap position, } namespace detail { + template + void + maybe_jitter_point(Point& p1, const Point& p2, Point origin, Point extent) + { +#ifndef BOOST_NO_STDC_NAMESPACE + using std::sqrt; + using std::fabs; +#endif // BOOST_NO_STDC_NAMESPACE + typedef double Dim; + Dim too_close_x = extent.x / Dim(10000); + if (fabs(p1.x - p2.x) < too_close_x) { + Dim dist_to_move = sqrt(extent.x) / Dim(200); + if (p1.x - origin.x < origin.x + extent.x - p1.x) + p1.x += dist_to_move * drand48(); + else + p1.x -= dist_to_move * drand48(); + } + Dim too_close_y = extent.y / Dim(10000); + if (fabs(p1.y - p2.y) < too_close_y) { + Dim dist_to_move = sqrt(extent.y) / Dim(200); + if (p1.y - origin.y < origin.y + extent.y - p1.y) + p1.y += dist_to_move * drand48(); + else + p1.y -= dist_to_move * drand48(); + } + } + template + typename RepulsiveForce, typename Graph> struct fr_apply_force { typedef typename graph_traits::vertex_descriptor vertex_descriptor; + typedef typename property_traits::value_type Point; + typedef double Dim; fr_apply_force(const PositionMap& position, const DisplacementMap& displacement, + Point origin, Point extent, RepulsiveForce repulsive_force, Dim k, const Graph& g) - : position(position), displacement(displacement), - repulsive_force(repulsive_force), k(k), g(g) + : position(position), displacement(displacement), origin(origin), + extent(extent), repulsive_force(repulsive_force), k(k), g(g) { } void operator()(vertex_descriptor u, vertex_descriptor v) @@ -223,18 +270,31 @@ namespace detail { using std::sqrt; #endif // BOOST_NO_STDC_NAMESPACE if (u != v) { + // When the vertices land on top of each other, move the + // first vertex away from the boundaries. + maybe_jitter_point(position[u], position[v], origin, extent); + + // DPG TBD: Can we use the Topology concept's + // distance/move_position_toward to handle this? Dim delta_x = position[v].x - position[u].x; Dim delta_y = position[v].y - position[u].y; - Dim dist = sqrt(delta_x * delta_x + delta_y * delta_y); - Dim fr = repulsive_force(u, v, k, dist, g); - displacement[v].x += delta_x / dist * fr; - displacement[v].y += delta_y / dist * fr; + Dim dist = hypot(delta_x, delta_y); + if (dist == Dim(0)) { + displacement[v].x += 0.01; + displacement[v].y += 0.01; + } else { + Dim fr = repulsive_force(u, v, k, dist, g); + displacement[v].x += delta_x / dist * fr; + displacement[v].y += delta_y / dist * fr; + } } } private: PositionMap position; DisplacementMap displacement; + Point origin; + Point extent; RepulsiveForce repulsive_force; Dim k; const Graph& g; @@ -242,21 +302,23 @@ namespace detail { } // end namespace detail -template void fruchterman_reingold_force_directed_layout (const Graph& g, PositionMap position, - Dim width, - Dim height, + typename property_traits::value_type const& origin, + typename property_traits::value_type const& extent, AttractiveForce attractive_force, RepulsiveForce repulsive_force, ForcePairs force_pairs, Cooling cool, DisplacementMap displacement) { + typedef typename property_traits::value_type Point; + typedef double Dim; typedef typename graph_traits::vertex_iterator vertex_iterator; typedef typename graph_traits::vertex_descriptor vertex_descriptor; typedef typename graph_traits::edge_iterator edge_iterator; @@ -265,22 +327,20 @@ fruchterman_reingold_force_directed_layout using std::sqrt; #endif // BOOST_NO_STDC_NAMESPACE - Dim area = width * height; + Dim volume = extent.x * extent.y; + // assume positions are initialized randomly - Dim k = sqrt(area / num_vertices(g)); + Dim k = sqrt(volume / num_vertices(g)); detail::fr_apply_force - apply_force(position, displacement, repulsive_force, k, g); + RepulsiveForce, Graph> + apply_force(position, displacement, origin, extent, repulsive_force, k, g); - Dim temp = cool(); - if (temp) do { + do { // Calculate repulsive forces vertex_iterator v, v_end; - for (tie(v, v_end) = vertices(g); v != v_end; ++v) { - displacement[*v].x = 0; - displacement[*v].y = 0; - } + for (tie(v, v_end) = vertices(g); v != v_end; ++v) + displacement[*v] = Point(); force_pairs(g, apply_force); // Calculate attractive forces @@ -288,9 +348,17 @@ fruchterman_reingold_force_directed_layout for (tie(e, e_end) = edges(g); e != e_end; ++e) { vertex_descriptor v = source(*e, g); vertex_descriptor u = target(*e, g); + + // When the vertices land on top of each other, move the + // first vertex away from the boundaries. + ::boost::detail::maybe_jitter_point(position[u], position[v], + origin, extent); + + // DPG TBD: Can we use the Topology concept's + // distance/move_position_toward to handle this? Dim delta_x = position[v].x - position[u].x; Dim delta_y = position[v].y - position[u].y; - Dim dist = sqrt(delta_x * delta_x + delta_y * delta_y); + Dim dist = hypot(delta_x, delta_y); Dim fa = attractive_force(*e, k, dist, g); displacement[v].x -= delta_x / dist * fa; @@ -299,41 +367,66 @@ fruchterman_reingold_force_directed_layout displacement[u].y += delta_y / dist * fa; } - // Update positions - for (tie(v, v_end) = vertices(g); v != v_end; ++v) { - BOOST_USING_STD_MIN(); - BOOST_USING_STD_MAX(); - Dim disp_size = sqrt(displacement[*v].x * displacement[*v].x - + displacement[*v].y * displacement[*v].y); - position[*v].x += displacement[*v].x / disp_size - * min BOOST_PREVENT_MACRO_SUBSTITUTION (disp_size, temp); - position[*v].y += displacement[*v].y / disp_size - * min BOOST_PREVENT_MACRO_SUBSTITUTION (disp_size, temp); - position[*v].x = min BOOST_PREVENT_MACRO_SUBSTITUTION - (width / 2, - max BOOST_PREVENT_MACRO_SUBSTITUTION(-width / 2, - position[*v].x)); - position[*v].y = min BOOST_PREVENT_MACRO_SUBSTITUTION - (height / 2, - max BOOST_PREVENT_MACRO_SUBSTITUTION(-height / 2, - position[*v].y)); + if (Dim temp = cool()) { + // Update positions + for (tie(v, v_end) = vertices(g); v != v_end; ++v) { + BOOST_USING_STD_MIN(); + BOOST_USING_STD_MAX(); + Dim disp_size = hypot(displacement[*v].x, displacement[*v].y); + { + position[*v].x += displacement[*v].x / disp_size + * (min)(disp_size, temp); + if (vertex_migration) { + position[*v].x = (min)(Dim(1.0), + (max)(Dim(-1.0), position[*v].x)); + } else { + position[*v].x = (min)(origin.x + extent.x, + (max)(origin.x, position[*v].x)); + } + + // CEM HACK: Jitter if we're on the edges + if(position[*v].x == 1.0f) // origin.x + extent.x) + position[*v].x -= drand48() * .1 * extent.x; + else if(position[*v].x == -1.0f) // origin.x) + position[*v].x += drand48() * .1 * extent.x; + } + { + position[*v].y += displacement[*v].y / disp_size + * (min)(disp_size, temp); + if (vertex_migration) { + position[*v].y = (min)(Dim(1.0), + (max)(Dim(-1.0), position[*v].y)); + } else { + position[*v].y = (min)(origin.y + extent.y, + (max)(origin.y, position[*v].y)); + } + + // CEM HACK: Jitter if we're on the edges + if(position[*v].y == 1.0f) // origin.y + extent.y) + position[*v].y -= drand48() * .1 * extent.y; + else if(position[*v].y == -1.0f) // origin.y) + position[*v].y += drand48() * .1 * extent.y; + } + } + } else { + break; } - } while ((temp = cool())); + } while (true); } namespace detail { template struct fr_force_directed_layout { - template static void run(const Graph& g, PositionMap position, - Dim width, - Dim height, + typename property_traits::value_type const& origin, + typename property_traits::value_type const& extent, AttractiveForce attractive_force, RepulsiveForce repulsive_force, ForcePairs force_pairs, @@ -342,7 +435,7 @@ namespace detail { const bgl_named_params&) { fruchterman_reingold_force_directed_layout - (g, position, width, height, attractive_force, repulsive_force, + (g, position, origin, extent, attractive_force, repulsive_force, force_pairs, cool, displacement); } }; @@ -350,15 +443,15 @@ namespace detail { template<> struct fr_force_directed_layout { - template static void run(const Graph& g, PositionMap position, - Dim width, - Dim height, + typename property_traits::value_type const& origin, + typename property_traits::value_type const& extent, AttractiveForce attractive_force, RepulsiveForce repulsive_force, ForcePairs force_pairs, @@ -366,56 +459,58 @@ namespace detail { error_property_not_found, const bgl_named_params& params) { - std::vector > displacements(num_vertices(g)); + typedef typename property_traits::value_type Point; + std::vector displacements(num_vertices(g)); fruchterman_reingold_force_directed_layout - (g, position, width, height, attractive_force, repulsive_force, + (g, position, origin, extent, attractive_force, repulsive_force, force_pairs, cool, make_iterator_property_map (displacements.begin(), choose_const_pmap(get_param(params, vertex_index), g, vertex_index), - simple_point())); + Point())); } }; } // end namespace detail -template void fruchterman_reingold_force_directed_layout (const Graph& g, PositionMap position, - Dim width, - Dim height, + typename property_traits::value_type const& origin, + typename property_traits::value_type const& extent, const bgl_named_params& params) { typedef typename property_value, vertex_displacement_t>::type D; detail::fr_force_directed_layout::run - (g, position, width, height, + (g, position, origin, extent, choose_param(get_param(params, attractive_force_t()), square_distance_attractive_force()), choose_param(get_param(params, repulsive_force_t()), square_distance_repulsive_force()), choose_param(get_param(params, force_pairs_t()), - make_grid_force_pairs(width, height, position, g)), + make_grid_force_pairs(origin, extent, position, g)), choose_param(get_param(params, cooling_t()), - linear_cooling(100)), + linear_cooling(100)), get_param(params, vertex_displacement_t()), params); } -template +template void -fruchterman_reingold_force_directed_layout(const Graph& g, - PositionMap position, - Dim width, - Dim height) +fruchterman_reingold_force_directed_layout + (const Graph& g, + PositionMap position, + typename property_traits::value_type const& origin, + typename property_traits::value_type const& extent) { fruchterman_reingold_force_directed_layout - (g, position, width, height, + (g, position, origin, extent, attractive_force(square_distance_attractive_force())); } diff --git a/include/boost/graph/graph_stats.hpp b/include/boost/graph/graph_stats.hpp new file mode 100644 index 00000000..080a57fd --- /dev/null +++ b/include/boost/graph/graph_stats.hpp @@ -0,0 +1,136 @@ +// Copyright 2005 The Trustees of Indiana University. + +// 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) + +// Authors: Alex Breuer +// Andrew Lumsdaine +#ifndef BOOST_GRAPH_GRAPH_STATS_HPP +#define BOOST_GRAPH_GRAPH_STATS_HPP + +#include +#include +#include + +namespace boost { namespace graph { + +template +struct sort_edge_by_origin { +public: + typedef typename graph_traits::edge_descriptor edge_type; + + explicit sort_edge_by_origin( Graph& g ) : g(g) {} + + inline bool operator()( edge_type a, edge_type b ) { + return source( a, g ) == source( b, g ) ? target( a, g ) < target( b, g ) : + source( a, g ) < source( b, g ); + } + +private: + Graph& g; +}; + +template +struct equal_edge { +public: + typedef typename graph_traits::edge_descriptor edge_type; + + explicit equal_edge( Graph& g ) : g(g) {} + + inline bool operator()( edge_type a, edge_type b ) { + return source( a, g ) == source( b, g ) && + target( a, g ) == target( b, g ); + } + +private: + Graph& g; +}; + +template +unsigned long num_dup_edges( Graph& g ) { + typedef typename graph_traits::edge_iterator e_iterator_type; + typedef typename graph_traits::edge_descriptor edge_type; + + std::list all_edges; + + BGL_FORALL_EDGES_T( e, g, Graph ) { + all_edges.push_back( e ); + } + + sort_edge_by_origin cmp1( g ); + all_edges.sort( cmp1 ); + equal_edge cmp2( g ); + all_edges.unique( cmp2 ); + + return num_edges( g ) - all_edges.size(); +} + + +template +std::map dup_edge_dist( Graph& g ) { + std::map dist; + typedef typename graph_traits::adjacency_iterator a_iterator_type; + typedef typename graph_traits::vertex_descriptor vertex_type; + + + BGL_FORALL_VERTICES_T( v, g, Graph ) { + std::list front_neighbors; + a_iterator_type a_iter, a_end; + for( tie( a_iter, a_end ) = adjacent_vertices( v, g ); + a_iter != a_end; ++a_iter ) { + front_neighbors.push_back( *a_iter ); + } + + front_neighbors.sort(); + front_neighbors.unique(); + dist[out_degree( v, g ) - front_neighbors.size()] += 1; + } + return dist; +} + +template +std::map degree_dist( Graph& g ) { + std::map dist; + typedef typename graph_traits::adjacency_iterator a_iterator_type; + typedef typename graph_traits::vertex_descriptor vertex_type; + + BGL_FORALL_VERTICES_T( v, g, Graph ) { + dist[out_degree( v, g )] += 1; + } + + return dist; +} + +template +std::map weight_degree_dist( Graph& g ) { + std::map dist, n; + typedef typename graph_traits::adjacency_iterator a_iterator_type; + typedef typename graph_traits::vertex_descriptor vertex_type; + typedef typename property_map::const_type edge_map_type; + typedef typename property_traits::value_type + edge_weight_type; + + typename property_map::type em = get( edge_weight, g ); + + BGL_FORALL_VERTICES_T( v, g, Graph ) { + edge_weight_type tmp = 0; + BGL_FORALL_OUTEDGES_T( v, e, g, Graph ) { + tmp += em[e]; + } + n[out_degree( v, g )] += 1.; + dist[out_degree( v, g )] += tmp; + } + + for( std::map::iterator iter = dist.begin(); + iter != dist.end(); ++iter ) { + assert( n[iter->first] != 0 ); + dist[iter->first] /= n[iter->first]; + } + + return dist; +} + +}} + +#endif diff --git a/include/boost/graph/graphviz.hpp b/include/boost/graph/graphviz.hpp index ccaacf35..9935b4be 100644 --- a/include/boost/graph/graphviz.hpp +++ b/include/boost/graph/graphviz.hpp @@ -1,7 +1,7 @@ //======================================================================= // Copyright 2001 University of Notre Dame. // Copyright 2003 Jeremy Siek -// Authors: Lie-Quan Lee and Jeremy Siek +// Authors: Lie-Quan Lee, Jeremy Siek, and Douglas Gregor // // Distributed under the Boost Software License, Version 1.0. (See // accompanying file LICENSE_1_0.txt or copy at @@ -23,6 +23,7 @@ #include #include #include +#include #ifdef BOOST_HAS_DECLSPEC # if defined(BOOST_ALL_DYN_LINK) || defined(BOOST_GRAPH_DYN_LINK) @@ -236,11 +237,14 @@ namespace boost { template - inline void write_graphviz(std::ostream& out, const Graph& g, - VertexPropertiesWriter vpw, - EdgePropertiesWriter epw, - GraphPropertiesWriter gpw, - VertexID vertex_id) + inline void + write_graphviz + (std::ostream& out, const Graph& g, + VertexPropertiesWriter vpw, + EdgePropertiesWriter epw, + GraphPropertiesWriter gpw, + VertexID vertex_id + BOOST_GRAPH_ENABLE_IF_MODELS_PARM(Graph,vertex_list_graph_tag)) { typedef typename graph_traits::directed_category cat_type; typedef graphviz_io_traits Traits; @@ -267,17 +271,21 @@ namespace boost { template - inline void write_graphviz(std::ostream& out, const Graph& g, - VertexPropertiesWriter vpw, - EdgePropertiesWriter epw, - GraphPropertiesWriter gpw) + inline void + write_graphviz(std::ostream& out, const Graph& g, + VertexPropertiesWriter vpw, + EdgePropertiesWriter epw, + GraphPropertiesWriter gpw + BOOST_GRAPH_ENABLE_IF_MODELS_PARM(Graph,vertex_list_graph_tag)) { write_graphviz(out, g, vpw, epw, gpw, get(vertex_index, g)); } #if !defined(BOOST_MSVC) || BOOST_MSVC > 1300 // ambiguous overload problem with VC++ template inline void - write_graphviz(std::ostream& out, const Graph& g) { + write_graphviz(std::ostream& out, const Graph& g + BOOST_GRAPH_ENABLE_IF_MODELS_PARM(Graph,vertex_list_graph_tag)) + { default_writer dw; default_writer gw; write_graphviz(out, g, dw, dw, gw); @@ -286,7 +294,9 @@ namespace boost { template inline void - write_graphviz(std::ostream& out, const Graph& g, VertexWriter vw) { + write_graphviz(std::ostream& out, const Graph& g, VertexWriter vw + BOOST_GRAPH_ENABLE_IF_MODELS_PARM(Graph,vertex_list_graph_tag)) + { default_writer dw; default_writer gw; write_graphviz(out, g, vw, dw, gw); @@ -295,7 +305,9 @@ namespace boost { template inline void write_graphviz(std::ostream& out, const Graph& g, - VertexWriter vw, EdgeWriter ew) { + VertexWriter vw, EdgeWriter ew + BOOST_GRAPH_ENABLE_IF_MODELS_PARM(Graph,vertex_list_graph_tag)) + { default_writer gw; write_graphviz(out, g, vw, ew, gw); } @@ -575,7 +587,8 @@ namespace boost { inline void write_graphviz(std::ostream& out, const Graph& g, const dynamic_properties& dp, - const std::string& node_id = "node_id") + const std::string& node_id = "node_id" + BOOST_GRAPH_ENABLE_IF_MODELS_PARM(Graph,vertex_list_graph_tag)) { typedef typename graph_traits::vertex_descriptor Vertex; write_graphviz(out, g, dp, node_id, @@ -586,7 +599,8 @@ namespace boost { void write_graphviz(std::ostream& out, const Graph& g, const dynamic_properties& dp, const std::string& node_id, - VertexID id) + VertexID id + BOOST_GRAPH_ENABLE_IF_MODELS_PARM(Graph,vertex_list_graph_tag)) { write_graphviz (out, g, diff --git a/include/boost/graph/mesh_graph_generator.hpp b/include/boost/graph/mesh_graph_generator.hpp new file mode 100644 index 00000000..0511cd9c --- /dev/null +++ b/include/boost/graph/mesh_graph_generator.hpp @@ -0,0 +1,158 @@ +// Copyright 2004, 2005 The Trustees of Indiana University. + +// 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) + +// Authors: Nick Edmonds +// Andrew Lumsdaine +#ifndef BOOST_GRAPH_MESH_GENERATOR_HPP +#define BOOST_GRAPH_MESH_GENERATOR_HPP + +#include +#include +#include +#include +#include +#include + +namespace boost { + + template + class mesh_iterator + { + typedef typename graph_traits::directed_category directed_category; + typedef typename graph_traits::vertices_size_type + vertices_size_type; + + BOOST_STATIC_CONSTANT + (bool, + is_undirected = (is_base_and_derived::value + || is_same::value)); + + public: + typedef std::input_iterator_tag iterator_category; + typedef std::pair value_type; + typedef const value_type& reference; + typedef const value_type* pointer; + typedef void difference_type; + + mesh_iterator() + : x(0), y(0), done(true) { } + + // Vertices are numbered in row-major order + // Assumes directed + mesh_iterator(vertices_size_type x, vertices_size_type y, + 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); } + + reference operator*() const { return current; } + pointer operator->() const { return ¤t; } + + mesh_iterator& operator++() + { + if (is_undirected) { + if (!toroidal) { + if (target == source + 1) + if (source < x * (y - 1)) + target = source + x; + else { + source++; + target = (source % x) < x - 1 ? source + 1 : source + x; + if (target > n) + done = true; + } + else if (target == source + x) { + source++; + target = (source % x) < x - 1 ? source + 1 : source + x; + } + } else { + if (target == source + 1 || target == source - (source % x)) + target = (source + x) % n; + else if (target == (source + x) % n) { + if (source == n - 1) + done = true; + else { + source++; + target = (source % x) < (x - 1) ? source + 1 : source - (source % x); + } + } + } + } else { // Directed + if ( !toroidal ) { + if (target == source - x) + target = source % x > 0 ? source - 1 : source + 1; + else if (target == source - 1) + if ((source % x) < (x - 1)) + target = source + 1; + else if (source < x * (y - 1)) + target = source + x; + else { + done = true; + } + else if (target == source + 1) + if (source < x * (y - 1)) + target = source + x; + else { + source++; + target = source - x; + } + else if (target == source + x) { + source++; + target = (source >= x) ? source - x : source - 1; + } + } else { + if (source == n - 1 && target == (source + x) % n) + done = true; + else if (target == source - 1 || target == source + x - 1) + target = (source + x) % n; + else if (target == source + 1 || target == source - (source % x)) + target = (source - x + n) % n; + else if (target == (source - x + n) % n) + target = (source % x > 0) ? source - 1 : source + x - 1; + else if (target == (source + x) % n) { + source++; + target = (source % x) < (x - 1) ? source + 1 : source - (source % x); + } + } + } + + current.first = source; + current.second = target; + + return *this; + } + + mesh_iterator operator++(int) + { + mesh_iterator temp(*this); + ++(*this); + return temp; + } + + bool operator==(const mesh_iterator& other) const + { + return done == other.done; + } + + bool operator!=(const mesh_iterator& other) const + { return !(*this == other); } + + private: + + vertices_size_type x,y; + vertices_size_type n; + vertices_size_type source; + vertices_size_type target; + value_type current; + bool toroidal; + bool done; + }; + + +} // end namespace boost + +#endif // BOOST_GRAPH_MESH_GENERATOR_HPP diff --git a/include/boost/graph/metis.hpp b/include/boost/graph/metis.hpp new file mode 100644 index 00000000..f16cac26 --- /dev/null +++ b/include/boost/graph/metis.hpp @@ -0,0 +1,339 @@ +// Copyright 2005 The Trustees of Indiana University. + +// 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) + +// Authors: Douglas Gregor +// Andrew Lumsdaine +#ifndef BOOST_GRAPH_METIS_HPP +#define BOOST_GRAPH_METIS_HPP + +#ifdef BOOST_GRAPH_METIS_NO_INLINE +# define BOOST_GRAPH_METIS_INLINE_KEYWORD +#else +# define BOOST_GRAPH_METIS_INLINE_KEYWORD inline +#endif + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost { namespace graph { + +class metis_exception : public std::exception {}; +class metis_input_exception : public metis_exception {}; + +class metis_reader +{ + public: + typedef std::size_t vertices_size_type; + typedef std::size_t edges_size_type; + typedef double vertex_weight_type; + typedef double edge_weight_type; + + class edge_iterator + { + public: + typedef std::input_iterator_tag iterator_category; + typedef std::pair value_type; + typedef const value_type& reference; + typedef const value_type* pointer; + typedef std::ptrdiff_t difference_type; + + private: + class postincrement_proxy + { + postincrement_proxy(const value_type& value) : value(value) { } + + public: + reference operator*() const { return value; } + + private: + value_type value; + friend class edge_iterator; + }; + + public: + edge_iterator& operator++(); + postincrement_proxy operator++(int); + + reference operator*() const { return self->edge; } + pointer operator->() const { return &self->edge; } + + // Default copy constructor and assignment operator are okay + + private: + edge_iterator(metis_reader* self); + void advance(bool skip_initial_read); + + metis_reader* self; + + friend class metis_reader; + friend bool operator==(edge_iterator, edge_iterator); + friend bool operator!=(edge_iterator, edge_iterator); + }; + friend class edge_iterator; + + class edge_weight_iterator + { + public: + typedef std::input_iterator_tag iterator_category; + typedef edge_weight_type value_type; + typedef const value_type& reference; + typedef const value_type* pointer; + + // Default copy constructor and assignment operator are okay + + reference operator*() const { return self->edge_weight; } + pointer operator->() const { return &self->edge_weight; } + + edge_weight_iterator& operator++() { return *this; } + edge_weight_iterator operator++(int) { return *this; } + + private: + edge_weight_iterator(metis_reader* self) : self(self) { } + + metis_reader* self; + + friend class metis_reader; + }; + + metis_reader(std::istream& in) : in(in), edge_weight(1.0) { start(); } + + edge_iterator begin(); + edge_iterator end(); + edge_weight_iterator weight_begin(); + + vertices_size_type num_vertices() const { return n_vertices; } + edges_size_type num_edges() const { return n_edges; } + + std::size_t num_vertex_weights() const { return n_vertex_weights; } + + vertex_weight_type vertex_weight(vertices_size_type v, std::size_t n) + { return vertex_weights[v*num_vertex_weights() + n]; } + + bool has_edge_weights() const { return edge_weights; } + + private: + void start(); + + // Configuration information + std::istream& in; + + // Information about the current METIS file + vertices_size_type n_vertices; + edges_size_type n_edges; + std::size_t n_vertex_weights; + bool edge_weights; + + // Information about the current edge/vertex + std::istringstream line_in; + std::pair edge; + std::vector vertex_weights; + edge_weight_type edge_weight; + + friend bool operator==(edge_iterator, edge_iterator); + friend bool operator!=(edge_iterator, edge_iterator); +}; + +class metis_distribution +{ + public: + typedef int process_id_type; + typedef std::size_t size_type; + typedef std::vector::iterator iterator; + + metis_distribution(std::istream& in, process_id_type my_id); + + size_type block_size(process_id_type id, size_type) const; + process_id_type operator()(size_type n) const { return vertices[n]; } + size_type local(size_type n) const; + size_type global(size_type n) const { return global(my_id, n); } + size_type global(process_id_type id, size_type n) const; + + iterator begin() { return vertices.begin(); } + iterator end() { return vertices.end(); } + + private: + std::istream& in; + process_id_type my_id; + std::vector vertices; +}; + +#if !defined(BOOST_GRAPH_METIS_NO_INLINE) || defined(BOOST_GRAPH_METIS_SOURCE) +BOOST_GRAPH_METIS_INLINE_KEYWORD +bool operator==(metis_reader::edge_iterator x, metis_reader::edge_iterator y) +{ + return (x.self == y.self + || (x.self && x.self->edge.first == x.self->num_vertices()) + || (y.self && y.self->edge.first == y.self->num_vertices())); +} + +BOOST_GRAPH_METIS_INLINE_KEYWORD +bool operator!=(metis_reader::edge_iterator x, metis_reader::edge_iterator y) +{ + return !(x == y); +} + +BOOST_GRAPH_METIS_INLINE_KEYWORD +metis_reader::edge_iterator::edge_iterator(metis_reader* self) + : self(self) +{ + if (self) advance(true); +} + +BOOST_GRAPH_METIS_INLINE_KEYWORD +metis_reader::edge_iterator& metis_reader::edge_iterator::operator++() +{ + advance(false); + return *this; +} + +BOOST_GRAPH_METIS_INLINE_KEYWORD +void metis_reader::edge_iterator::advance(bool skip_initial_read) +{ + do { + + if (!skip_initial_read) { + // Try to read the next edge + if (self->line_in >> std::ws >> self->edge.second) { + --self->edge.second; + if (self->has_edge_weights()) { + if (!(self->line_in >> self->edge_weight)) + boost::throw_exception(metis_input_exception()); + } + return; + } + + // Check if we're done + ++self->edge.first; + if (self->edge.first == self->num_vertices()) + return; + } + + // Find the next line + std::string line; + while (getline(self->in, line) && !line.empty() && line[0] == '%') { + /* Keep reading lines in the loop header... */ + } + if (!self->in) boost::throw_exception(metis_input_exception()); + self->line_in.str(line); + self->line_in.clear(); + + // Read the next line + std::size_t weights_left = self->n_vertex_weights; + vertex_weight_type weight; + while (weights_left > 0) { + if (self->line_in >> weight) self->vertex_weights.push_back(weight); + else boost::throw_exception(metis_input_exception()); + --weights_left; + } + + // Successive iterations will pick up edges for this vertex. + skip_initial_read = false; + } while (true); +} + +BOOST_GRAPH_METIS_INLINE_KEYWORD +metis_reader::edge_iterator::postincrement_proxy +metis_reader::edge_iterator::operator++(int) +{ + postincrement_proxy result(**this); + ++(*this); + return result; +} + +BOOST_GRAPH_METIS_INLINE_KEYWORD +metis_reader::edge_iterator metis_reader::begin() +{ + if (edge.first != 0) start(); + return edge_iterator(this); +} + +BOOST_GRAPH_METIS_INLINE_KEYWORD +metis_reader::edge_iterator metis_reader::end() +{ + return edge_iterator(0); +} + +BOOST_GRAPH_METIS_INLINE_KEYWORD +metis_reader::edge_weight_iterator metis_reader::weight_begin() +{ + return edge_weight_iterator(this); +} + +BOOST_GRAPH_METIS_INLINE_KEYWORD +void metis_reader::start() +{ + in.seekg(0, std::ios::beg); + std::string line; + while (getline(in, line) && !line.empty() && line[0] == '%') { + /* Keep getting lines in loop header. */ + } + + if (!in || line.empty()) boost::throw_exception(metis_input_exception()); + + // Determine number of vertices and edges in the graph + line_in.str(line); + if (!(line_in >> n_vertices >> n_edges)) boost::throw_exception(metis_input_exception()); + + // Determine whether vertex or edge weights are included in the graph + int fmt = 0; + line_in >> fmt; + n_vertex_weights = fmt / 10; + edge_weights = (fmt % 10 == 1); + + // Determine how many (if any!) vertex weights are included + if (n_vertex_weights) line_in >> n_vertex_weights; + + // Setup the iteration data structures + edge_weight = 1.0; + edge.first = 0; + edge.second = 0; + vertex_weights.reserve(n_vertex_weights * num_vertices()); +} + +metis_distribution::metis_distribution(std::istream& in, process_id_type my_id) + : in(in), my_id(my_id), + vertices(std::istream_iterator(in), + std::istream_iterator()) +{ +} + + +metis_distribution::size_type +metis_distribution::block_size(process_id_type id, size_type) const +{ + return std::count(vertices.begin(), vertices.end(), id); +} + +metis_distribution::size_type metis_distribution::local(size_type n) const +{ + return std::count(vertices.begin(), vertices.begin() + n, vertices[n]); +} + +metis_distribution::size_type +metis_distribution::global(process_id_type id, size_type n) const +{ + std::vector::const_iterator i = vertices.begin(); + while (*i != id) ++i; + + while (n > 0) { + do { ++i; } while (*i != id); + --n; + } + + return i - vertices.begin(); +} + +#endif + +} } // end namespace boost::graph + +#endif // BOOST_GRAPH_METIS_HPP diff --git a/include/boost/graph/named_function_params.hpp b/include/boost/graph/named_function_params.hpp index 39f837c1..7dbcd8a8 100644 --- a/include/boost/graph/named_function_params.hpp +++ b/include/boost/graph/named_function_params.hpp @@ -29,6 +29,9 @@ namespace boost { struct vertex_max_invariant_t { }; struct orig_to_copy_t { }; struct root_vertex_t { }; + struct polling_t { }; + struct lookahead_t { }; + struct in_parallel_t { }; struct attractive_force_t { }; struct repulsive_force_t { }; struct force_pairs_t { }; @@ -53,7 +56,7 @@ namespace boost { typedef Base next_type; typedef Tag tag_type; typedef T value_type; - bgl_named_params(T v) : m_value(v) { } + bgl_named_params(T v = T()) : m_value(v) { } bgl_named_params(T v, const Base& b) : Base(b), m_value(v) { } T m_value; @@ -305,6 +308,23 @@ namespace boost { return Params(c, *this); } + bgl_named_params + polling(bool b) const { + return bgl_named_params(b, *this); + } + + template + bgl_named_params + lookahead(const Tp& x) const { + return bgl_named_params(x, *this); + } + + template + bgl_named_params + in_parallel(const Tp& x) const { + return bgl_named_params(x, *this); + } + template bgl_named_params displacement_map(const VertexDisplacement& c) const { @@ -589,6 +609,24 @@ namespace boost { return Params(c); } + bgl_named_params + inline polling(bool b) { + return bgl_named_params(b); + } + + + template + bgl_named_params + lookahead(const T& x) { + return bgl_named_params(x); + } + + template + bgl_named_params + in_parallel(const T& x) { + return bgl_named_params(x); + } + template bgl_named_params displacement_map(const VertexDisplacement& c) { diff --git a/include/boost/graph/overloading.hpp b/include/boost/graph/overloading.hpp new file mode 100644 index 00000000..a952e22f --- /dev/null +++ b/include/boost/graph/overloading.hpp @@ -0,0 +1,46 @@ +// Copyright 2004 The Trustees of Indiana University. + +// 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) + +// Authors: Douglas Gregor +// Andrew Lumsdaine + +// +// This file contains helps that enable concept-based overloading +// within the Boost Graph Library. +// +#ifndef BOOST_GRAPH_OVERLOADING_HPP +#define BOOST_GRAPH_OVERLOADING_HPP + +#include +#include + +namespace boost { namespace graph { namespace detail { + +struct no_parameter {}; + +} } } // end namespace boost::graph::detail + +#ifndef BOOST_NO_SFINAE + +#define BOOST_GRAPH_ENABLE_IF_MODELS(Graph, Tag, Type) \ + typename enable_if_c<(is_base_and_derived< \ + Tag, \ + typename graph_traits::traversal_category>::value), \ + Type>::type + +#define BOOST_GRAPH_ENABLE_IF_MODELS_PARM(Graph, Tag) \ + , BOOST_GRAPH_ENABLE_IF_MODELS(Graph, Tag, \ + ::boost::graph::detail::no_parameter) \ + = ::boost::graph::detail::no_parameter() + +#else + +#define BOOST_GRAPH_ENABLE_IF_MODELS(Graph, Tag, Type) Type +#define BOOST_GRAPH_ENABLE_IF_MODELS_PARM(Graph, Tag) + +#endif // no SFINAE support + +#endif // BOOST_GRAPH_OVERLOADING_HPP diff --git a/include/boost/graph/page_rank.hpp b/include/boost/graph/page_rank.hpp index 8a4e1414..5f97e14b 100644 --- a/include/boost/graph/page_rank.hpp +++ b/include/boost/graph/page_rank.hpp @@ -15,6 +15,7 @@ #include #include #include +#include #include namespace boost { namespace graph { @@ -72,7 +73,8 @@ void page_rank(const Graph& g, RankMap rank_map, Done done, typename property_traits::value_type damping, typename graph_traits::vertices_size_type n, - RankMap2 rank_map2) + RankMap2 rank_map2 + BOOST_GRAPH_ENABLE_IF_MODELS_PARM(Graph, vertex_list_graph_tag)) { typedef typename property_traits::value_type rank_type; @@ -131,7 +133,9 @@ page_rank(const Graph& g, RankMap rank_map) // applies when we have a bidirectional graph. template void -remove_dangling_links(MutableGraph& g) +remove_dangling_links(MutableGraph& g + BOOST_GRAPH_ENABLE_IF_MODELS_PARM(MutableGraph, + vertex_list_graph_tag)) { typename graph_traits::vertices_size_type old_n; do { diff --git a/include/boost/graph/point_traits.hpp b/include/boost/graph/point_traits.hpp new file mode 100644 index 00000000..89da9395 --- /dev/null +++ b/include/boost/graph/point_traits.hpp @@ -0,0 +1,26 @@ +// Copyright 2004, 2005 The Trustees of Indiana University. + +// 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) + +// Authors: Douglas Gregor +// Andrew Lumsdaine +#ifndef BOOST_GRAPH_POINT_TRAITS_HPP +#define BOOST_GRAPH_POINT_TRAITS_HPP + +namespace boost { namespace graph { + +template +struct point_traits +{ + // The type of each component of the point + typedef typename Point::component_type component_type; + + // The number of dimensions in the point + static std::size_t dimensions(const Point& point); +}; + +} } // end namespace boost::graph + +#endif // BOOST_GRAPH_POINT_TRAITS_HPP diff --git a/include/boost/graph/properties.hpp b/include/boost/graph/properties.hpp index 2ce8e26a..78e52cb0 100644 --- a/include/boost/graph/properties.hpp +++ b/include/boost/graph/properties.hpp @@ -122,6 +122,17 @@ namespace boost { BOOST_DEF_PROPERTY(vertex, bundle); BOOST_DEF_PROPERTY(edge, bundle); + // These tags are used to denote the owners and local descriptors + // for the vertices and edges of a distributed graph. + BOOST_DEF_PROPERTY(vertex, global); + BOOST_DEF_PROPERTY(vertex, owner); + BOOST_DEF_PROPERTY(vertex, local); + BOOST_DEF_PROPERTY(edge, global); + BOOST_DEF_PROPERTY(edge, owner); + BOOST_DEF_PROPERTY(edge, local); + BOOST_DEF_PROPERTY(vertex, local_index); + BOOST_DEF_PROPERTY(edge, local_index); + #undef BOOST_DEF_PROPERTY namespace detail { diff --git a/include/boost/graph/random_layout.hpp b/include/boost/graph/random_layout.hpp index b65950d6..c5520bf3 100644 --- a/include/boost/graph/random_layout.hpp +++ b/include/boost/graph/random_layout.hpp @@ -18,14 +18,18 @@ namespace boost { -template void -random_graph_layout(const Graph& g, PositionMap position_map, - Dimension minX, Dimension maxX, - Dimension minY, Dimension maxY, - RandomNumberGenerator& gen) +random_graph_layout + (const Graph& g, PositionMap position_map, + typename property_traits::value_type const& origin, + typename property_traits::value_type const& extent, + RandomNumberGenerator& gen) { + typedef typename property_traits::value_type Point; + typedef double Dimension; + typedef typename mpl::if_, uniform_int, uniform_real >::type distrib_t; @@ -35,8 +39,8 @@ random_graph_layout(const Graph& g, PositionMap position_map, ::type gen_t; gen_t my_gen(gen); - distrib_t x(minX, maxX); - distrib_t y(minY, maxY); + distrib_t x(origin.x, origin.x + extent.x); + distrib_t y(origin.y, origin.y + extent.y); typename graph_traits::vertex_iterator vi, vi_end; for(tie(vi, vi_end) = vertices(g); vi != vi_end; ++vi) { position_map[*vi].x = x(my_gen); diff --git a/include/boost/graph/ssca_graph_generator.hpp b/include/boost/graph/ssca_graph_generator.hpp new file mode 100644 index 00000000..e52cbce9 --- /dev/null +++ b/include/boost/graph/ssca_graph_generator.hpp @@ -0,0 +1,164 @@ +// Copyright 2004, 2005 The Trustees of Indiana University. + +// 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) + +// Authors: Nick Edmonds +// Andrew Lumsdaine +#ifndef BOOST_GRAPH_SSCA_GENERATOR_HPP +#define BOOST_GRAPH_SSCA_GENERATOR_HPP + +#include +#include +#include +#include +#include +#include +#include +#include + +enum Direction {FORWARD = 1, BACKWARD = 2, BOTH = FORWARD | BACKWARD}; + +namespace boost { + + template + class ssca_iterator + { + typedef typename graph_traits::directed_category directed_category; + typedef typename graph_traits::vertices_size_type + vertices_size_type; + + public: + typedef std::input_iterator_tag iterator_category; + typedef std::pair value_type; + typedef const value_type& reference; + typedef const value_type* pointer; + typedef void difference_type; + + // No argument constructor, set to terminating condition + ssca_iterator() + : gen(), verticesRemaining(0) { } + + // Initialize for edge generation + ssca_iterator(RandomGenerator& gen, vertices_size_type totVertices, + vertices_size_type maxCliqueSize, double probUnidirectional, + int maxParallelEdges, double probIntercliqueEdges) + : gen(&gen), totVertices(totVertices), maxCliqueSize(maxCliqueSize), + probUnidirectional(probUnidirectional), maxParallelEdges(maxParallelEdges), + probIntercliqueEdges(probIntercliqueEdges), currentClique(0), + verticesRemaining(totVertices) + { + cliqueNum = std::vector(totVertices, -1); + current = std::make_pair(0,0); + } + + reference operator*() const { return current; } + pointer operator->() const { return ¤t; } + + ssca_iterator& operator++() + { + while (values.empty() && verticesRemaining > 0) { // If there are no values left, generate a new clique + uniform_int clique_size(1, maxCliqueSize); + uniform_int rand_vertex(0, totVertices-1); + uniform_int num_parallel_edges(1, maxParallelEdges); + uniform_int direction(0,1); + uniform_01 prob(*gen); + std::vector cliqueVertices; + + cliqueVertices.clear(); + vertices_size_type size = std::min(clique_size(*gen), verticesRemaining); + while (cliqueVertices.size() < size) { + vertices_size_type v = rand_vertex(*gen); + if (cliqueNum[v] == -1) { + cliqueNum[v] = currentClique; + cliqueVertices.push_back(v); + verticesRemaining--; + } + } // Nick: This is inefficient when only a few vertices remain... + // I should probably just select the remaining vertices + // in order when only a certain fraction remain. + + typename std::vector::iterator first, second; + for (first = cliqueVertices.begin(); first != cliqueVertices.end(); ++first) + for (second = first+1; second != cliqueVertices.end(); ++second) { + Direction d; + int edges; + + d = prob() < probUnidirectional ? (direction(*gen) == 0 ? FORWARD : BACKWARD) : BOTH; + + if (d & FORWARD) { + edges = num_parallel_edges(*gen); + for (int i = 0; i < edges; ++i) + values.push(std::make_pair(*first, *second)); + } + + if (d & BACKWARD) { + edges = num_parallel_edges(*gen); + for (int i = 0; i < edges; ++i) + values.push(std::make_pair(*second, *first)); + } + } + + if (verticesRemaining == 0) { + // Generate interclique edges + for (vertices_size_type i = 0; i < totVertices; ++i) { + double p = probIntercliqueEdges; + for (vertices_size_type d = 2; d < totVertices/2; d *= 2, p/= 2) { + vertices_size_type j = (i+d) % totVertices; + if (cliqueNum[j] != cliqueNum[i] && prob() < p) { + int edges = num_parallel_edges(*gen); + for (int i = 0; i < edges; ++i) + values.push(std::make_pair(i, j)); + } + } + } + } + + currentClique++; + } + + if (!values.empty()) { // If we're not done return a value + current = values.front(); + values.pop(); + } + + return *this; + } + + ssca_iterator operator++(int) + { + ssca_iterator temp(*this); + ++(*this); + return temp; + } + + bool operator==(const ssca_iterator& other) const + { + return verticesRemaining == other.verticesRemaining && values.empty() && other.values.empty(); + } + + bool operator!=(const ssca_iterator& other) const + { return !(*this == other); } + + private: + + // Parameters + RandomGenerator* gen; + vertices_size_type totVertices; + vertices_size_type maxCliqueSize; + double probUnidirectional; + int maxParallelEdges; + double probIntercliqueEdges; + + // Internal data structures + std::vector cliqueNum; + std::queue values; + int currentClique; + vertices_size_type verticesRemaining; + value_type current; + }; + +} // end namespace boost + +#endif // BOOST_GRAPH_SSCA_GENERATOR_HPP diff --git a/include/boost/graph/st_connected.hpp b/include/boost/graph/st_connected.hpp new file mode 100644 index 00000000..9801a275 --- /dev/null +++ b/include/boost/graph/st_connected.hpp @@ -0,0 +1,82 @@ +// Copyright (C) 2006 The Trustees of Indiana University. + +// 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) + +// Authors: Douglas Gregor +// Andrew Lumsdaine +#ifndef BOOST_GRAPH_DISTRIBUTED_ST_CONNECTED_HPP +#define BOOST_GRAPH_DISTRIBUTED_ST_CONNECTED_HPP + +#include +#include +#include +#include + +namespace boost { namespace graph { + +template +bool +st_connected(const Graph& g, + typename graph_traits::vertex_descriptor s, + typename graph_traits::vertex_descriptor t, + ColorMap color) +{ + typedef typename property_traits::value_type Color; + typedef color_traits ColorTraits; + typedef typename graph_traits::vertex_descriptor Vertex; + + // Set all vertices to white (unvisited) + BGL_FORALL_VERTICES_T(v, g, Graph) + put(color, v, ColorTraits::white()); + + // Vertices found from the source are grey + put(color, s, ColorTraits::gray()); + + // Vertices found from the target are greeen + put(color, t, ColorTraits::green()); + queue Q; + Q.push(s); + Q.push(t); + + while (!Q.empty()) { + Vertex u = Q.top(); Q.pop(); + Color u_color = get(color, u); + + BGL_FORALL_OUTEDGES_T(u, e, g, Graph) { + Vertex v = target(e, g); + Color v_color = get(color, v); + if (v_color == ColorTraits::white()) { + // We have not seen "v" before; mark it with the same color as u + Color u_color = get(color, u); + put(color, v, u_color); + + // Push it on the queue + Q.push(v); + } else if (v_color != ColorTraits::black() && u_color != v_color) { + // Colors have collided. We're done! + return true; + } + } + // u is done, so mark it black + put(color, u, ColorTraits::black()); + } + + return false; +} + +template +inline bool +st_connected(const Graph& g, + typename graph_traits::vertex_descriptor s, + typename graph_traits::vertex_descriptor t) +{ + return st_connected(g, s, t, + make_two_bit_color_map(num_vertices(g), + get(vertex_index, g))); +} + +} } // end namespace boost::graph + +#endif // BOOST_GRAPH_DISTRIBUTED_ST_CONNECTED_HPP diff --git a/include/boost/graph/strong_components.hpp b/include/boost/graph/strong_components.hpp index 0ed0b4a1..1931d86f 100644 --- a/include/boost/graph/strong_components.hpp +++ b/include/boost/graph/strong_components.hpp @@ -17,6 +17,7 @@ #include #include #include +#include namespace boost { @@ -219,7 +220,8 @@ namespace boost { class P, class T, class R> inline typename property_traits::value_type strong_components(const Graph& g, ComponentMap comp, - const bgl_named_params& params) + const bgl_named_params& params + BOOST_GRAPH_ENABLE_IF_MODELS_PARM(Graph, vertex_list_graph_tag)) { typedef typename graph_traits::directed_category DirCat; BOOST_STATIC_ASSERT((is_convertible::value == true)); @@ -229,7 +231,8 @@ namespace boost { template inline typename property_traits::value_type - strong_components(const Graph& g, ComponentMap comp) + strong_components(const Graph& g, ComponentMap comp + BOOST_GRAPH_ENABLE_IF_MODELS_PARM(Graph, vertex_list_graph_tag)) { typedef typename graph_traits::directed_category DirCat; BOOST_STATIC_ASSERT((is_convertible::value == true)); diff --git a/include/boost/graph/vertex_and_edge_range.hpp b/include/boost/graph/vertex_and_edge_range.hpp new file mode 100644 index 00000000..acddbb42 --- /dev/null +++ b/include/boost/graph/vertex_and_edge_range.hpp @@ -0,0 +1,141 @@ +// Copyright 2004 The Trustees of Indiana University. + +// 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) + +// Authors: Douglas Gregor +// Andrew Lumsdaine + +#ifndef BOOST_GRAPH_VERTEX_AND_EDGE_RANGE_HPP +#define BOOST_GRAPH_VERTEX_AND_EDGE_RANGE_HPP + +#include +#include + +namespace boost { + +namespace graph { + template + class vertex_and_edge_range + { + typedef graph_traits traits_type; + + public: + typedef typename traits_type::directed_category directed_category; + typedef typename traits_type::edge_parallel_category + edge_parallel_category; + struct traversal_category + : public virtual vertex_list_graph_tag, + public virtual edge_list_graph_tag { }; + + typedef std::size_t vertices_size_type; + typedef VertexIterator vertex_iterator; + typedef typename std::iterator_traits::value_type + vertex_descriptor; + + typedef EdgeIterator edge_iterator; + typedef typename std::iterator_traits::value_type + edge_descriptor; + + typedef std::size_t edges_size_type; + + typedef void adjacency_iterator; + typedef void out_edge_iterator; + typedef void in_edge_iterator; + typedef void degree_size_type; + + static vertex_descriptor null_vertex() + { return traits_type::null_vertex(); } + + vertex_and_edge_range(const Graph& g, + VertexIterator first_v, VertexIterator last_v, + vertices_size_type n, + EdgeIterator first_e, EdgeIterator last_e, + edges_size_type m) + : g(&g), + first_vertex(first_v), last_vertex(last_v), m_num_vertices(n), + first_edge(first_e), last_edge(last_e), m_num_edges(m) + { + } + + vertex_and_edge_range(const Graph& g, + VertexIterator first_v, VertexIterator last_v, + EdgeIterator first_e, EdgeIterator last_e) + : g(&g), + first_vertex(first_v), last_vertex(last_v), + first_edge(first_e), last_edge(last_e) + { + m_num_vertices = std::distance(first_v, last_v); + m_num_edges = std::distance(first_e, last_e); + } + + const Graph* g; + vertex_iterator first_vertex; + vertex_iterator last_vertex; + vertices_size_type m_num_vertices; + edge_iterator first_edge; + edge_iterator last_edge; + edges_size_type m_num_edges; + }; + + template + inline std::pair + vertices(const vertex_and_edge_range& g) + { return std::make_pair(g.first_vertex, g.last_vertex); } + + template + inline typename vertex_and_edge_range + ::vertices_size_type + num_vertices(const vertex_and_edge_range& g) + { return g.m_num_vertices; } + + template + inline std::pair + edges(const vertex_and_edge_range& g) + { return std::make_pair(g.first_edge, g.last_edge); } + + template + inline typename vertex_and_edge_range + ::edges_size_type + num_edges(const vertex_and_edge_range& g) + { return g.m_num_edges; } + + template + inline typename vertex_and_edge_range + ::vertex_descriptor + source(typename vertex_and_edge_range + ::edge_descriptor e, + const vertex_and_edge_range& g) + { return source(e, *g.g); } + + template + inline typename vertex_and_edge_range + ::vertex_descriptor + target(typename vertex_and_edge_range + ::edge_descriptor e, + const vertex_and_edge_range& g) + { return target(e, *g.g); } + + template + inline vertex_and_edge_range + make_vertex_and_edge_range(const Graph& g, + VertexIterator first_v, VertexIterator last_v, + EdgeIterator first_e, EdgeIterator last_e) + { + typedef vertex_and_edge_range + result_type; + return result_type(g, first_v, last_v, first_e, last_e); + } + +} // end namespace graph + +using graph::vertex_and_edge_range; +using graph::make_vertex_and_edge_range; + +} // end namespace boost +#endif // BOOST_GRAPH_VERTEX_AND_EDGE_RANGE_HPP diff --git a/test/layout_test.cpp b/test/layout_test.cpp index a659333b..bf814125 100644 --- a/test/layout_test.cpp +++ b/test/layout_test.cpp @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -24,8 +25,9 @@ namespace boost { BOOST_INSTALL_PROPERTY(vertex, position); } struct point { - double x; - double y; + double x, y; + point(double x, double y): x(x), y(y) {} + point() {} }; template @@ -200,15 +202,17 @@ test_cube(Graph*) dump_graph_layout("cube", g, get(vertex_position, g)); minstd_rand gen; - random_graph_layout(g, get(vertex_position, g), -25.0, 25.0, -25.0, 25.0, + random_graph_layout(g, get(vertex_position, g), + point(-25.0, -25.0), + point(25.0, 25.0), gen); std::vector displacements(num_vertices(g)); fruchterman_reingold_force_directed_layout (g, get(vertex_position, g), - 50.0, - 50.0, + point(50.0, 50.0), + point(50.0, 50.0), square_distance_attractive_force(), square_distance_repulsive_force(), all_force_pairs(), @@ -267,7 +271,7 @@ test_triangular(Graph*) dump_graph_layout("triangular-kk", g, get(vertex_position, g)); minstd_rand gen; - random_graph_layout(g, get(vertex_position, g), -25.0, 25.0, -25.0, 25.0, + random_graph_layout(g, get(vertex_position, g), point(-25.0, -25.0), point(25.0, 25.0), gen); dump_graph_layout("random", g, get(vertex_position, g)); @@ -276,8 +280,8 @@ test_triangular(Graph*) fruchterman_reingold_force_directed_layout (g, get(vertex_position, g), - 50.0, - 50.0, + point(50.0, 50.0), + point(50.0, 50.0), attractive_force(square_distance_attractive_force()). cooling(linear_cooling(100))); @@ -327,15 +331,15 @@ test_disconnected(Graph*) BOOST_CHECK(!ok); minstd_rand gen; - random_graph_layout(g, get(vertex_position, g), -25.0, 25.0, -25.0, 25.0, + random_graph_layout(g, get(vertex_position, g), point(-25.0, -25.0), point(25.0, 25.0), gen); std::vector displacements(num_vertices(g)); fruchterman_reingold_force_directed_layout (g, get(vertex_position, g), - 50.0, - 50.0, + point(50.0, 50.0), + point(50.0, 50.0), attractive_force(square_distance_attractive_force()). cooling(linear_cooling(50))); From 7ce44fc213ec67d59fc7bb279e79fe8b11306640 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Wed, 1 Apr 2009 18:49:52 +0000 Subject: [PATCH 102/224] Removed #if 0 code [SVN r52117] --- include/boost/graph/dimacs.hpp | 94 ---------------------------------- 1 file changed, 94 deletions(-) diff --git a/include/boost/graph/dimacs.hpp b/include/boost/graph/dimacs.hpp index 4f8c1f4f..4dadb7a1 100644 --- a/include/boost/graph/dimacs.hpp +++ b/include/boost/graph/dimacs.hpp @@ -195,100 +195,6 @@ protected: bool want_weights; }; -#if 0 -class dimacs_indexed_reader : public dimacs_basic_reader { -public: - dimacs_indexed_reader( std::istream& in, std::istream& idx ) : - dimacs_basic_reader( in ), - index( idx ), start( 0 ), stop( 0 ), still_reading( true ) { - - int n = process_id( pg ); - std::stringstream instr; - - while( getline( index, buf ) ) { - instr.str( buf ); - instr.clear(); - long p, begin, end; - - instr >> p >> begin >> end; - - if( p == n ) { - start = begin; - stop = end; - break; - } - } - - std::cerr << "start is " << start << " stop is " << stop << std::endl; - assert( start != 0 && stop != 0 ); - inpt.seekg( start, std::ios::beg ); - - //what a kludge! - seen_edges = 0; - read_edges.pop(); - incr( dimacs_basic_reader::edge_weight ); - } - - dimacs_indexed_reader() : dimacs_basic_reader(), index( std::cin ) { - } - bool done_edges() { - return (stop < 0 ? (long)inpt.tellg() == stop && read_edges.size() == 0 : (long)inpt.tellg()) - >= stop && read_edges.size() == 0; - } - - inline dimacs_indexed_reader incr( incr_mode mode ) { - if( mode == edge ) { - assert( !read_edges.empty() ); - read_edges.pop(); - } - else if( mode == edge_weight ) { - assert( !read_edge_weights.empty() ); - read_edge_weights.pop(); - } - - if( (mode == edge && read_edges.empty()) || - (mode == edge_weight && read_edge_weights.empty() )) { - - if( seen_edges > num_edges ) { - boost::throw_exception(dimacs_exception()); - } - - while( getline( inpt, buf ) && !buf.empty() && buf[0] == 'c' ); - - if( still_reading && !inpt.eof() ) { - std::stringstream instr( buf ); - vertices_size_type source, dest; - edge_weight_type weight; - instr >> buf >> source >> dest >> weight; - seen_edges++; - - // take care of indexing - source--; - dest--; - - read_edges.push( edge_type( source, dest ) ); - read_edge_weights.push( weight ); - } - still_reading = stop < 0 ? (long)inpt.tellg() != stop : (long)inpt.tellg() < stop; - assert( read_edges.size() < 100 ); - assert( read_edge_weights.size() < 100 ); - } - - // the 1000000 just happens to be about how many edges can be read in - // 10s - if( !(seen_edges % 1000000) && !process_id( pg ) && mode == edge ) { - // std::cout << "read " << seen_edges << " edges" << std::endl; - } - return *this; - } - -private: - std::istream& index; - long start, stop; - bool still_reading; -}; -#endif - template class dimacs_edge_iterator { public: From 5b53e4e6e8e3654c9e58145fd07b5c67e8ef850b Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Thu, 2 Apr 2009 17:59:22 +0000 Subject: [PATCH 103/224] Generalized layout algorithms to use extended version of topology objects from Gursoy-Atun layout; Kamada-Kawai now supports 3-D; random layout supports arbitrary topologies [SVN r52137] --- include/boost/graph/circle_layout.hpp | 19 +- include/boost/graph/fruchterman_reingold.hpp | 292 +++++----- include/boost/graph/gursoy_atun_layout.hpp | 276 +-------- .../graph/kamada_kawai_spring_layout.hpp | 184 +++--- include/boost/graph/random_layout.hpp | 29 +- include/boost/graph/topology.hpp | 527 ++++++++++++++++++ test/layout_test.cpp | 108 ++-- 7 files changed, 861 insertions(+), 574 deletions(-) create mode 100644 include/boost/graph/topology.hpp diff --git a/include/boost/graph/circle_layout.hpp b/include/boost/graph/circle_layout.hpp index 26387d14..9c6ca6ef 100644 --- a/include/boost/graph/circle_layout.hpp +++ b/include/boost/graph/circle_layout.hpp @@ -9,8 +9,12 @@ #ifndef BOOST_GRAPH_CIRCLE_LAYOUT_HPP #define BOOST_GRAPH_CIRCLE_LAYOUT_HPP #include +#include #include #include +#include +#include +#include namespace boost { /** @@ -28,7 +32,8 @@ namespace boost { circle_graph_layout(const VertexListGraph& g, PositionMap position, Radius radius) { - const double pi = 3.14159; + BOOST_STATIC_ASSERT (property_traits::value_type::dimensions >= 2); + const double pi = boost::math::constants::pi(); #ifndef BOOST_NO_STDC_NAMESPACE using std::sin; @@ -40,14 +45,12 @@ namespace boost { vertices_size_type n = num_vertices(g); - typedef typename graph_traits::vertex_iterator - vertex_iterator; - vertices_size_type i = 0; - for(std::pair v = vertices(g); - v.first != v.second; ++v.first, ++i) { - position[*v.first].x = radius * cos(i * 2 * pi / n); - position[*v.first].y = radius * sin(i * 2 * pi / n); + double two_pi_over_n = 2. * pi / n; + BGL_FORALL_VERTICES_T(v, g, VertexListGraph) { + position[v][0] = radius * cos(i * two_pi_over_n); + position[v][1] = radius * sin(i * two_pi_over_n); + ++i; } } } // end namespace boost diff --git a/include/boost/graph/fruchterman_reingold.hpp b/include/boost/graph/fruchterman_reingold.hpp index 14235284..e90b30cd 100644 --- a/include/boost/graph/fruchterman_reingold.hpp +++ b/include/boost/graph/fruchterman_reingold.hpp @@ -12,12 +12,13 @@ #include #include #include +#include +#include // For topology concepts #include #include #include // for std::min and std::max #include // for std::accumulate #include // for std::sqrt and std::fabs -#include // for hypot (not in ) #include #include // for drand48 @@ -91,22 +92,24 @@ struct all_force_pairs } }; -template +template struct grid_force_pairs { typedef typename property_traits::value_type Point; - typedef double Dim; + BOOST_STATIC_ASSERT (Point::dimensions == 2); + typedef typename Topology::point_difference_type point_difference_type; template explicit - grid_force_pairs(const Point& origin, const Point& extent, + grid_force_pairs(const Topology& topology, + const Point& origin, const point_difference_type& extent, PositionMap position, const Graph& g) - : width(extent.x), height(extent.y), position(position) + : topology(topology), extent(extent), origin(origin), position(position) { #ifndef BOOST_NO_STDC_NAMESPACE using std::sqrt; #endif // BOOST_NO_STDC_NAMESPACE - two_k = Dim(2) * sqrt(width * height / num_vertices(g)); + two_k = 2. * topology.volume(extent) / sqrt(num_vertices(g)); } template @@ -121,13 +124,13 @@ struct grid_force_pairs using std::sqrt; #endif // BOOST_NO_STDC_NAMESPACE - std::size_t columns = std::size_t(width / two_k + Dim(1)); - std::size_t rows = std::size_t(height / two_k + Dim(1)); + std::size_t columns = std::size_t(extent[0] / two_k + 1.); + std::size_t rows = std::size_t(extent[1] / two_k + 1.); buckets_t buckets(rows * columns); vertex_iterator v, v_end; for (tie(v, v_end) = vertices(g); v != v_end; ++v) { - std::size_t column = std::size_t((position[*v].x + width / 2) / two_k); - std::size_t row = std::size_t((position[*v].y + height / 2) / two_k); + std::size_t column = std::size_t((position[*v][0] + extent[0] / 2) / two_k); + std::size_t row = std::size_t((position[*v][1] + extent[1] / 2) / two_k); if (column >= columns) column = columns - 1; if (row >= rows) row = rows - 1; @@ -159,9 +162,7 @@ struct grid_force_pairs bucket_t& other_bucket = buckets[other_row * columns + other_column]; for (v = other_bucket.begin(); v != other_bucket.end(); ++v) { - Dim delta_x = position[*u].x - position[*v].x; - Dim delta_y = position[*u].y - position[*v].y; - Dim dist = hypot(delta_x, delta_y); + double dist = topology.distance(position[*u], position[*v]); if (dist < two_k) apply_force(*u, *v); } } @@ -170,97 +171,89 @@ struct grid_force_pairs } private: - Dim width; - Dim height; + const Topology& topology; + point_difference_type extent; + Point origin; PositionMap position; - Dim two_k; + double two_k; }; -template -inline grid_force_pairs +template +inline grid_force_pairs make_grid_force_pairs - (typename property_traits::value_type const& origin, - typename property_traits::value_type const& extent, + (const Topology& topology, + typename Topology::point_type const& origin, + typename Topology::point_difference_type const& extent, const PositionMap& position, const Graph& g) -{ return grid_force_pairs(origin, extent, position, g); } +{ return grid_force_pairs(topology, origin, extent, position, g); } -template +template void -scale_graph(const Graph& g, PositionMap position, - Dim left, Dim top, Dim right, Dim bottom) +scale_graph(const Graph& g, PositionMap position, const Topology& topology, + typename Topology::point_type upper_left, typename Topology::point_type lower_right) { if (num_vertices(g) == 0) return; - if (bottom > top) { - using std::swap; - swap(bottom, top); - } - - typedef typename graph_traits::vertex_iterator vertex_iterator; + typedef typename Topology::point_type Point; + typedef typename Topology::point_difference_type point_difference_type; // Find min/max ranges - Dim minX = position[*vertices(g).first].x, maxX = minX; - Dim minY = position[*vertices(g).first].y, maxY = minY; - vertex_iterator vi, vi_end; - for (tie(vi, vi_end) = vertices(g); vi != vi_end; ++vi) { - BOOST_USING_STD_MIN(); - BOOST_USING_STD_MAX(); - minX = min BOOST_PREVENT_MACRO_SUBSTITUTION (minX, position[*vi].x); - maxX = max BOOST_PREVENT_MACRO_SUBSTITUTION (maxX, position[*vi].x); - minY = min BOOST_PREVENT_MACRO_SUBSTITUTION (minY, position[*vi].y); - maxY = max BOOST_PREVENT_MACRO_SUBSTITUTION (maxY, position[*vi].y); + Point min_point = position[*vertices(g).first], max_point = min_point; + BGL_FORALL_VERTICES_T(v, g, Graph) { + min_point = topology.pointwise_min(min_point, position[v]); + max_point = topology.pointwise_max(max_point, position[v]); } + Point old_origin = topology.move_position_toward(min_point, 0.5, max_point); + Point new_origin = topology.move_position_toward(upper_left, 0.5, lower_right); + point_difference_type old_size = topology.difference(max_point, min_point); + point_difference_type new_size = topology.difference(lower_right, upper_left); + // Scale to bounding box provided - for (tie(vi, vi_end) = vertices(g); vi != vi_end; ++vi) { - position[*vi].x = ((position[*vi].x - minX) / (maxX - minX)) - * (right - left) + left; - position[*vi].y = ((position[*vi].y - minY) / (maxY - minY)) - * (top - bottom) + bottom; + BGL_FORALL_VERTICES_T(v, g, Graph) { + point_difference_type relative_loc = topology.difference(position[v], old_origin); + relative_loc = (relative_loc / old_size) * new_size; + position[v] = topology.adjust(new_origin, relative_loc); } } namespace detail { - template + template void - maybe_jitter_point(Point& p1, const Point& p2, Point origin, Point extent) + maybe_jitter_point(const Topology& topology, + typename Topology::point_type& p1, const typename Topology::point_type& p2, + typename Topology::point_type origin, typename Topology::point_difference_type extent) { #ifndef BOOST_NO_STDC_NAMESPACE using std::sqrt; using std::fabs; #endif // BOOST_NO_STDC_NAMESPACE - typedef double Dim; - Dim too_close_x = extent.x / Dim(10000); - if (fabs(p1.x - p2.x) < too_close_x) { - Dim dist_to_move = sqrt(extent.x) / Dim(200); - if (p1.x - origin.x < origin.x + extent.x - p1.x) - p1.x += dist_to_move * drand48(); - else - p1.x -= dist_to_move * drand48(); - } - Dim too_close_y = extent.y / Dim(10000); - if (fabs(p1.y - p2.y) < too_close_y) { - Dim dist_to_move = sqrt(extent.y) / Dim(200); - if (p1.y - origin.y < origin.y + extent.y - p1.y) - p1.y += dist_to_move * drand48(); - else - p1.y -= dist_to_move * drand48(); + double too_close = topology.norm(extent) / 10000.; + if (topology.distance(p1, p2) < too_close) { + double dist_to_move = sqrt(topology.norm(extent)) / 200.; + for (std::size_t i = 0; i < Topology::point_type::dimensions; ++i) { + if (p1[i] - origin[i] < origin[i] + extent[i] - p1[i]) + p1[i] += dist_to_move * drand48(); + else + p1[i] -= dist_to_move * drand48(); + } } } - template struct fr_apply_force { typedef typename graph_traits::vertex_descriptor vertex_descriptor; - typedef typename property_traits::value_type Point; - typedef double Dim; + typedef typename Topology::point_type Point; + typedef typename Topology::point_difference_type PointDiff; - fr_apply_force(const PositionMap& position, + fr_apply_force(const Topology& topology, + const PositionMap& position, const DisplacementMap& displacement, - Point origin, Point extent, - RepulsiveForce repulsive_force, Dim k, const Graph& g) - : position(position), displacement(displacement), origin(origin), + Point origin, PointDiff extent, + RepulsiveForce repulsive_force, double k, const Graph& g) + : topology(topology), position(position), displacement(displacement), origin(origin), extent(extent), repulsive_force(repulsive_force), k(k), g(g) { } @@ -272,75 +265,76 @@ namespace detail { if (u != v) { // When the vertices land on top of each other, move the // first vertex away from the boundaries. - maybe_jitter_point(position[u], position[v], origin, extent); + maybe_jitter_point(topology, position[u], position[v], origin, extent); - // DPG TBD: Can we use the Topology concept's - // distance/move_position_toward to handle this? - Dim delta_x = position[v].x - position[u].x; - Dim delta_y = position[v].y - position[u].y; - Dim dist = hypot(delta_x, delta_y); - if (dist == Dim(0)) { - displacement[v].x += 0.01; - displacement[v].y += 0.01; + double dist = topology.distance(position[u], position[v]); + if (dist == 0.) { + for (std::size_t i = 0; i < Point::dimensions; ++i) { + displacement[v][i] += 0.01; + } } else { - Dim fr = repulsive_force(u, v, k, dist, g); - displacement[v].x += delta_x / dist * fr; - displacement[v].y += delta_y / dist * fr; + double fr = repulsive_force(u, v, k, dist, g); + typename Topology::point_difference_type dispv = displacement[v]; + dispv += (fr / dist) * topology.difference(position[v], position[u]); } } } private: + const Topology& topology; PositionMap position; DisplacementMap displacement; Point origin; - Point extent; + PointDiff extent; RepulsiveForce repulsive_force; - Dim k; + double k; const Graph& g; }; } // end namespace detail -template void fruchterman_reingold_force_directed_layout (const Graph& g, PositionMap position, - typename property_traits::value_type const& origin, - typename property_traits::value_type const& extent, + const Topology& topology, + typename Topology::point_type const& origin, + typename Topology::point_difference_type const& extent, AttractiveForce attractive_force, RepulsiveForce repulsive_force, ForcePairs force_pairs, Cooling cool, DisplacementMap displacement) { - typedef typename property_traits::value_type Point; - typedef double Dim; + 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; #ifndef BOOST_NO_STDC_NAMESPACE using std::sqrt; + using std::pow; #endif // BOOST_NO_STDC_NAMESPACE - Dim volume = extent.x * extent.y; + double volume = 1.; + for (std::size_t i = 0; i < Topology::point_difference_type::dimensions; ++i) + volume *= extent[i]; // assume positions are initialized randomly - Dim k = sqrt(volume / num_vertices(g)); + double k = pow(volume / num_vertices(g), 1. / (double)(Topology::point_difference_type::dimensions)); - detail::fr_apply_force - apply_force(position, displacement, origin, extent, repulsive_force, k, g); + apply_force(topology, position, displacement, origin, extent, repulsive_force, k, g); do { // Calculate repulsive forces vertex_iterator v, v_end; for (tie(v, v_end) = vertices(g); v != v_end; ++v) - displacement[*v] = Point(); + displacement[*v] = typename Topology::point_difference_type(); force_pairs(g, apply_force); // Calculate attractive forces @@ -351,62 +345,32 @@ fruchterman_reingold_force_directed_layout // When the vertices land on top of each other, move the // first vertex away from the boundaries. - ::boost::detail::maybe_jitter_point(position[u], position[v], + ::boost::detail::maybe_jitter_point(topology, position[u], position[v], origin, extent); - // DPG TBD: Can we use the Topology concept's - // distance/move_position_toward to handle this? - Dim delta_x = position[v].x - position[u].x; - Dim delta_y = position[v].y - position[u].y; - Dim dist = hypot(delta_x, delta_y); - Dim fa = attractive_force(*e, k, dist, g); + typename Topology::point_difference_type delta = topology.difference(position[v], position[u]); + double dist = topology.distance(position[u], position[v]); + double fa = attractive_force(*e, k, dist, g); - displacement[v].x -= delta_x / dist * fa; - displacement[v].y -= delta_y / dist * fa; - displacement[u].x += delta_x / dist * fa; - displacement[u].y += delta_y / dist * fa; + displacement[v] -= (fa / dist) * delta; + displacement[u] += (fa / dist) * delta; } - if (Dim temp = cool()) { + if (double temp = cool()) { // Update positions - for (tie(v, v_end) = vertices(g); v != v_end; ++v) { + BGL_FORALL_VERTICES_T (v, g, Graph) { BOOST_USING_STD_MIN(); BOOST_USING_STD_MAX(); - Dim disp_size = hypot(displacement[*v].x, displacement[*v].y); - { - position[*v].x += displacement[*v].x / disp_size - * (min)(disp_size, temp); - if (vertex_migration) { - position[*v].x = (min)(Dim(1.0), - (max)(Dim(-1.0), position[*v].x)); - } else { - position[*v].x = (min)(origin.x + extent.x, - (max)(origin.x, position[*v].x)); - } - - // CEM HACK: Jitter if we're on the edges - if(position[*v].x == 1.0f) // origin.x + extent.x) - position[*v].x -= drand48() * .1 * extent.x; - else if(position[*v].x == -1.0f) // origin.x) - position[*v].x += drand48() * .1 * extent.x; - } - { - position[*v].y += displacement[*v].y / disp_size - * (min)(disp_size, temp); - if (vertex_migration) { - position[*v].y = (min)(Dim(1.0), - (max)(Dim(-1.0), position[*v].y)); - } else { - position[*v].y = (min)(origin.y + extent.y, - (max)(origin.y, position[*v].y)); - } - - // CEM HACK: Jitter if we're on the edges - if(position[*v].y == 1.0f) // origin.y + extent.y) - position[*v].y -= drand48() * .1 * extent.y; - else if(position[*v].y == -1.0f) // origin.y) - position[*v].y += drand48() * .1 * extent.y; - } + double disp_size = topology.norm(displacement[v]); + position[v] = topology.adjust(position[v], displacement[v] * (min BOOST_PREVENT_MACRO_SUBSTITUTION (disp_size, temp) / disp_size)); + position[v] = topology.bound(position[v]); +#if 0 + // CEM HACK: Jitter if we're on the edges + if(position[v].x == 1.0f) // origin.x + extent.x) + position[v].x -= drand48() * .1 * extent.x; + else if(position[v].x == -1.0f) // origin.x) + position[v].x += drand48() * .1 * extent.x; +#endif } } else { break; @@ -418,15 +382,16 @@ namespace detail { template struct fr_force_directed_layout { - template static void run(const Graph& g, PositionMap position, - typename property_traits::value_type const& origin, - typename property_traits::value_type const& extent, + const Topology& topology, + typename Topology::point_type const& origin, + typename Topology::point_difference_type const& extent, AttractiveForce attractive_force, RepulsiveForce repulsive_force, ForcePairs force_pairs, @@ -435,7 +400,7 @@ namespace detail { const bgl_named_params&) { fruchterman_reingold_force_directed_layout - (g, position, origin, extent, attractive_force, repulsive_force, + (g, position, topology, origin, extent, attractive_force, repulsive_force, force_pairs, cool, displacement); } }; @@ -443,15 +408,16 @@ namespace detail { template<> struct fr_force_directed_layout { - template static void run(const Graph& g, PositionMap position, - typename property_traits::value_type const& origin, - typename property_traits::value_type const& extent, + const Topology& topology, + typename Topology::point_type const& origin, + typename Topology::point_difference_type const& extent, AttractiveForce attractive_force, RepulsiveForce repulsive_force, ForcePairs force_pairs, @@ -459,58 +425,60 @@ namespace detail { error_property_not_found, const bgl_named_params& params) { - typedef typename property_traits::value_type Point; - std::vector displacements(num_vertices(g)); + typedef typename Topology::point_difference_type PointDiff; + std::vector displacements(num_vertices(g)); fruchterman_reingold_force_directed_layout - (g, position, origin, extent, attractive_force, repulsive_force, + (g, position, topology, origin, extent, attractive_force, repulsive_force, force_pairs, cool, make_iterator_property_map (displacements.begin(), choose_const_pmap(get_param(params, vertex_index), g, vertex_index), - Point())); + PointDiff())); } }; } // end namespace detail -template void fruchterman_reingold_force_directed_layout (const Graph& g, PositionMap position, - typename property_traits::value_type const& origin, - typename property_traits::value_type const& extent, + const Topology& topology, + typename Topology::point_type const& origin, + typename Topology::point_difference_type const& extent, const bgl_named_params& params) { typedef typename property_value, vertex_displacement_t>::type D; detail::fr_force_directed_layout::run - (g, position, origin, extent, + (g, position, topology, origin, extent, choose_param(get_param(params, attractive_force_t()), square_distance_attractive_force()), choose_param(get_param(params, repulsive_force_t()), square_distance_repulsive_force()), choose_param(get_param(params, force_pairs_t()), - make_grid_force_pairs(origin, extent, position, g)), + make_grid_force_pairs(topology, origin, extent, position, g)), choose_param(get_param(params, cooling_t()), linear_cooling(100)), get_param(params, vertex_displacement_t()), params); } -template +template void fruchterman_reingold_force_directed_layout (const Graph& g, PositionMap position, - typename property_traits::value_type const& origin, - typename property_traits::value_type const& extent) + const Topology& topology, + typename Topology::point_type const& origin, + typename Topology::point_difference_type const& extent) { fruchterman_reingold_force_directed_layout - (g, position, origin, extent, + (g, position, topology, origin, extent, attractive_force(square_distance_attractive_force())); } diff --git a/include/boost/graph/gursoy_atun_layout.hpp b/include/boost/graph/gursoy_atun_layout.hpp index 7cc1f973..ed5e0509 100644 --- a/include/boost/graph/gursoy_atun_layout.hpp +++ b/include/boost/graph/gursoy_atun_layout.hpp @@ -28,6 +28,7 @@ #include #include #include +#include namespace boost { @@ -351,281 +352,6 @@ gursoy_atun_layout(const VertexListAndIncidenceGraph& graph, dummy_property_map())); } -/*********************************************************** - * Topologies * - ***********************************************************/ -template -class convex_topology -{ - struct point - { - point() { } - double& operator[](std::size_t i) {return values[i];} - const double& operator[](std::size_t i) const {return values[i];} - - private: - double values[Dims]; - }; - - public: - typedef point point_type; - - double distance(point a, point b) const - { - double dist = 0; - for (std::size_t i = 0; i < Dims; ++i) { - double diff = b[i] - a[i]; - dist += diff * diff; - } - // Exact properties of the distance are not important, as long as - // < on what this returns matches real distances - return dist; - } - - point move_position_toward(point a, double fraction, point b) const - { - point result; - for (std::size_t i = 0; i < Dims; ++i) - result[i] = a[i] + (b[i] - a[i]) * fraction; - return result; - } -}; - -template -class hypercube_topology : public convex_topology -{ - typedef uniform_01 rand_t; - - public: - typedef typename convex_topology::point_type point_type; - - explicit hypercube_topology(double scaling = 1.0) - : gen_ptr(new RandomNumberGenerator), rand(new rand_t(*gen_ptr)), - scaling(scaling) - { } - - hypercube_topology(RandomNumberGenerator& gen, double scaling = 1.0) - : gen_ptr(), rand(new rand_t(gen)), scaling(scaling) { } - - point_type random_point() const - { - point_type p; - for (std::size_t i = 0; i < Dims; ++i) - p[i] = (*rand)() * scaling; - return p; - } - - private: - shared_ptr gen_ptr; - shared_ptr rand; - double scaling; -}; - -template -class square_topology : public hypercube_topology<2, RandomNumberGenerator> -{ - typedef hypercube_topology<2, RandomNumberGenerator> inherited; - - public: - explicit square_topology(double scaling = 1.0) : inherited(scaling) { } - - square_topology(RandomNumberGenerator& gen, double scaling = 1.0) - : inherited(gen, scaling) { } -}; - -template -class cube_topology : public hypercube_topology<3, RandomNumberGenerator> -{ - typedef hypercube_topology<3, RandomNumberGenerator> inherited; - - public: - explicit cube_topology(double scaling = 1.0) : inherited(scaling) { } - - cube_topology(RandomNumberGenerator& gen, double scaling = 1.0) - : inherited(gen, scaling) { } -}; - -template -class ball_topology : public convex_topology -{ - typedef uniform_01 rand_t; - - public: - typedef typename convex_topology::point_type point_type; - - explicit ball_topology(double radius = 1.0) - : gen_ptr(new RandomNumberGenerator), rand(new rand_t(*gen_ptr)), - radius(radius) - { } - - ball_topology(RandomNumberGenerator& gen, double radius = 1.0) - : gen_ptr(), rand(new rand_t(gen)), radius(radius) { } - - point_type random_point() const - { - point_type p; - double dist_sum; - do { - dist_sum = 0.0; - for (std::size_t i = 0; i < Dims; ++i) { - double x = (*rand)() * 2*radius - radius; - p[i] = x; - dist_sum += x * x; - } - } while (dist_sum > radius*radius); - return p; - } - - private: - shared_ptr gen_ptr; - shared_ptr rand; - double radius; -}; - -template -class circle_topology : public ball_topology<2, RandomNumberGenerator> -{ - typedef ball_topology<2, RandomNumberGenerator> inherited; - - public: - explicit circle_topology(double radius = 1.0) : inherited(radius) { } - - circle_topology(RandomNumberGenerator& gen, double radius = 1.0) - : inherited(gen, radius) { } -}; - -template -class sphere_topology : public ball_topology<3, RandomNumberGenerator> -{ - typedef ball_topology<3, RandomNumberGenerator> inherited; - - public: - explicit sphere_topology(double radius = 1.0) : inherited(radius) { } - - sphere_topology(RandomNumberGenerator& gen, double radius = 1.0) - : inherited(gen, radius) { } -}; - -template -class heart_topology -{ - // Heart is defined as the union of three shapes: - // Square w/ corners (+-1000, -1000), (0, 0), (0, -2000) - // Circle centered at (-500, -500) radius 500*sqrt(2) - // Circle centered at (500, -500) radius 500*sqrt(2) - // Bounding box (-1000, -2000) - (1000, 500*(sqrt(2) - 1)) - - struct point - { - point() { values[0] = 0.0; values[1] = 0.0; } - point(double x, double y) { values[0] = x; values[1] = y; } - - double& operator[](std::size_t i) { return values[i]; } - double operator[](std::size_t i) const { return values[i]; } - - private: - double values[2]; - }; - - bool in_heart(point p) const - { -#ifndef BOOST_NO_STDC_NAMESPACE - using std::abs; - using std::pow; -#endif - - if (p[1] < abs(p[0]) - 2000) return false; // Bottom - if (p[1] <= -1000) return true; // Diagonal of square - if (pow(p[0] - -500, 2) + pow(p[1] - -500, 2) <= 500000) - return true; // Left circle - if (pow(p[0] - 500, 2) + pow(p[1] - -500, 2) <= 500000) - return true; // Right circle - return false; - } - - bool segment_within_heart(point p1, point p2) const - { - // Assumes that p1 and p2 are within the heart - if ((p1[0] < 0) == (p2[0] < 0)) return true; // Same side of symmetry line - if (p1[0] == p2[0]) return true; // Vertical - double slope = (p2[1] - p1[1]) / (p2[0] - p1[0]); - double intercept = p1[1] - p1[0] * slope; - if (intercept > 0) return false; // Crosses between circles - return true; - } - - typedef uniform_01 rand_t; - - public: - typedef point point_type; - - heart_topology() - : gen_ptr(new RandomNumberGenerator), rand(new rand_t(*gen_ptr)) { } - - heart_topology(RandomNumberGenerator& gen) - : gen_ptr(), rand(new rand_t(gen)) { } - - point random_point() const - { -#ifndef BOOST_NO_STDC_NAMESPACE - using std::sqrt; -#endif - - point result; - double sqrt2 = sqrt(2.); - do { - result[0] = (*rand)() * (1000 + 1000 * sqrt2) - (500 + 500 * sqrt2); - result[1] = (*rand)() * (2000 + 500 * (sqrt2 - 1)) - 2000; - } while (!in_heart(result)); - return result; - } - - double distance(point a, point b) const - { -#ifndef BOOST_NO_STDC_NAMESPACE - using std::sqrt; -#endif - if (segment_within_heart(a, b)) { - // Straight line - return sqrt((b[0] - a[0]) * (b[0] - a[0]) + (b[1] - a[1]) * (b[1] - a[1])); - } else { - // Straight line bending around (0, 0) - return sqrt(a[0] * a[0] + a[1] * a[1]) + sqrt(b[0] * b[0] + b[1] * b[1]); - } - } - - point move_position_toward(point a, double fraction, point b) const - { -#ifndef BOOST_NO_STDC_NAMESPACE - using std::sqrt; -#endif - - if (segment_within_heart(a, b)) { - // Straight line - return point(a[0] + (b[0] - a[0]) * fraction, - a[1] + (b[1] - a[1]) * fraction); - } else { - double distance_to_point_a = sqrt(a[0] * a[0] + a[1] * a[1]); - double distance_to_point_b = sqrt(b[0] * b[0] + b[1] * b[1]); - double location_of_point = distance_to_point_a / - (distance_to_point_a + distance_to_point_b); - if (fraction < location_of_point) - return point(a[0] * (1 - fraction / location_of_point), - a[1] * (1 - fraction / location_of_point)); - else - return point( - b[0] * ((fraction - location_of_point) / (1 - location_of_point)), - b[1] * ((fraction - location_of_point) / (1 - location_of_point))); - } - } - - private: - shared_ptr gen_ptr; - shared_ptr rand; -}; - } // namespace boost #endif // BOOST_GRAPH_GURSOY_ATUN_LAYOUT_HPP diff --git a/include/boost/graph/kamada_kawai_spring_layout.hpp b/include/boost/graph/kamada_kawai_spring_layout.hpp index 00dbcb76..d846cd5d 100644 --- a/include/boost/graph/kamada_kawai_spring_layout.hpp +++ b/include/boost/graph/kamada_kawai_spring_layout.hpp @@ -10,6 +10,8 @@ #define BOOST_GRAPH_KAMADA_KAWAI_SPRING_LAYOUT_HPP #include +#include +#include #include #include #include @@ -67,22 +69,82 @@ namespace boost { return length.value / result; } + /** + * Dense linear solver for fixed-size matrices. + */ + template + struct linear_solver { + // Indices in mat are (row, column) + // template + // static Vec solve(double mat[Size][Size], Vec rhs); + }; + + template <> + struct linear_solver<1> { + template + static Vec solve(double mat[1][1], Vec rhs) { + return rhs / mat[0][0]; + } + }; + + // These are from http://en.wikipedia.org/wiki/Cramer%27s_rule + template <> + struct linear_solver<2> { + template + static Vec solve(double mat[2][2], Vec rhs) { + double denom = mat[0][0] * mat[1][1] - mat[1][0] * mat[0][1]; + double x_num = rhs[0] * mat[1][1] - rhs[1] * mat[0][1]; + double y_num = mat[0][0] * rhs[1] - mat[1][0] * rhs[0] ; + Vec result; + result[0] = x_num / denom; + result[1] = y_num / denom; + return result; + } + }; + + template <> + struct linear_solver<3> { + template + static Vec solve(double mat[2][2], Vec rhs) { + double denom = mat[0][0] * (mat[1][1] * mat[2][2] - mat[2][1] * mat[1][2]) + - mat[1][0] * (mat[0][1] * mat[2][2] - mat[2][1] * mat[0][2]) + + mat[2][0] * (mat[0][1] * mat[1][2] - mat[1][1] * mat[0][2]); + double x_num = rhs[0] * (mat[1][1] * mat[2][2] - mat[2][1] * mat[1][2]) + - rhs[1] * (mat[0][1] * mat[2][2] - mat[2][1] * mat[0][2]) + + rhs[2] * (mat[0][1] * mat[1][2] - mat[1][1] * mat[0][2]); + double y_num = mat[0][0] * (rhs[1] * mat[2][2] - rhs[2] * mat[1][2]) + - mat[1][0] * (rhs[0] * mat[2][2] - rhs[2] * mat[0][2]) + + mat[2][0] * (rhs[0] * mat[1][2] - rhs[1] * mat[0][2]); + double z_num = mat[0][0] * (mat[1][1] * rhs[2] - mat[2][1] * rhs[1] ) + - mat[1][0] * (mat[0][1] * rhs[2] - mat[2][1] * rhs[0] ) + + mat[2][0] * (mat[0][1] * rhs[1] - mat[1][1] * rhs[0] ); + Vec result; + result[0] = x_num / denom; + result[1] = y_num / denom; + result[2] = z_num / denom; + return result; + } + }; + /** * Implementation of the Kamada-Kawai spring layout algorithm. */ - template struct kamada_kawai_spring_layout_impl { typedef typename property_traits::value_type weight_type; - typedef std::pair deriv_type; + typedef typename Topology::point_type Point; + typedef typename Topology::point_difference_type point_difference_type; + typedef point_difference_type deriv_type; typedef typename graph_traits::vertex_iterator vertex_iterator; typedef typename graph_traits::vertex_descriptor vertex_descriptor; kamada_kawai_spring_layout_impl( + const Topology& topology, const Graph& g, PositionMap position, WeightMap weight, @@ -93,7 +155,7 @@ namespace boost { DistanceMatrix distance, SpringStrengthMatrix spring_strength, PartialDerivativeMap partial_derivatives) - : g(g), position(position), weight(weight), + : topology(topology), g(g), position(position), weight(weight), edge_or_side_length(edge_or_side_length), done(done), spring_constant(spring_constant), index(index), distance(distance), spring_strength(spring_strength), @@ -108,15 +170,12 @@ namespace boost { using std::sqrt; #endif // BOOST_NO_STDC_NAMESPACE - deriv_type result(0, 0); + deriv_type result; if (i != m) { - weight_type x_diff = position[m].x - position[i].x; - weight_type y_diff = position[m].y - position[i].y; - weight_type dist = sqrt(x_diff * x_diff + y_diff * y_diff); - result.first = spring_strength[get(index, m)][get(index, i)] - * (x_diff - distance[get(index, m)][get(index, i)]*x_diff/dist); - result.second = spring_strength[get(index, m)][get(index, i)] - * (y_diff - distance[get(index, m)][get(index, i)]*y_diff/dist); + point_difference_type diff = topology.difference(position[m], position[i]); + weight_type dist = topology.norm(diff); + result = spring_strength[get(index, m)][get(index, i)] + * (diff - distance[get(index, m)][get(index, i)]/dist*diff); } return result; @@ -130,15 +189,12 @@ namespace boost { using std::sqrt; #endif // BOOST_NO_STDC_NAMESPACE - deriv_type result(0, 0); + deriv_type result; // TBD: looks like an accumulate to me - std::pair verts = vertices(g); - for (/* no init */; verts.first != verts.second; ++verts.first) { - vertex_descriptor i = *verts.first; + BGL_FORALL_VERTICES_T(i, g, Graph) { deriv_type deriv = compute_partial_derivative(m, i); - result.first += deriv.first; - result.second += deriv.second; + result += deriv; } return result; @@ -185,8 +241,7 @@ namespace boost { deriv_type deriv = compute_partial_derivatives(*ui); put(partial_derivatives, *ui, deriv); - weight_type delta = - sqrt(deriv.first*deriv.first + deriv.second*deriv.second); + weight_type delta = topology.norm(deriv); if (delta > delta_p) { p = *ui; @@ -206,47 +261,48 @@ namespace boost { } do { - // Compute the 4 elements of the Jacobian - weight_type dE_dx_dx = 0, dE_dx_dy = 0, dE_dy_dx = 0, dE_dy_dy = 0; + // Compute the elements of the Jacobian + // From + // http://www.cs.panam.edu/~rfowler/papers/1994_kumar_fowler_A_Spring_UTPACSTR.pdf + // with the bugs fixed in the off-diagonal case + weight_type dE_d_d[Point::dimensions][Point::dimensions]; + 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) { vertex_descriptor i = *ui; if (i != p) { - weight_type x_diff = position[p].x - position[i].x; - weight_type y_diff = position[p].y - position[i].y; - weight_type dist = sqrt(x_diff * x_diff + y_diff * y_diff); - weight_type dist_cubed = dist * dist * dist; + point_difference_type diff = topology.difference(position[p], position[i]); + weight_type dist = topology.norm(diff); + weight_type dist_squared = dist * dist; + weight_type inv_dist_cubed = 1. / (dist_squared * dist); weight_type k_mi = spring_strength[get(index,p)][get(index,i)]; weight_type l_mi = distance[get(index, p)][get(index, i)]; - dE_dx_dx += k_mi * (1 - (l_mi * y_diff * y_diff)/dist_cubed); - dE_dx_dy += k_mi * l_mi * x_diff * y_diff / dist_cubed; - dE_dy_dx += k_mi * l_mi * x_diff * y_diff / dist_cubed; - dE_dy_dy += k_mi * (1 - (l_mi * x_diff * x_diff)/dist_cubed); + for (std::size_t i = 0; i < Point::dimensions; ++i) { + for (std::size_t j = 0; j < Point::dimensions; ++j) { + if (i == j) { + 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; + } + } + } } } - // Solve for delta_x and delta_y - weight_type dE_dx = get(partial_derivatives, p).first; - weight_type dE_dy = get(partial_derivatives, p).second; + deriv_type dE_d = get(partial_derivatives, p); - weight_type delta_x = - (dE_dx_dy * dE_dy - dE_dy_dy * dE_dx) - / (dE_dx_dx * dE_dy_dy - dE_dx_dy * dE_dy_dx); + // Solve dE_d_d * delta = dE_d to get delta + point_difference_type delta = -linear_solver::solve(dE_d_d, dE_d); - weight_type delta_y = - (dE_dx_dx * dE_dy - dE_dy_dx * dE_dx) - / (dE_dy_dx * dE_dx_dy - dE_dx_dx * dE_dy_dy); - - - // Move p by (delta_x, delta_y) - position[p].x += delta_x; - position[p].y += delta_y; + // Move p by delta + position[p] = topology.adjust(position[p], delta); // Recompute partial derivatives and delta_p deriv_type deriv = compute_partial_derivatives(p); put(partial_derivatives, p, deriv); - delta_p = - sqrt(deriv.first*deriv.first + deriv.second*deriv.second); + delta_p = topology.norm(deriv); } while (!done(delta_p, p, g, false)); // Select new p by updating each partial derivative and delta @@ -257,12 +313,10 @@ namespace boost { compute_partial_derivative(*ui, old_p); deriv_type deriv = get(partial_derivatives, *ui); - deriv.first += old_p_partial.first - old_deriv_p.first; - deriv.second += old_p_partial.second - old_deriv_p.second; + deriv += old_p_partial - old_deriv_p; put(partial_derivatives, *ui, deriv); - weight_type delta = - sqrt(deriv.first*deriv.first + deriv.second*deriv.second); + weight_type delta = topology.norm(deriv); if (delta > delta_p) { p = *ui; @@ -274,6 +328,7 @@ namespace boost { return true; } + const Topology& topology; const Graph& g; PositionMap position; WeightMap weight; @@ -417,7 +472,7 @@ namespace boost { * \returns @c true if layout was successful or @c false if a * negative weight cycle was detected. */ - template @@ -426,6 +481,7 @@ namespace boost { const Graph& g, PositionMap position, WeightMap weight, + const Topology& topology, detail::graph::edge_or_side edge_or_side_length, Done done, typename property_traits::value_type spring_constant, @@ -440,10 +496,10 @@ namespace boost { >::value)); detail::graph::kamada_kawai_spring_layout_impl< - Graph, PositionMap, WeightMap, + Topology, Graph, PositionMap, WeightMap, detail::graph::edge_or_side, Done, VertexIndexMap, DistanceMatrix, SpringStrengthMatrix, PartialDerivativeMap> - alg(g, position, weight, edge_or_side_length, done, spring_constant, + alg(topology, g, position, weight, edge_or_side_length, done, spring_constant, index, distance, spring_strength, partial_derivatives); return alg.run(); } @@ -451,7 +507,7 @@ namespace boost { /** * \overload */ - template bool @@ -459,6 +515,7 @@ namespace boost { const Graph& g, PositionMap position, WeightMap weight, + const Topology& topology, detail::graph::edge_or_side edge_or_side_length, Done done, typename property_traits::value_type spring_constant, @@ -471,32 +528,33 @@ namespace boost { std::vector distance(n, weight_vec(n)); std::vector spring_strength(n, weight_vec(n)); - std::vector > partial_derivatives(n); + std::vector partial_derivatives(n); return kamada_kawai_spring_layout( - g, position, weight, edge_or_side_length, done, spring_constant, index, + g, position, weight, topology, edge_or_side_length, done, spring_constant, index, distance.begin(), spring_strength.begin(), make_iterator_property_map(partial_derivatives.begin(), index, - std::pair())); + typename Topology::point_difference_type())); } /** * \overload */ - template bool kamada_kawai_spring_layout( const Graph& g, PositionMap position, WeightMap weight, + const Topology& topology, detail::graph::edge_or_side edge_or_side_length, Done done, typename property_traits::value_type spring_constant) { - return kamada_kawai_spring_layout(g, position, weight, edge_or_side_length, + return kamada_kawai_spring_layout(g, position, weight, topology, edge_or_side_length, done, spring_constant, get(vertex_index, g)); } @@ -504,35 +562,37 @@ namespace boost { /** * \overload */ - template bool kamada_kawai_spring_layout( const Graph& g, PositionMap position, WeightMap weight, + const Topology& topology, detail::graph::edge_or_side edge_or_side_length, Done done) { typedef typename property_traits::value_type weight_type; - return kamada_kawai_spring_layout(g, position, weight, edge_or_side_length, + return kamada_kawai_spring_layout(g, position, weight, topology, edge_or_side_length, done, weight_type(1)); } /** * \overload */ - template bool kamada_kawai_spring_layout( const Graph& g, PositionMap position, WeightMap weight, + const Topology& topology, detail::graph::edge_or_side edge_or_side_length) { typedef typename property_traits::value_type weight_type; - return kamada_kawai_spring_layout(g, position, weight, edge_or_side_length, + return kamada_kawai_spring_layout(g, position, weight, topology, edge_or_side_length, layout_tolerance(), weight_type(1.0), get(vertex_index, g)); diff --git a/include/boost/graph/random_layout.hpp b/include/boost/graph/random_layout.hpp index c5520bf3..4cd16f29 100644 --- a/include/boost/graph/random_layout.hpp +++ b/include/boost/graph/random_layout.hpp @@ -15,36 +15,19 @@ #include #include #include +#include namespace boost { -template +template void random_graph_layout (const Graph& g, PositionMap position_map, - typename property_traits::value_type const& origin, - typename property_traits::value_type const& extent, - RandomNumberGenerator& gen) + const Topology& topology) { - typedef typename property_traits::value_type Point; - typedef double Dimension; - - typedef typename mpl::if_, - uniform_int, - uniform_real >::type distrib_t; - typedef typename mpl::if_, - RandomNumberGenerator&, - uniform_01 > - ::type gen_t; - - gen_t my_gen(gen); - distrib_t x(origin.x, origin.x + extent.x); - distrib_t y(origin.y, origin.y + extent.y); - typename graph_traits::vertex_iterator vi, vi_end; - for(tie(vi, vi_end) = vertices(g); vi != vi_end; ++vi) { - position_map[*vi].x = x(my_gen); - position_map[*vi].y = y(my_gen); + BGL_FORALL_VERTICES_T(v, g, Graph) { + put(position_map, v, topology.random_point()); } } diff --git a/include/boost/graph/topology.hpp b/include/boost/graph/topology.hpp new file mode 100644 index 00000000..e2632292 --- /dev/null +++ b/include/boost/graph/topology.hpp @@ -0,0 +1,527 @@ +// Copyright 2009 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 +// Douglas Gregor +// Andrew Lumsdaine +#ifndef BOOST_GRAPH_TOPOLOGY_HPP +#define BOOST_GRAPH_TOPOLOGY_HPP + +#include +#include +#include +#include +#include +#include +#include // For BOOST_STATIC_CONSTANT +#include + +// Classes and concepts to represent points in a space, with distance and move +// operations (used for Gurson-Atun layout), plus other things like bounding +// boxes used for other layout algorithms. + +namespace boost { + +/*********************************************************** + * Topologies * + ***********************************************************/ +template +class convex_topology +{ + struct point + { + BOOST_STATIC_CONSTANT(std::size_t, dimensions = Dims); + point() { } + double& operator[](std::size_t i) {return values[i];} + const double& operator[](std::size_t i) const {return values[i];} + + private: + double values[Dims]; + }; + + struct point_difference + { + BOOST_STATIC_CONSTANT(std::size_t, dimensions = Dims); + point_difference() { + for (std::size_t i = 0; i < Dims; ++i) values[i] = 0.; + } + double& operator[](std::size_t i) {return values[i];} + const double& operator[](std::size_t i) const {return values[i];} + + friend point_difference operator+(const point_difference& a, const point_difference& b) { + point_difference result; + for (std::size_t i = 0; i < Dims; ++i) + result[i] = a[i] + b[i]; + return result; + } + + friend point_difference& operator+=(point_difference& a, const point_difference& b) { + for (std::size_t i = 0; i < Dims; ++i) + a[i] += b[i]; + return a; + } + + friend point_difference operator-(const point_difference& a) { + point_difference result; + for (std::size_t i = 0; i < Dims; ++i) + result[i] = -a[i]; + return result; + } + + friend point_difference operator-(const point_difference& a, const point_difference& b) { + point_difference result; + for (std::size_t i = 0; i < Dims; ++i) + result[i] = a[i] - b[i]; + return result; + } + + friend point_difference& operator-=(point_difference& a, const point_difference& b) { + for (std::size_t i = 0; i < Dims; ++i) + a[i] -= b[i]; + return a; + } + + friend point_difference operator*(const point_difference& a, const point_difference& b) { + point_difference result; + for (std::size_t i = 0; i < Dims; ++i) + result[i] = a[i] * b[i]; + return result; + } + + friend point_difference operator*(const point_difference& a, double b) { + point_difference result; + for (std::size_t i = 0; i < Dims; ++i) + result[i] = a[i] * b; + return result; + } + + friend point_difference operator*(double a, const point_difference& b) { + point_difference result; + for (std::size_t i = 0; i < Dims; ++i) + result[i] = a * b[i]; + return result; + } + + friend point_difference operator/(const point_difference& a, const point_difference& b) { + point_difference result; + for (std::size_t i = 0; i < Dims; ++i) + result[i] = (b[i] == 0.) ? 0. : a[i] / b[i]; + return result; + } + + private: + double values[Dims]; + }; + + public: + typedef point point_type; + typedef point_difference point_difference_type; + + double distance(point a, point b) const + { + double dist = 0.; + for (std::size_t i = 0; i < Dims; ++i) { + double diff = b[i] - a[i]; + dist = boost::math::hypot(dist, diff); + } + // Exact properties of the distance are not important, as long as + // < on what this returns matches real distances; l_2 is used because + // Fruchterman-Reingold also uses this code and it relies on l_2. + return dist; + } + + point move_position_toward(point a, double fraction, point b) const + { + point result; + for (std::size_t i = 0; i < Dims; ++i) + result[i] = a[i] + (b[i] - a[i]) * fraction; + return result; + } + + point_difference difference(point a, point b) const { + point_difference result; + for (std::size_t i = 0; i < Dims; ++i) + result[i] = a[i] - b[i]; + return result; + } + + point adjust(point a, point_difference delta) const { + point result; + for (std::size_t i = 0; i < Dims; ++i) + result[i] = a[i] + delta[i]; + return result; + } + + point pointwise_min(point a, point b) const { + BOOST_USING_STD_MIN(); + point result; + for (std::size_t i = 0; i < Dims; ++i) + result[i] = min BOOST_PREVENT_MACRO_SUBSTITUTION (a[i], b[i]); + return result; + } + + point pointwise_max(point a, point b) const { + BOOST_USING_STD_MAX(); + point result; + for (std::size_t i = 0; i < Dims; ++i) + result[i] = max BOOST_PREVENT_MACRO_SUBSTITUTION (a[i], b[i]); + return result; + } + + double norm(point_difference delta) const { + double n = 0.; + for (std::size_t i = 0; i < Dims; ++i) + n = boost::math::hypot(n, delta[i]); + return n; + } + + double volume(point_difference delta) const { + double n = 1.; + for (std::size_t i = 0; i < Dims; ++i) + n *= delta[i]; + return n; + } + +}; + +template +class hypercube_topology : public convex_topology +{ + typedef uniform_01 rand_t; + + public: + typedef typename convex_topology::point_type point_type; + typedef typename convex_topology::point_difference_type point_difference_type; + + explicit hypercube_topology(double scaling = 1.0) + : gen_ptr(new RandomNumberGenerator), rand(new rand_t(*gen_ptr)), + scaling(scaling) + { } + + hypercube_topology(RandomNumberGenerator& gen, double scaling = 1.0) + : gen_ptr(), rand(new rand_t(gen)), scaling(scaling) { } + + point_type random_point() const + { + point_type p; + for (std::size_t i = 0; i < Dims; ++i) + p[i] = (*rand)() * scaling; + return p; + } + + point_type bound(point_type a) const + { + BOOST_USING_STD_MIN(); + BOOST_USING_STD_MAX(); + point_type p; + for (std::size_t i = 0; i < Dims; ++i) + p[i] = min BOOST_PREVENT_MACRO_SUBSTITUTION (scaling, max BOOST_PREVENT_MACRO_SUBSTITUTION (-scaling, a[i])); + return p; + } + + double distance_from_boundary(point_type a) const + { + BOOST_USING_STD_MIN(); + BOOST_USING_STD_MAX(); +#ifndef BOOST_NO_STDC_NAMESPACE + using std::abs; +#endif + BOOST_STATIC_ASSERT (Dims >= 1); + double dist = abs(scaling - a[0]); + for (std::size_t i = 1; i < Dims; ++i) + dist = min BOOST_PREVENT_MACRO_SUBSTITUTION (dist, abs(scaling - a[i])); + return dist; + } + + private: + shared_ptr gen_ptr; + shared_ptr rand; + double scaling; +}; + +template +class square_topology : public hypercube_topology<2, RandomNumberGenerator> +{ + typedef hypercube_topology<2, RandomNumberGenerator> inherited; + + public: + explicit square_topology(double scaling = 1.0) : inherited(scaling) { } + + square_topology(RandomNumberGenerator& gen, double scaling = 1.0) + : inherited(gen, scaling) { } +}; + +template +class rectangle_topology : public convex_topology<2> +{ + typedef uniform_01 rand_t; + + public: + rectangle_topology(double left, double top, double right, double bottom) + : gen_ptr(new RandomNumberGenerator), rand(new rand_t(*gen_ptr)), + left(std::min BOOST_PREVENT_MACRO_SUBSTITUTION (left, right)), + top(std::min BOOST_PREVENT_MACRO_SUBSTITUTION (top, bottom)), + right(std::max BOOST_PREVENT_MACRO_SUBSTITUTION (left, right)), + bottom(std::max BOOST_PREVENT_MACRO_SUBSTITUTION (top, bottom)) { } + + rectangle_topology(RandomNumberGenerator& gen, double left, double top, double right, double bottom) + : gen_ptr(), rand(new rand_t(gen)), + left(std::min BOOST_PREVENT_MACRO_SUBSTITUTION (left, right)), + top(std::min BOOST_PREVENT_MACRO_SUBSTITUTION (top, bottom)), + right(std::max BOOST_PREVENT_MACRO_SUBSTITUTION (left, right)), + bottom(std::max BOOST_PREVENT_MACRO_SUBSTITUTION (top, bottom)) { } + + typedef typename convex_topology<2>::point_type point_type; + typedef typename convex_topology<2>::point_difference_type point_difference_type; + + point_type random_point() const + { + point_type p; + p[0] = (*rand)() * (right - left) + left; + p[1] = (*rand)() * (bottom - top) + top; + return p; + } + + point_type bound(point_type a) const + { + BOOST_USING_STD_MIN(); + BOOST_USING_STD_MAX(); + point_type p; + p[0] = min BOOST_PREVENT_MACRO_SUBSTITUTION (right, max BOOST_PREVENT_MACRO_SUBSTITUTION (left, a[0])); + p[1] = min BOOST_PREVENT_MACRO_SUBSTITUTION (bottom, max BOOST_PREVENT_MACRO_SUBSTITUTION (top, a[1])); + return p; + } + + double distance_from_boundary(point_type a) const + { + BOOST_USING_STD_MIN(); + BOOST_USING_STD_MAX(); +#ifndef BOOST_NO_STDC_NAMESPACE + using std::abs; +#endif + double dist = abs(left - a[0]); + dist = min BOOST_PREVENT_MACRO_SUBSTITUTION (dist, abs(right - a[0])); + dist = min BOOST_PREVENT_MACRO_SUBSTITUTION (dist, abs(top - a[1])); + dist = min BOOST_PREVENT_MACRO_SUBSTITUTION (dist, abs(bottom - a[1])); + return dist; + } + + private: + shared_ptr gen_ptr; + shared_ptr rand; + double left, top, right, bottom; +}; + +template +class cube_topology : public hypercube_topology<3, RandomNumberGenerator> +{ + typedef hypercube_topology<3, RandomNumberGenerator> inherited; + + public: + explicit cube_topology(double scaling = 1.0) : inherited(scaling) { } + + cube_topology(RandomNumberGenerator& gen, double scaling = 1.0) + : inherited(gen, scaling) { } +}; + +template +class ball_topology : public convex_topology +{ + typedef uniform_01 rand_t; + + public: + typedef typename convex_topology::point_type point_type; + + explicit ball_topology(double radius = 1.0) + : gen_ptr(new RandomNumberGenerator), rand(new rand_t(*gen_ptr)), + radius(radius) + { } + + ball_topology(RandomNumberGenerator& gen, double radius = 1.0) + : gen_ptr(), rand(new rand_t(gen)), radius(radius) { } + + point_type random_point() const + { + point_type p; + double dist_sum; + do { + dist_sum = 0.0; + for (std::size_t i = 0; i < Dims; ++i) { + double x = (*rand)() * 2*radius - radius; + p[i] = x; + dist_sum += x * x; + } + } while (dist_sum > radius*radius); + return p; + } + + point_type bound(point_type a) const + { + BOOST_USING_STD_MIN(); + BOOST_USING_STD_MAX(); + double r = 0.; + for (std::size_t i = 0; i < Dims; ++i) + r = boost::math::hypot(r, a[i]); + if (r <= radius) return a; + double scaling_factor = radius / r; + point_type p; + for (std::size_t i = 0; i < Dims; ++i) + p[i] = a[i] * scaling_factor; + return p; + } + + double distance_from_boundary(point_type a) const + { + double r = 0.; + for (std::size_t i = 0; i < Dims; ++i) + r = boost::math::hypot(r, a[i]); + return radius - r; + } + + private: + shared_ptr gen_ptr; + shared_ptr rand; + double radius; +}; + +template +class circle_topology : public ball_topology<2, RandomNumberGenerator> +{ + typedef ball_topology<2, RandomNumberGenerator> inherited; + + public: + explicit circle_topology(double radius = 1.0) : inherited(radius) { } + + circle_topology(RandomNumberGenerator& gen, double radius = 1.0) + : inherited(gen, radius) { } +}; + +template +class sphere_topology : public ball_topology<3, RandomNumberGenerator> +{ + typedef ball_topology<3, RandomNumberGenerator> inherited; + + public: + explicit sphere_topology(double radius = 1.0) : inherited(radius) { } + + sphere_topology(RandomNumberGenerator& gen, double radius = 1.0) + : inherited(gen, radius) { } +}; + +template +class heart_topology +{ + // Heart is defined as the union of three shapes: + // Square w/ corners (+-1000, -1000), (0, 0), (0, -2000) + // Circle centered at (-500, -500) radius 500*sqrt(2) + // Circle centered at (500, -500) radius 500*sqrt(2) + // Bounding box (-1000, -2000) - (1000, 500*(sqrt(2) - 1)) + + struct point + { + point() { values[0] = 0.0; values[1] = 0.0; } + point(double x, double y) { values[0] = x; values[1] = y; } + + double& operator[](std::size_t i) { return values[i]; } + double operator[](std::size_t i) const { return values[i]; } + + private: + double values[2]; + }; + + bool in_heart(point p) const + { +#ifndef BOOST_NO_STDC_NAMESPACE + using std::abs; + using boost::math::constants::root_two; +#endif + + if (p[1] < abs(p[0]) - 2000) return false; // Bottom + if (p[1] <= -1000) return true; // Diagonal of square + if (boost::math::hypot(p[0] - -500, p[1] - -500) <= 500. * root_two()) + return true; // Left circle + if (boost::math::hypot(p[0] - 500, p[1] - -500) <= 500. * root_two()) + return true; // Right circle + return false; + } + + bool segment_within_heart(point p1, point p2) const + { + // Assumes that p1 and p2 are within the heart + if ((p1[0] < 0) == (p2[0] < 0)) return true; // Same side of symmetry line + if (p1[0] == p2[0]) return true; // Vertical + double slope = (p2[1] - p1[1]) / (p2[0] - p1[0]); + double intercept = p1[1] - p1[0] * slope; + if (intercept > 0) return false; // Crosses between circles + return true; + } + + typedef uniform_01 rand_t; + + public: + typedef point point_type; + + heart_topology() + : gen_ptr(new RandomNumberGenerator), rand(new rand_t(*gen_ptr)) { } + + heart_topology(RandomNumberGenerator& gen) + : gen_ptr(), rand(new rand_t(gen)) { } + + point random_point() const + { + point result; + using boost::math::constants::root_two; + do { + result[0] = (*rand)() * (1000 + 1000 * root_two()) - (500 + 500 * root_two()); + result[1] = (*rand)() * (2000 + 500 * (root_two() - 1)) - 2000; + } while (!in_heart(result)); + return result; + } + + // Not going to provide clipping to bounding region or distance from boundary + + double distance(point a, point b) const + { + if (segment_within_heart(a, b)) { + // Straight line + return boost::math::hypot(b[0] - a[0], b[1] - a[1]); + } else { + // Straight line bending around (0, 0) + return boost::math::hypot(a[0], a[1]) + boost::math::hypot(b[0], b[1]); + } + } + + point move_position_toward(point a, double fraction, point b) const + { + if (segment_within_heart(a, b)) { + // Straight line + return point(a[0] + (b[0] - a[0]) * fraction, + a[1] + (b[1] - a[1]) * fraction); + } else { + double distance_to_point_a = boost::math::hypot(a[0], a[1]); + double distance_to_point_b = boost::math::hypot(b[0], b[1]); + double location_of_point = distance_to_point_a / + (distance_to_point_a + distance_to_point_b); + if (fraction < location_of_point) + return point(a[0] * (1 - fraction / location_of_point), + a[1] * (1 - fraction / location_of_point)); + else + return point( + b[0] * ((fraction - location_of_point) / (1 - location_of_point)), + b[1] * ((fraction - location_of_point) / (1 - location_of_point))); + } + } + + private: + shared_ptr gen_ptr; + shared_ptr rand; +}; + +} // namespace boost + +#endif // BOOST_GRAPH_TOPOLOGY_HPP diff --git a/test/layout_test.cpp b/test/layout_test.cpp index bf814125..1199d641 100644 --- a/test/layout_test.cpp +++ b/test/layout_test.cpp @@ -23,31 +23,26 @@ using namespace boost; enum vertex_position_t { vertex_position }; namespace boost { BOOST_INSTALL_PROPERTY(vertex, position); } -struct point -{ - double x, y; - point(double x, double y): x(x), y(y) {} - point() {} -}; +typedef square_topology<>::point_type point; -template -void print_graph_layout(const Graph& g, PositionMap position) +template +void print_graph_layout(const Graph& g, PositionMap position, const Topology& topology) { - typename graph_traits::vertex_iterator vi, vi_end; - int xmin = 0, xmax = 0, ymin = 0, ymax = 0; - for (tie(vi, vi_end) = vertices(g); vi != vi_end; ++vi) { - if ((int)position[*vi].x < xmin) xmin = (int)position[*vi].x; - if ((int)position[*vi].x > xmax) xmax = (int)position[*vi].x; - if ((int)position[*vi].y < ymin) ymin = (int)position[*vi].y; - if ((int)position[*vi].y > ymax) ymax = (int)position[*vi].y; + typedef typename Topology::point_type Point; + // Find min/max ranges + Point min_point = position[*vertices(g).first], max_point = min_point; + BGL_FORALL_VERTICES_T(v, g, Graph) { + min_point = topology.pointwise_min(min_point, position[v]); + max_point = topology.pointwise_max(max_point, position[v]); } - for (int y = ymin; y <= ymax; ++y) { - for (int x = xmin; x <= xmax; ++x) { + for (int y = min_point[1]; y <= max_point[1]; ++y) { + for (int x = min_point[0]; x <= max_point[0]; ++x) { + typename graph_traits::vertex_iterator vi, vi_end; // Find vertex at this position typename graph_traits::vertices_size_type index = 0; for (tie(vi, vi_end) = vertices(g); vi != vi_end; ++vi, ++index) { - if ((int)position[*vi].x == x && (int)position[*vi].y == y) + if ((int)position[*vi][0] == x && (int)position[*vi][1] == y) break; } @@ -67,7 +62,7 @@ void dump_graph_layout(std::string name, const Graph& g, PositionMap position) typename graph_traits::vertex_iterator vi, vi_end; for (tie(vi, vi_end) = vertices(g); vi != vi_end; ++vi) { out << " n" << get(vertex_index, g, *vi) << "[ pos=\"" - << (int)position[*vi].x + 25 << ", " << (int)position[*vi].y + 25 + << (int)position[*vi][0] + 25 << ", " << (int)position[*vi][1] + 25 << "\" ];\n"; } @@ -98,7 +93,8 @@ test_circle_layout(Graph*, typename graph_traits::vertices_size_type n) circle_graph_layout(g, get(vertex_position, g), 10.0); std::cout << "Regular polygon layout with " << n << " points.\n"; - print_graph_layout(g, get(vertex_position, g)); + square_topology<> topology; + print_graph_layout(g, get(vertex_position, g), topology); } struct simple_edge @@ -151,6 +147,7 @@ test_triangle(Graph*) bool ok = kamada_kawai_spring_layout(g, get(vertex_position, g), get(edge_weight, g), + square_topology<>(50.0), side_length(50.0)); BOOST_CHECK(ok); @@ -192,37 +189,43 @@ test_cube(Graph*) bool ok = kamada_kawai_spring_layout(g, get(vertex_position, g), get(edge_weight, g), + square_topology<>(50.0), side_length(50.0), kamada_kawai_done()); BOOST_CHECK(ok); std::cout << "Cube layout (Kamada-Kawai).\n"; - print_graph_layout(g, get(vertex_position, g)); + print_graph_layout(g, get(vertex_position, g), square_topology<>(50.)); dump_graph_layout("cube", g, get(vertex_position, g)); minstd_rand gen; - random_graph_layout(g, get(vertex_position, g), - point(-25.0, -25.0), - point(25.0, 25.0), - gen); + typedef square_topology<> Topology; + Topology topology(gen, 50.0); + std::vector displacements(num_vertices(g)); + Topology::point_type origin; + origin[0] = origin[1] = 50.0; + Topology::point_difference_type extent; + extent[0] = extent[1] = 50.0; + rectangle_topology<> rect_top(gen, 0, 0, 50, 50); + random_graph_layout(g, get(vertex_position, g), rect_top); - std::vector displacements(num_vertices(g)); fruchterman_reingold_force_directed_layout (g, get(vertex_position, g), - point(50.0, 50.0), - point(50.0, 50.0), + topology, + origin, + extent, square_distance_attractive_force(), square_distance_repulsive_force(), all_force_pairs(), linear_cooling(100), make_iterator_property_map(displacements.begin(), get(vertex_index, g), - point())); + Topology::point_difference_type())); std::cout << "Cube layout (Fruchterman-Reingold).\n"; - print_graph_layout(g, get(vertex_position, g)); + print_graph_layout(g, get(vertex_position, g), square_topology<>(50.)); dump_graph_layout("cube-fr", g, get(vertex_position, g)); } @@ -256,37 +259,46 @@ test_triangular(Graph*) } std::cerr << std::endl; + typedef square_topology<> Topology; + minstd_rand gen; + Topology topology(gen, 50.0); + Topology::point_type origin; + origin[0] = origin[1] = 50.0; + Topology::point_difference_type extent; + extent[0] = extent[1] = 50.0; + circle_graph_layout(g, get(vertex_position, g), 25.0); bool ok = kamada_kawai_spring_layout(g, get(vertex_position, g), get(edge_weight, g), + topology, side_length(50.0), kamada_kawai_done()); BOOST_CHECK(ok); std::cout << "Triangular layout (Kamada-Kawai).\n"; - print_graph_layout(g, get(vertex_position, g)); + print_graph_layout(g, get(vertex_position, g), square_topology<>(50.)); dump_graph_layout("triangular-kk", g, get(vertex_position, g)); - minstd_rand gen; - random_graph_layout(g, get(vertex_position, g), point(-25.0, -25.0), point(25.0, 25.0), - gen); + rectangle_topology<> rect_top(gen, -25, -25, 25, 25); + random_graph_layout(g, get(vertex_position, g), rect_top); dump_graph_layout("random", g, get(vertex_position, g)); - std::vector displacements(num_vertices(g)); + std::vector displacements(num_vertices(g)); fruchterman_reingold_force_directed_layout (g, get(vertex_position, g), - point(50.0, 50.0), - point(50.0, 50.0), + topology, + origin, + extent, attractive_force(square_distance_attractive_force()). cooling(linear_cooling(100))); std::cout << "Triangular layout (Fruchterman-Reingold).\n"; - print_graph_layout(g, get(vertex_position, g)); + print_graph_layout(g, get(vertex_position, g), square_topology<>(50.)); dump_graph_layout("triangular-fr", g, get(vertex_position, g)); } @@ -326,25 +338,33 @@ test_disconnected(Graph*) bool ok = kamada_kawai_spring_layout(g, get(vertex_position, g), get(edge_weight, g), + square_topology<>(50.0), side_length(50.0), kamada_kawai_done()); BOOST_CHECK(!ok); minstd_rand gen; - random_graph_layout(g, get(vertex_position, g), point(-25.0, -25.0), point(25.0, 25.0), - gen); + rectangle_topology<> rect_top(gen, -25, -25, 25, 25); + random_graph_layout(g, get(vertex_position, g), rect_top); - std::vector displacements(num_vertices(g)); + typedef square_topology<> Topology; + Topology topology(gen, 50.0); + std::vector displacements(num_vertices(g)); + Topology::point_type origin; + origin[0] = origin[1] = 50.0; + Topology::point_difference_type extent; + extent[0] = extent[1] = 50.0; fruchterman_reingold_force_directed_layout (g, get(vertex_position, g), - point(50.0, 50.0), - point(50.0, 50.0), + topology, + origin, + extent, attractive_force(square_distance_attractive_force()). cooling(linear_cooling(50))); std::cout << "Disconnected layout (Fruchterman-Reingold).\n"; - print_graph_layout(g, get(vertex_position, g)); + print_graph_layout(g, get(vertex_position, g), square_topology<>(50.)); dump_graph_layout("disconnected-fr", g, get(vertex_position, g)); } From c6035b97e67e46705b2ea7c1b692478cd73b546a Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Thu, 2 Apr 2009 18:17:38 +0000 Subject: [PATCH 104/224] Removed uses of drand48() in Fruchterman-Reingold layout [SVN r52138] --- include/boost/graph/fruchterman_reingold.hpp | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/include/boost/graph/fruchterman_reingold.hpp b/include/boost/graph/fruchterman_reingold.hpp index e90b30cd..dbab6bc8 100644 --- a/include/boost/graph/fruchterman_reingold.hpp +++ b/include/boost/graph/fruchterman_reingold.hpp @@ -21,8 +21,6 @@ #include // for std::sqrt and std::fabs #include -#include // for drand48 - namespace boost { bool vertex_migration = false; @@ -224,19 +222,9 @@ namespace detail { typename Topology::point_type& p1, const typename Topology::point_type& p2, typename Topology::point_type origin, typename Topology::point_difference_type extent) { -#ifndef BOOST_NO_STDC_NAMESPACE - using std::sqrt; - using std::fabs; -#endif // BOOST_NO_STDC_NAMESPACE double too_close = topology.norm(extent) / 10000.; if (topology.distance(p1, p2) < too_close) { - double dist_to_move = sqrt(topology.norm(extent)) / 200.; - for (std::size_t i = 0; i < Topology::point_type::dimensions; ++i) { - if (p1[i] - origin[i] < origin[i] + extent[i] - p1[i]) - p1[i] += dist_to_move * drand48(); - else - p1[i] -= dist_to_move * drand48(); - } + p1 = topology.move_position_toward(p1, 1./200, topology.random_point()); } } From bae3f3950a509d2879b6e324325fcf7c0b5386b7 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Thu, 2 Apr 2009 18:49:28 +0000 Subject: [PATCH 105/224] Removed tabs [SVN r52139] --- .../boost/graph/betweenness_centrality.hpp | 12 +- include/boost/graph/detail/d_ary_heap.hpp | 2 +- include/boost/graph/dimacs.hpp | 16 +-- include/boost/graph/graph_stats.hpp | 4 +- include/boost/graph/graph_utility.hpp | 2 +- include/boost/graph/mesh_graph_generator.hpp | 128 +++++++++--------- include/boost/graph/ssca_graph_generator.hpp | 116 ++++++++-------- include/boost/graph/vertex_and_edge_range.hpp | 40 +++--- 8 files changed, 160 insertions(+), 160 deletions(-) diff --git a/include/boost/graph/betweenness_centrality.hpp b/include/boost/graph/betweenness_centrality.hpp index 741436c6..132602e5 100644 --- a/include/boost/graph/betweenness_centrality.hpp +++ b/include/boost/graph/betweenness_centrality.hpp @@ -371,7 +371,7 @@ brandes_betweenness_centrality(const Graph& g, DependencyMap dependency, // delta PathCountMap path_count, // sigma VertexIndexMap vertex_index - BOOST_GRAPH_ENABLE_IF_MODELS_PARM(Graph,vertex_list_graph_tag)) + BOOST_GRAPH_ENABLE_IF_MODELS_PARM(Graph,vertex_list_graph_tag)) { detail::graph::brandes_unweighted_shortest_paths shortest_paths; @@ -397,7 +397,7 @@ brandes_betweenness_centrality(const Graph& g, PathCountMap path_count, // sigma VertexIndexMap vertex_index, WeightMap weight_map - BOOST_GRAPH_ENABLE_IF_MODELS_PARM(Graph,vertex_list_graph_tag)) + BOOST_GRAPH_ENABLE_IF_MODELS_PARM(Graph,vertex_list_graph_tag)) { detail::graph::brandes_dijkstra_shortest_paths shortest_paths(weight_map); @@ -518,7 +518,7 @@ template void brandes_betweenness_centrality(const Graph& g, const bgl_named_params& params - BOOST_GRAPH_ENABLE_IF_MODELS_PARM(Graph,vertex_list_graph_tag)) + BOOST_GRAPH_ENABLE_IF_MODELS_PARM(Graph,vertex_list_graph_tag)) { typedef bgl_named_params named_params; @@ -536,7 +536,7 @@ brandes_betweenness_centrality(const Graph& g, template void brandes_betweenness_centrality(const Graph& g, CentralityMap centrality - BOOST_GRAPH_ENABLE_IF_MODELS_PARM(Graph,vertex_list_graph_tag)) + BOOST_GRAPH_ENABLE_IF_MODELS_PARM(Graph,vertex_list_graph_tag)) { detail::graph::brandes_betweenness_centrality_dispatch2( g, centrality, dummy_property_map(), get(vertex_index, g)); @@ -546,7 +546,7 @@ template void brandes_betweenness_centrality(const Graph& g, CentralityMap centrality, EdgeCentralityMap edge_centrality_map - BOOST_GRAPH_ENABLE_IF_MODELS_PARM(Graph,vertex_list_graph_tag)) + BOOST_GRAPH_ENABLE_IF_MODELS_PARM(Graph,vertex_list_graph_tag)) { detail::graph::brandes_betweenness_centrality_dispatch2( g, centrality, edge_centrality_map, get(vertex_index, g)); @@ -577,7 +577,7 @@ relative_betweenness_centrality(const Graph& g, CentralityMap centrality) template typename property_traits::value_type central_point_dominance(const Graph& g, CentralityMap centrality - BOOST_GRAPH_ENABLE_IF_MODELS_PARM(Graph,vertex_list_graph_tag)) + BOOST_GRAPH_ENABLE_IF_MODELS_PARM(Graph,vertex_list_graph_tag)) { using std::max; diff --git a/include/boost/graph/detail/d_ary_heap.hpp b/include/boost/graph/detail/d_ary_heap.hpp index 94ad2a60..548b06dd 100644 --- a/include/boost/graph/detail/d_ary_heap.hpp +++ b/include/boost/graph/detail/d_ary_heap.hpp @@ -81,7 +81,7 @@ namespace boost { // the operations used probably require that it is std::vector). // template , diff --git a/include/boost/graph/dimacs.hpp b/include/boost/graph/dimacs.hpp index 4dadb7a1..195ad3b6 100644 --- a/include/boost/graph/dimacs.hpp +++ b/include/boost/graph/dimacs.hpp @@ -29,7 +29,7 @@ public: typedef double vertex_weight_type; typedef double edge_weight_type; typedef std::pair edge_type; + vertices_size_type> edge_type; enum incr_mode {edge, edge_weight}; dimacs_basic_reader( std::istream& in, bool want_weights = true ) : @@ -51,7 +51,7 @@ public: //for a past the end iterator dimacs_basic_reader() : inpt( std::cin ), num_vertices( 0 ), - num_edges( 0 ), seen_edges( 0 ), want_weights(false) {} + num_edges( 0 ), seen_edges( 0 ), want_weights(false) {} edge_type edge_deref() { assert( !read_edges.empty() ); @@ -79,7 +79,7 @@ public: } if( (mode == edge && read_edges.empty()) || - (mode == edge_weight && read_edge_weights.empty() )) { + (mode == edge_weight && read_edge_weights.empty() )) { if( seen_edges > num_edges ) { boost::throw_exception(dimacs_exception()); @@ -94,7 +94,7 @@ public: seen_edges++; source--; dest--; - + read_edges.push( edge_type( source, dest ) ); if (want_weights) { read_edge_weights.push( weight ); @@ -202,10 +202,10 @@ public: typedef dimacs_basic_reader::incr_mode incr_mode; typedef std::input_iterator_tag iterator_category; - typedef edge_type value_type; - typedef value_type reference; - typedef edge_type* pointer; - typedef std::ptrdiff_t difference_type; + typedef edge_type value_type; + typedef value_type reference; + typedef edge_type* pointer; + typedef std::ptrdiff_t difference_type; dimacs_edge_iterator( T& reader ) : reader( reader ) {} diff --git a/include/boost/graph/graph_stats.hpp b/include/boost/graph/graph_stats.hpp index 080a57fd..47c05025 100644 --- a/include/boost/graph/graph_stats.hpp +++ b/include/boost/graph/graph_stats.hpp @@ -78,7 +78,7 @@ std::map dup_edge_dist( Graph& g ) { std::list front_neighbors; a_iterator_type a_iter, a_end; for( tie( a_iter, a_end ) = adjacent_vertices( v, g ); - a_iter != a_end; ++a_iter ) { + a_iter != a_end; ++a_iter ) { front_neighbors.push_back( *a_iter ); } @@ -116,7 +116,7 @@ std::map weight_degree_dist( Graph& g ) { BGL_FORALL_VERTICES_T( v, g, Graph ) { edge_weight_type tmp = 0; BGL_FORALL_OUTEDGES_T( v, e, g, Graph ) { - tmp += em[e]; + tmp += em[e]; } n[out_degree( v, g )] += 1.; dist[out_degree( v, g )] += tmp; diff --git a/include/boost/graph/graph_utility.hpp b/include/boost/graph/graph_utility.hpp index 0bbe5947..f7c53ed0 100644 --- a/include/boost/graph/graph_utility.hpp +++ b/include/boost/graph/graph_utility.hpp @@ -431,7 +431,7 @@ namespace boost { template void operator() (Edge stay, Edge away) { - put(ep, stay, get(ep, stay) + get(ep, away)); + put(ep, stay, get(ep, stay) + get(ep, away)); } EdgeProperty ep; }; diff --git a/include/boost/graph/mesh_graph_generator.hpp b/include/boost/graph/mesh_graph_generator.hpp index 0511cd9c..5bf1d47f 100644 --- a/include/boost/graph/mesh_graph_generator.hpp +++ b/include/boost/graph/mesh_graph_generator.hpp @@ -44,9 +44,9 @@ namespace boost { // Vertices are numbered in row-major order // Assumes directed mesh_iterator(vertices_size_type x, vertices_size_type y, - bool toroidal = true) + bool toroidal = true) : x(x), y(y), n(x*y), source(0), target(1), current(0,1), - toroidal(toroidal), done(false) + toroidal(toroidal), done(false) { assert(x > 1 && y > 1); } reference operator*() const { return current; } @@ -55,69 +55,69 @@ namespace boost { mesh_iterator& operator++() { if (is_undirected) { - if (!toroidal) { - if (target == source + 1) - if (source < x * (y - 1)) - target = source + x; - else { - source++; - target = (source % x) < x - 1 ? source + 1 : source + x; - if (target > n) - done = true; - } - else if (target == source + x) { - source++; - target = (source % x) < x - 1 ? source + 1 : source + x; - } - } else { - if (target == source + 1 || target == source - (source % x)) - target = (source + x) % n; - else if (target == (source + x) % n) { - if (source == n - 1) - done = true; - else { - source++; - target = (source % x) < (x - 1) ? source + 1 : source - (source % x); - } - } - } + if (!toroidal) { + if (target == source + 1) + if (source < x * (y - 1)) + target = source + x; + else { + source++; + target = (source % x) < x - 1 ? source + 1 : source + x; + if (target > n) + done = true; + } + else if (target == source + x) { + source++; + target = (source % x) < x - 1 ? source + 1 : source + x; + } + } else { + if (target == source + 1 || target == source - (source % x)) + target = (source + x) % n; + else if (target == (source + x) % n) { + if (source == n - 1) + done = true; + else { + source++; + target = (source % x) < (x - 1) ? source + 1 : source - (source % x); + } + } + } } else { // Directed - if ( !toroidal ) { - if (target == source - x) - target = source % x > 0 ? source - 1 : source + 1; - else if (target == source - 1) - if ((source % x) < (x - 1)) - target = source + 1; - else if (source < x * (y - 1)) - target = source + x; - else { - done = true; - } - else if (target == source + 1) - if (source < x * (y - 1)) - target = source + x; - else { - source++; - target = source - x; - } - else if (target == source + x) { - source++; - target = (source >= x) ? source - x : source - 1; - } - } else { - if (source == n - 1 && target == (source + x) % n) - done = true; - else if (target == source - 1 || target == source + x - 1) - target = (source + x) % n; - else if (target == source + 1 || target == source - (source % x)) - target = (source - x + n) % n; - else if (target == (source - x + n) % n) - target = (source % x > 0) ? source - 1 : source + x - 1; - else if (target == (source + x) % n) { - source++; - target = (source % x) < (x - 1) ? source + 1 : source - (source % x); - } - } + if ( !toroidal ) { + if (target == source - x) + target = source % x > 0 ? source - 1 : source + 1; + else if (target == source - 1) + if ((source % x) < (x - 1)) + target = source + 1; + else if (source < x * (y - 1)) + target = source + x; + else { + done = true; + } + else if (target == source + 1) + if (source < x * (y - 1)) + target = source + x; + else { + source++; + target = source - x; + } + else if (target == source + x) { + source++; + target = (source >= x) ? source - x : source - 1; + } + } else { + if (source == n - 1 && target == (source + x) % n) + done = true; + else if (target == source - 1 || target == source + x - 1) + target = (source + x) % n; + else if (target == source + 1 || target == source - (source % x)) + target = (source - x + n) % n; + else if (target == (source - x + n) % n) + target = (source % x > 0) ? source - 1 : source + x - 1; + else if (target == (source + x) % n) { + source++; + target = (source % x) < (x - 1) ? source + 1 : source - (source % x); + } + } } current.first = source; diff --git a/include/boost/graph/ssca_graph_generator.hpp b/include/boost/graph/ssca_graph_generator.hpp index e52cbce9..a9a6a5fe 100644 --- a/include/boost/graph/ssca_graph_generator.hpp +++ b/include/boost/graph/ssca_graph_generator.hpp @@ -42,12 +42,12 @@ namespace boost { // Initialize for edge generation ssca_iterator(RandomGenerator& gen, vertices_size_type totVertices, - vertices_size_type maxCliqueSize, double probUnidirectional, - int maxParallelEdges, double probIntercliqueEdges) + vertices_size_type maxCliqueSize, double probUnidirectional, + int maxParallelEdges, double probIntercliqueEdges) : gen(&gen), totVertices(totVertices), maxCliqueSize(maxCliqueSize), - probUnidirectional(probUnidirectional), maxParallelEdges(maxParallelEdges), - probIntercliqueEdges(probIntercliqueEdges), currentClique(0), - verticesRemaining(totVertices) + probUnidirectional(probUnidirectional), maxParallelEdges(maxParallelEdges), + probIntercliqueEdges(probIntercliqueEdges), currentClique(0), + verticesRemaining(totVertices) { cliqueNum = std::vector(totVertices, -1); current = std::make_pair(0,0); @@ -59,68 +59,68 @@ namespace boost { ssca_iterator& operator++() { while (values.empty() && verticesRemaining > 0) { // If there are no values left, generate a new clique - uniform_int clique_size(1, maxCliqueSize); - uniform_int rand_vertex(0, totVertices-1); - uniform_int num_parallel_edges(1, maxParallelEdges); - uniform_int direction(0,1); - uniform_01 prob(*gen); - std::vector cliqueVertices; + uniform_int clique_size(1, maxCliqueSize); + uniform_int rand_vertex(0, totVertices-1); + uniform_int num_parallel_edges(1, maxParallelEdges); + uniform_int direction(0,1); + uniform_01 prob(*gen); + std::vector cliqueVertices; - cliqueVertices.clear(); - vertices_size_type size = std::min(clique_size(*gen), verticesRemaining); - while (cliqueVertices.size() < size) { - vertices_size_type v = rand_vertex(*gen); - if (cliqueNum[v] == -1) { - cliqueNum[v] = currentClique; - cliqueVertices.push_back(v); - verticesRemaining--; - } - } // Nick: This is inefficient when only a few vertices remain... - // I should probably just select the remaining vertices - // in order when only a certain fraction remain. + cliqueVertices.clear(); + vertices_size_type size = std::min(clique_size(*gen), verticesRemaining); + while (cliqueVertices.size() < size) { + vertices_size_type v = rand_vertex(*gen); + if (cliqueNum[v] == -1) { + cliqueNum[v] = currentClique; + cliqueVertices.push_back(v); + verticesRemaining--; + } + } // Nick: This is inefficient when only a few vertices remain... + // I should probably just select the remaining vertices + // in order when only a certain fraction remain. - typename std::vector::iterator first, second; - for (first = cliqueVertices.begin(); first != cliqueVertices.end(); ++first) - for (second = first+1; second != cliqueVertices.end(); ++second) { - Direction d; - int edges; + typename std::vector::iterator first, second; + for (first = cliqueVertices.begin(); first != cliqueVertices.end(); ++first) + for (second = first+1; second != cliqueVertices.end(); ++second) { + Direction d; + int edges; - d = prob() < probUnidirectional ? (direction(*gen) == 0 ? FORWARD : BACKWARD) : BOTH; + d = prob() < probUnidirectional ? (direction(*gen) == 0 ? FORWARD : BACKWARD) : BOTH; - if (d & FORWARD) { - edges = num_parallel_edges(*gen); - for (int i = 0; i < edges; ++i) - values.push(std::make_pair(*first, *second)); - } - - if (d & BACKWARD) { - edges = num_parallel_edges(*gen); - for (int i = 0; i < edges; ++i) - values.push(std::make_pair(*second, *first)); - } - } + if (d & FORWARD) { + edges = num_parallel_edges(*gen); + for (int i = 0; i < edges; ++i) + values.push(std::make_pair(*first, *second)); + } + + if (d & BACKWARD) { + edges = num_parallel_edges(*gen); + for (int i = 0; i < edges; ++i) + values.push(std::make_pair(*second, *first)); + } + } - if (verticesRemaining == 0) { - // Generate interclique edges - for (vertices_size_type i = 0; i < totVertices; ++i) { - double p = probIntercliqueEdges; - for (vertices_size_type d = 2; d < totVertices/2; d *= 2, p/= 2) { - vertices_size_type j = (i+d) % totVertices; - if (cliqueNum[j] != cliqueNum[i] && prob() < p) { - int edges = num_parallel_edges(*gen); - for (int i = 0; i < edges; ++i) - values.push(std::make_pair(i, j)); - } - } - } - } + if (verticesRemaining == 0) { + // Generate interclique edges + for (vertices_size_type i = 0; i < totVertices; ++i) { + double p = probIntercliqueEdges; + for (vertices_size_type d = 2; d < totVertices/2; d *= 2, p/= 2) { + vertices_size_type j = (i+d) % totVertices; + if (cliqueNum[j] != cliqueNum[i] && prob() < p) { + int edges = num_parallel_edges(*gen); + for (int i = 0; i < edges; ++i) + values.push(std::make_pair(i, j)); + } + } + } + } - currentClique++; + currentClique++; } if (!values.empty()) { // If we're not done return a value - current = values.front(); - values.pop(); + current = values.front(); + values.pop(); } return *this; diff --git a/include/boost/graph/vertex_and_edge_range.hpp b/include/boost/graph/vertex_and_edge_range.hpp index acddbb42..bcba2bfb 100644 --- a/include/boost/graph/vertex_and_edge_range.hpp +++ b/include/boost/graph/vertex_and_edge_range.hpp @@ -49,22 +49,22 @@ namespace graph { { return traits_type::null_vertex(); } vertex_and_edge_range(const Graph& g, - VertexIterator first_v, VertexIterator last_v, - vertices_size_type n, - EdgeIterator first_e, EdgeIterator last_e, - edges_size_type m) + VertexIterator first_v, VertexIterator last_v, + vertices_size_type n, + EdgeIterator first_e, EdgeIterator last_e, + edges_size_type m) : g(&g), - first_vertex(first_v), last_vertex(last_v), m_num_vertices(n), - first_edge(first_e), last_edge(last_e), m_num_edges(m) + first_vertex(first_v), last_vertex(last_v), m_num_vertices(n), + first_edge(first_e), last_edge(last_e), m_num_edges(m) { } vertex_and_edge_range(const Graph& g, - VertexIterator first_v, VertexIterator last_v, - EdgeIterator first_e, EdgeIterator last_e) + VertexIterator first_v, VertexIterator last_v, + EdgeIterator first_e, EdgeIterator last_e) : g(&g), - first_vertex(first_v), last_vertex(last_v), - first_edge(first_e), last_edge(last_e) + first_vertex(first_v), last_vertex(last_v), + first_edge(first_e), last_edge(last_e) { m_num_vertices = std::distance(first_v, last_v); m_num_edges = std::distance(first_e, last_e); @@ -88,7 +88,7 @@ namespace graph { inline typename vertex_and_edge_range ::vertices_size_type num_vertices(const vertex_and_edge_range& g) + EdgeIterator>& g) { return g.m_num_vertices; } template @@ -100,32 +100,32 @@ namespace graph { inline typename vertex_and_edge_range ::edges_size_type num_edges(const vertex_and_edge_range& g) + EdgeIterator>& g) { return g.m_num_edges; } template inline typename vertex_and_edge_range ::vertex_descriptor source(typename vertex_and_edge_range - ::edge_descriptor e, - const vertex_and_edge_range& g) + ::edge_descriptor e, + const vertex_and_edge_range& g) { return source(e, *g.g); } template inline typename vertex_and_edge_range ::vertex_descriptor target(typename vertex_and_edge_range - ::edge_descriptor e, - const vertex_and_edge_range& g) + ::edge_descriptor e, + const vertex_and_edge_range& g) { return target(e, *g.g); } template inline vertex_and_edge_range make_vertex_and_edge_range(const Graph& g, - VertexIterator first_v, VertexIterator last_v, - EdgeIterator first_e, EdgeIterator last_e) + VertexIterator first_v, VertexIterator last_v, + EdgeIterator first_e, EdgeIterator last_e) { typedef vertex_and_edge_range result_type; From 3e3b80e5c18b48ff2163e7616f77a79a444bdee0 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Thu, 2 Apr 2009 19:22:38 +0000 Subject: [PATCH 106/224] Fixed min/max inspection reports [SVN r52140] --- .../boost/graph/bron_kerbosch_all_cliques.hpp | 4 ++- include/boost/graph/detail/geodesic.hpp | 3 ++- include/boost/graph/eccentricity.hpp | 11 +++++--- include/boost/graph/howard_cycle_ratio.hpp | 3 ++- include/boost/graph/numeric_values.hpp | 2 +- include/boost/graph/ssca_graph_generator.hpp | 4 ++- include/boost/graph/tiernan_all_cycles.hpp | 27 ++++++++++--------- 7 files changed, 33 insertions(+), 21 deletions(-) diff --git a/include/boost/graph/bron_kerbosch_all_cliques.hpp b/include/boost/graph/bron_kerbosch_all_cliques.hpp index 48579068..bf7e3ff4 100644 --- a/include/boost/graph/bron_kerbosch_all_cliques.hpp +++ b/include/boost/graph/bron_kerbosch_all_cliques.hpp @@ -9,6 +9,7 @@ #include #include +#include #include @@ -106,7 +107,8 @@ struct max_clique_visitor template inline void clique(const Clique& p, const Graph& g) { - maximum = std::max(maximum, p.size()); + BOOST_USING_STD_MAX(); + maximum = max BOOST_PREVENT_MACRO_SUBSTITUTION (maximum, p.size()); } std::size_t& maximum; }; diff --git a/include/boost/graph/detail/geodesic.hpp b/include/boost/graph/detail/geodesic.hpp index f61e8af7..99edaf9e 100644 --- a/include/boost/graph/detail/geodesic.hpp +++ b/include/boost/graph/detail/geodesic.hpp @@ -8,6 +8,7 @@ #define BOOST_GRAPH_DETAIL_GEODESIC_HPP #include +#include #include #include @@ -83,7 +84,7 @@ namespace detail { struct maximize : public std::binary_function { T operator ()(T x, T y) const - { return std::max(x, y); } + { BOOST_USING_STD_MAX(); return max BOOST_PREVENT_MACRO_SUBSTITUTION (x, y); } }; // Another helper, like maximize() to help abstract functional diff --git a/include/boost/graph/eccentricity.hpp b/include/boost/graph/eccentricity.hpp index 49e75d2e..340c6282 100644 --- a/include/boost/graph/eccentricity.hpp +++ b/include/boost/graph/eccentricity.hpp @@ -8,6 +8,7 @@ #define BOOST_GRAPH_ECCENTRICITY_HPP #include +#include #include namespace boost @@ -50,6 +51,8 @@ all_eccentricities(const Graph& g, const DistanceMatrix& dist, EccentricityMap e typedef typename property_traits::value_type DistanceMap; function_requires< WritablePropertyMapConcept >(); typedef typename property_traits::value_type Eccentricity; + BOOST_USING_STD_MIN(); + BOOST_USING_STD_MAX(); Eccentricity r = numeric_values::infinity(), @@ -62,8 +65,8 @@ all_eccentricities(const Graph& g, const DistanceMatrix& dist, EccentricityMap e put(ecc, *i, e); // track the radius and diameter at the same time - r = std::min(r, e); - d = std::max(d, e); + r = min BOOST_PREVENT_MACRO_SUBSTITUTION (r, e); + d = max BOOST_PREVENT_MACRO_SUBSTITUTION (d, e); } return make_pair(r, d); } @@ -85,8 +88,8 @@ radius_and_diameter(const Graph& g, EccentricityMap ecc) Eccentricity diameter = get(ecc, *i); for(i = next(i); i != end; ++i) { Eccentricity cur = get(ecc, *i); - radius = std::min(radius, cur); - diameter = std::max(diameter, cur); + radius = min BOOST_PREVENT_MACRO_SUBSTITUTION (radius, cur); + diameter = max BOOST_PREVENT_MACRO_SUBSTITUTION (diameter, cur); } return std::make_pair(radius, diameter); } diff --git a/include/boost/graph/howard_cycle_ratio.hpp b/include/boost/graph/howard_cycle_ratio.hpp index 2f5de88c..b3dcd125 100644 --- a/include/boost/graph/howard_cycle_ratio.hpp +++ b/include/boost/graph/howard_cycle_ratio.hpp @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include @@ -52,7 +53,7 @@ namespace boost { * \param ewm2 - edge weight2 read property map: E -> R+ * * \return maximum_{for all cycles C}CR(C), or - * -(std::numeric_limits)::max() if g is not "good". + * -(std::numeric_limits::max)() if g is not "good". */ template diff --git a/include/boost/graph/numeric_values.hpp b/include/boost/graph/numeric_values.hpp index 002620b9..ad018372 100644 --- a/include/boost/graph/numeric_values.hpp +++ b/include/boost/graph/numeric_values.hpp @@ -37,7 +37,7 @@ namespace boost { return T(); } static T infinity() - { return std::numeric_limits::max(); } + { return (std::numeric_limits::max)(); } }; // Specializations for floating point types refer to 0.0 and their infinity diff --git a/include/boost/graph/ssca_graph_generator.hpp b/include/boost/graph/ssca_graph_generator.hpp index a9a6a5fe..a8c67f24 100644 --- a/include/boost/graph/ssca_graph_generator.hpp +++ b/include/boost/graph/ssca_graph_generator.hpp @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -58,6 +59,7 @@ namespace boost { ssca_iterator& operator++() { + BOOST_USING_STD_MIN(); while (values.empty() && verticesRemaining > 0) { // If there are no values left, generate a new clique uniform_int clique_size(1, maxCliqueSize); uniform_int rand_vertex(0, totVertices-1); @@ -67,7 +69,7 @@ namespace boost { std::vector cliqueVertices; cliqueVertices.clear(); - vertices_size_type size = std::min(clique_size(*gen), verticesRemaining); + vertices_size_type size = min BOOST_PREVENT_MACRO_SUBSTITUTION (clique_size(*gen), verticesRemaining); while (cliqueVertices.size() < size) { vertices_size_type v = rand_vertex(*gen); if (cliqueNum[v] == -1) { diff --git a/include/boost/graph/tiernan_all_cycles.hpp b/include/boost/graph/tiernan_all_cycles.hpp index 6c1339c5..f750eb17 100644 --- a/include/boost/graph/tiernan_all_cycles.hpp +++ b/include/boost/graph/tiernan_all_cycles.hpp @@ -9,6 +9,7 @@ #include +#include #include #include #include @@ -99,24 +100,26 @@ struct cycle_visitor */ struct min_max_cycle_visitor { - min_max_cycle_visitor(std::size_t& min, std::size_t& max) - : minimum(min), maximum(max) + min_max_cycle_visitor(std::size_t& min_, std::size_t& max_) + : minimum(min_), maximum(max_) { } template inline void cycle(const Path& p, const Graph& g) { + BOOST_USING_STD_MIN(); + BOOST_USING_STD_MAX(); std::size_t len = p.size(); - minimum = std::min(minimum, len); - maximum = std::max(maximum, len); + minimum = min BOOST_PREVENT_MACRO_SUBSTITUTION (minimum, len); + maximum = max BOOST_PREVENT_MACRO_SUBSTITUTION (maximum, len); } std::size_t& minimum; std::size_t& maximum; }; inline min_max_cycle_visitor -find_min_max_cycle(std::size_t& min, std::size_t& max) -{ return min_max_cycle_visitor(min, max); } +find_min_max_cycle(std::size_t& min_, std::size_t& max_) +{ return min_max_cycle_visitor(min_, max_); } namespace detail { @@ -340,7 +343,7 @@ tiernan_all_cycles(const Graph& g, Visitor vis) { typedef typename graph_traits::directed_category Dir; tiernan_all_cycles(g, vis, detail::min_cycles::value, - std::numeric_limits::max()); + (std::numeric_limits::max)()); } template @@ -348,14 +351,14 @@ inline std::pair tiernan_girth_and_circumference(const Graph& g) { std::size_t - min = std::numeric_limits::max(), - max = 0; - tiernan_all_cycles(g, find_min_max_cycle(min, max)); + min_ = (std::numeric_limits::max)(), + max_ = 0; + tiernan_all_cycles(g, find_min_max_cycle(min_, max_)); // if this is the case, the graph is acyclic... - if(max == 0) max = min; + if(max_ == 0) max_ = min_; - return std::make_pair(min, max); + return std::make_pair(min_, max_); } template From 8803f55af90995cb10e12f39e1a2ecb89560ed5c Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Fri, 3 Apr 2009 00:23:42 +0000 Subject: [PATCH 107/224] Merged in more changes from Parallel BGL [SVN r52149] --- include/boost/graph/rmat_graph_generator.hpp | 579 +++++++++++++++++++ include/boost/graph/ssca_graph_generator.hpp | 3 + 2 files changed, 582 insertions(+) create mode 100644 include/boost/graph/rmat_graph_generator.hpp diff --git a/include/boost/graph/rmat_graph_generator.hpp b/include/boost/graph/rmat_graph_generator.hpp new file mode 100644 index 00000000..22c44b8a --- /dev/null +++ b/include/boost/graph/rmat_graph_generator.hpp @@ -0,0 +1,579 @@ +// Copyright 2004, 2005 The Trustees of Indiana University. + +// 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) + +// Authors: Nick Edmonds +// Andrew Lumsdaine +#ifndef BOOST_GRAPH_RMAT_GENERATOR_HPP +#define BOOST_GRAPH_RMAT_GENERATOR_HPP + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using boost::shared_ptr; +using boost::uniform_01; + +struct keep_all_edges { + template + bool operator()(const T&, const T&) { return true; } +}; + +template +struct keep_local_edges { + + keep_local_edges(const Distribution& distrib, const ProcessId& id) + : distrib(distrib), id(id) + { } + + template + bool operator()(const T& x, const T& y) + { return distrib(x) == id || distrib(y) == id; } + +private: + const Distribution& distrib; + const ProcessId& id; +}; + +template +void +generate_permutation_vector(RandomGenerator& gen, std::vector& vertexPermutation, T n) +{ + using boost::uniform_int; + + vertexPermutation.resize(n); + + // Generate permutation map of vertex numbers + uniform_int rand_vertex(0, n-1); + for (T i = 0; i < n; ++i) + vertexPermutation[i] = i; + + // Can't use std::random_shuffle unless we create another (synchronized) PRNG + for (T i = 0; i < n; ++i) + std::swap(vertexPermutation[i], vertexPermutation[rand_vertex(gen)]); +} + +template +std::pair +generate_edge(shared_ptr > prob, T n, + unsigned int SCALE, double a, double b, double c, double d) +{ + T u = 0, v = 0; + T step = n/2; + for (unsigned int j = 0; j < SCALE; ++j) { + double p = (*prob)(); + + if (p < a) + ; + else if (p >= a && p < a + b) + v += step; + else if (p >= a + b && p < a + b + c) + u += step; + else { // p > a + b + c && p < a + b + c + d + u += step; + v += step; + } + + step /= 2; + + // 0.2 and 0.9 are hardcoded in the reference SSCA implementation. + // The maximum change in any given value should be less than 10% + a *= 0.9 + 0.2 * (*prob)(); + b *= 0.9 + 0.2 * (*prob)(); + c *= 0.9 + 0.2 * (*prob)(); + d *= 0.9 + 0.2 * (*prob)(); + + double S = a + b + c + d; + + a /= S; b /= S; c /= S; d /= S; + } + + return std::make_pair(u, v); +} + +namespace boost { + + /* + Chakrabarti's R-MAT scale free generator. + + For all flavors of the R-MAT iterator a+b+c+d must equal 1 and for the + unique_rmat_iterator 'm' << 'n^2'. If 'm' is too close to 'n^2' the + generator may be unable to generate sufficient unique edges + + To get a true scale free distribution {a, b, c, d : a > b, a > c, a > d} + */ + + template + class rmat_iterator + { + typedef typename graph_traits::directed_category directed_category; + typedef typename graph_traits::vertices_size_type vertices_size_type; + typedef typename graph_traits::edges_size_type edges_size_type; + + public: + typedef std::input_iterator_tag iterator_category; + typedef std::pair value_type; + typedef const value_type& reference; + typedef const value_type* pointer; + typedef void difference_type; + + // No argument constructor, set to terminating condition + rmat_iterator() + : gen(), edge(0) { } + + // Initialize for edge generation + rmat_iterator(RandomGenerator& gen, vertices_size_type n, + edges_size_type m, double a, double b, double c, + double d, bool permute_vertices = true) + : gen(), n(n), a(a), b(b), c(c), d(d), edge(m), + permute_vertices(permute_vertices), + SCALE(int(floor(log2(n)))) + + { + this->gen.reset(new uniform_01(gen)); + + assert(a + b + c + d == 1); + + if (permute_vertices) + generate_permutation_vector(gen, vertexPermutation, n); + + // TODO: Generate the entire adjacency matrix then "Clip and flip" if undirected graph + + // Generate the first edge + vertices_size_type u, v; + tie(u, v) = generate_edge(this->gen, n, SCALE, a, b, c, d); + + if (permute_vertices) + current = std::make_pair(vertexPermutation[u], + vertexPermutation[v]); + else + current = std::make_pair(u, v); + + edge; + } + + reference operator*() const { return current; } + pointer operator->() const { return ¤t; } + + rmat_iterator& operator++() + { + vertices_size_type u, v; + tie(u, v) = generate_edge(this->gen, n, SCALE, a, b, c, d); + + if (permute_vertices) + current = std::make_pair(vertexPermutation[u], + vertexPermutation[v]); + else + current = std::make_pair(u, v); + + --edge; + + return *this; + } + + rmat_iterator operator++(int) + { + rmat_iterator temp(*this); + ++(*this); + return temp; + } + + bool operator==(const rmat_iterator& other) const + { + return edge == other.edge; + } + + bool operator!=(const rmat_iterator& other) const + { return !(*this == other); } + + private: + + // Parameters + shared_ptr > gen; + vertices_size_type n; + double a, b, c, d; + int edge; + bool permute_vertices; + int SCALE; + + // Internal data structures + std::vector vertexPermutation; + value_type current; + }; + + // Sorted version for CSR + template + struct sort_pair { + bool operator() (const std::pair& x, const std::pair& y) + { + if (x.first == y.first) + return x.second >= y.second; + else + return x.first >= y.first; + } + }; + + template + class sorted_rmat_iterator + { + typedef typename graph_traits::directed_category directed_category; + typedef typename graph_traits::vertices_size_type vertices_size_type; + typedef typename graph_traits::edges_size_type edges_size_type; + + public: + typedef std::input_iterator_tag iterator_category; + typedef std::pair value_type; + typedef const value_type& reference; + typedef const value_type* pointer; + typedef void difference_type; + + // No argument constructor, set to terminating condition + sorted_rmat_iterator() + : gen(), values(sort_pair()), done(true) + { } + + // Initialize for edge generation + sorted_rmat_iterator(RandomGenerator& gen, vertices_size_type n, + edges_size_type m, double a, double b, double c, + double d, bool permute_vertices = true, + EdgePredicate ep = keep_all_edges()) + : gen(), permute_vertices(permute_vertices), + values(sort_pair()), done(false) + + { + assert(a + b + c + d == 1); + + this->gen.reset(new uniform_01(gen)); + + std::vector vertexPermutation; + if (permute_vertices) + generate_permutation_vector(gen, vertexPermutation, n); + + // TODO: "Clip and flip" if undirected graph + int SCALE = int(floor(log2(n))); + + for (int i = 0; i < m; ++i) { + + vertices_size_type u, v; + tie(u, v) = generate_edge(this->gen, n, SCALE, a, b, c, d); + + if (permute_vertices) { + if (ep(vertexPermutation[u], vertexPermutation[v])) + values.push(std::make_pair(vertexPermutation[u], vertexPermutation[v])); + } else { + if (ep(u, v)) + values.push(std::make_pair(u, v)); + } + + } + + current = values.top(); + values.pop(); + } + + reference operator*() const { return current; } + pointer operator->() const { return ¤t; } + + sorted_rmat_iterator& operator++() + { + if (!values.empty()) { + current = values.top(); + values.pop(); + } else + done = true; + + return *this; + } + + sorted_rmat_iterator operator++(int) + { + sorted_rmat_iterator temp(*this); + ++(*this); + return temp; + } + + bool operator==(const sorted_rmat_iterator& other) const + { + return values.empty() && other.values.empty() && done && other.done; + } + + bool operator!=(const sorted_rmat_iterator& other) const + { return !(*this == other); } + + private: + + // Parameters + shared_ptr > gen; + bool permute_vertices; + + // Internal data structures + std::priority_queue, sort_pair > values; + value_type current; + bool done; + }; + + + // This version is slow but guarantees unique edges + template + class unique_rmat_iterator + { + typedef typename graph_traits::directed_category directed_category; + typedef typename graph_traits::vertices_size_type vertices_size_type; + typedef typename graph_traits::edges_size_type edges_size_type; + + public: + typedef std::input_iterator_tag iterator_category; + typedef std::pair value_type; + typedef const value_type& reference; + typedef const value_type* pointer; + typedef void difference_type; + + // No argument constructor, set to terminating condition + unique_rmat_iterator() + : gen(), done(true) + { } + + // Initialize for edge generation + unique_rmat_iterator(RandomGenerator& gen, vertices_size_type n, + edges_size_type m, double a, double b, double c, + double d, bool permute_vertices = true, + EdgePredicate ep = keep_all_edges()) + : gen(), done(false) + + { + assert(a + b + c + d == 1); + + this->gen.reset(new uniform_01(gen)); + + std::vector vertexPermutation; + if (permute_vertices) + generate_permutation_vector(gen, vertexPermutation, n); + + int SCALE = int(floor(log2(n))); + + std::map edge_map; + + edges_size_type edges = 0; + do { + vertices_size_type u, v; + tie(u, v) = generate_edge(this->gen, n, SCALE, a, b, c, d); + + // Lowest vertex number always comes first + // (this means we don't have to worry about i->j and j->i being in the edge list) + if (u > v && is_same::value) + std::swap(u, v); + + if (edge_map.find(std::make_pair(u, v)) == edge_map.end()) { + edge_map[std::make_pair(u, v)] = true; + + if (permute_vertices) { + if (ep(vertexPermutation[u], vertexPermutation[v])) + values.push_back(std::make_pair(vertexPermutation[u], vertexPermutation[v])); + } else { + if (ep(u, v)) + values.push_back(std::make_pair(u, v)); + } + + edges++; + } + } while (edges < m); + // NGE - Asking for more than n^2 edges will result in an infinite loop here + // Asking for a value too close to n^2 edges may as well + + current = values.back(); + values.pop_back(); + } + + reference operator*() const { return current; } + pointer operator->() const { return ¤t; } + + unique_rmat_iterator& operator++() + { + if (!values.empty()) { + current = values.back(); + values.pop_back(); + } else + done = true; + + return *this; + } + + unique_rmat_iterator operator++(int) + { + unique_rmat_iterator temp(*this); + ++(*this); + return temp; + } + + bool operator==(const unique_rmat_iterator& other) const + { + return values.empty() && other.values.empty() && done && other.done; + } + + bool operator!=(const unique_rmat_iterator& other) const + { return !(*this == other); } + + private: + + // Parameters + shared_ptr > gen; + + // Internal data structures + std::vector values; + value_type current; + bool done; + }; + + // This version is slow but guarantees unique edges + template + class sorted_unique_rmat_iterator + { + typedef typename graph_traits::directed_category directed_category; + typedef typename graph_traits::vertices_size_type vertices_size_type; + typedef typename graph_traits::edges_size_type edges_size_type; + + public: + typedef std::input_iterator_tag iterator_category; + typedef std::pair value_type; + typedef const value_type& reference; + typedef const value_type* pointer; + typedef void difference_type; + + // No argument constructor, set to terminating condition + sorted_unique_rmat_iterator() + : gen(), values(sort_pair()), done(true) { } + + // Initialize for edge generation + sorted_unique_rmat_iterator(RandomGenerator& gen, vertices_size_type n, + edges_size_type m, double a, double b, double c, + double d, bool bidirectional = false, + bool permute_vertices = true, + EdgePredicate ep = keep_all_edges()) + : gen(), bidirectional(bidirectional), + values(sort_pair()), done(false) + + { + assert(a + b + c + d == 1); + + this->gen.reset(new uniform_01(gen)); + + std::vector vertexPermutation; + if (permute_vertices) + generate_permutation_vector(gen, vertexPermutation, n); + + int SCALE = int(floor(log2(n))); + + std::map edge_map; + + edges_size_type edges = 0; + do { + + vertices_size_type u, v; + tie(u, v) = generate_edge(this->gen, n, SCALE, a, b, c, d); + + if (bidirectional) { + if (edge_map.find(std::make_pair(u, v)) == edge_map.end()) { + edge_map[std::make_pair(u, v)] = true; + edge_map[std::make_pair(v, u)] = true; + + if (ep(u, v)) + if (permute_vertices) { + values.push(std::make_pair(vertexPermutation[u], vertexPermutation[v])); + values.push(std::make_pair(vertexPermutation[v], vertexPermutation[u])); + } else { + values.push(std::make_pair(u, v)); + values.push(std::make_pair(v, u)); + } + + ++edges; + } + } else { + // Lowest vertex number always comes first + // (this means we don't have to worry about i->j and j->i being in the edge list) + if (u > v && is_same::value) + std::swap(u, v); + + if (edge_map.find(std::make_pair(u, v)) == edge_map.end()) { + edge_map[std::make_pair(u, v)] = true; + + if (permute_vertices) { + if (ep(vertexPermutation[u], vertexPermutation[v])) + values.push(std::make_pair(vertexPermutation[u], vertexPermutation[v])); + } else { + if (ep(u, v)) + values.push(std::make_pair(u, v)); + } + + ++edges; + } + } + + } while (edges < m); + // NGE - Asking for more than n^2 edges will result in an infinite loop here + // Asking for a value too close to n^2 edges may as well + + current = values.top(); + values.pop(); + } + + reference operator*() const { return current; } + pointer operator->() const { return ¤t; } + + sorted_unique_rmat_iterator& operator++() + { + if (!values.empty()) { + current = values.top(); + values.pop(); + } else + done = true; + + return *this; + } + + sorted_unique_rmat_iterator operator++(int) + { + sorted_unique_rmat_iterator temp(*this); + ++(*this); + return temp; + } + + bool operator==(const sorted_unique_rmat_iterator& other) const + { + return values.empty() && other.values.empty() && done && other.done; + } + + bool operator!=(const sorted_unique_rmat_iterator& other) const + { return !(*this == other); } + + private: + + // Parameters + shared_ptr > gen; + bool bidirectional; + + // Internal data structures + std::priority_queue, + sort_pair > values; + value_type current; + bool done; + }; + +} // end namespace boost + +#include + +#endif // BOOST_GRAPH_RMAT_GENERATOR_HPP + diff --git a/include/boost/graph/ssca_graph_generator.hpp b/include/boost/graph/ssca_graph_generator.hpp index a8c67f24..18d4a23f 100644 --- a/include/boost/graph/ssca_graph_generator.hpp +++ b/include/boost/graph/ssca_graph_generator.hpp @@ -23,6 +23,9 @@ enum Direction {FORWARD = 1, BACKWARD = 2, BOTH = FORWARD | BACKWARD}; namespace boost { + // This generator generates graphs according to the method specified + // in SSCA 1.1. Current versions of SSCA use R-MAT graphs + template class ssca_iterator { From f1677c439a4cef44a2b43ffd0aca89c655cc1fed Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Fri, 3 Apr 2009 14:54:10 +0000 Subject: [PATCH 108/224] Fixed float->int warnings [SVN r52156] --- test/layout_test.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/layout_test.cpp b/test/layout_test.cpp index 1199d641..e7537efb 100644 --- a/test/layout_test.cpp +++ b/test/layout_test.cpp @@ -36,8 +36,8 @@ void print_graph_layout(const Graph& g, PositionMap position, const Topology& to max_point = topology.pointwise_max(max_point, position[v]); } - for (int y = min_point[1]; y <= max_point[1]; ++y) { - for (int x = min_point[0]; x <= max_point[0]; ++x) { + for (int y = (int)min_point[1]; y <= (int)max_point[1]; ++y) { + for (int x = (int)min_point[0]; x <= (int)max_point[0]; ++x) { typename graph_traits::vertex_iterator vi, vi_end; // Find vertex at this position typename graph_traits::vertices_size_type index = 0; From 43eed0a3ba30a5edff1beaf061d4aa7cef5df3fa Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Fri, 3 Apr 2009 14:55:01 +0000 Subject: [PATCH 109/224] Trying to fix Sun CC 5.9 error by fully qualifying root_two [SVN r52157] --- include/boost/graph/topology.hpp | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/include/boost/graph/topology.hpp b/include/boost/graph/topology.hpp index e2632292..f6d74f38 100644 --- a/include/boost/graph/topology.hpp +++ b/include/boost/graph/topology.hpp @@ -14,7 +14,7 @@ #include #include #include -#include +#include // For root_two #include #include // For BOOST_STATIC_CONSTANT #include @@ -42,6 +42,7 @@ class convex_topology double values[Dims]; }; + friend struct point_difference; // Workaround for VisualAge C++ bug struct point_difference { BOOST_STATIC_CONSTANT(std::size_t, dimensions = Dims); @@ -438,14 +439,13 @@ class heart_topology { #ifndef BOOST_NO_STDC_NAMESPACE using std::abs; - using boost::math::constants::root_two; #endif if (p[1] < abs(p[0]) - 2000) return false; // Bottom if (p[1] <= -1000) return true; // Diagonal of square - if (boost::math::hypot(p[0] - -500, p[1] - -500) <= 500. * root_two()) + if (boost::math::hypot(p[0] - -500, p[1] - -500) <= 500. * boost::math::constants::root_two()) return true; // Left circle - if (boost::math::hypot(p[0] - 500, p[1] - -500) <= 500. * root_two()) + if (boost::math::hypot(p[0] - 500, p[1] - -500) <= 500. * boost::math::constants::root_two()) return true; // Right circle return false; } @@ -475,10 +475,9 @@ class heart_topology point random_point() const { point result; - using boost::math::constants::root_two; do { - result[0] = (*rand)() * (1000 + 1000 * root_two()) - (500 + 500 * root_two()); - result[1] = (*rand)() * (2000 + 500 * (root_two() - 1)) - 2000; + result[0] = (*rand)() * (1000 + 1000 * boost::math::constants::root_two()) - (500 + 500 * boost::math::constants::root_two()); + result[1] = (*rand)() * (2000 + 500 * (boost::math::constants::root_two() - 1)) - 2000; } while (!in_heart(result)); return result; } From 803a8be664fdbc68ae6cc52ee1455001e6da3788 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Fri, 3 Apr 2009 14:57:27 +0000 Subject: [PATCH 110/224] Fully qualifying std::sqrt to fix compile errors, and removing "using" statements that are never used [SVN r52158] --- include/boost/graph/fruchterman_reingold.hpp | 17 +---------------- 1 file changed, 1 insertion(+), 16 deletions(-) diff --git a/include/boost/graph/fruchterman_reingold.hpp b/include/boost/graph/fruchterman_reingold.hpp index dbab6bc8..531317f9 100644 --- a/include/boost/graph/fruchterman_reingold.hpp +++ b/include/boost/graph/fruchterman_reingold.hpp @@ -104,10 +104,7 @@ struct grid_force_pairs PositionMap position, const Graph& g) : topology(topology), extent(extent), origin(origin), position(position) { -#ifndef BOOST_NO_STDC_NAMESPACE - using std::sqrt; -#endif // BOOST_NO_STDC_NAMESPACE - two_k = 2. * topology.volume(extent) / sqrt(num_vertices(g)); + two_k = 2. * topology.volume(extent) / std::sqrt(num_vertices(g)); } template @@ -118,10 +115,6 @@ struct grid_force_pairs typedef std::list bucket_t; typedef std::vector buckets_t; -#ifndef BOOST_NO_STDC_NAMESPACE - using std::sqrt; -#endif // BOOST_NO_STDC_NAMESPACE - std::size_t columns = std::size_t(extent[0] / two_k + 1.); std::size_t rows = std::size_t(extent[1] / two_k + 1.); buckets_t buckets(rows * columns); @@ -247,9 +240,6 @@ namespace detail { void operator()(vertex_descriptor u, vertex_descriptor v) { -#ifndef BOOST_NO_STDC_NAMESPACE - using std::sqrt; -#endif // BOOST_NO_STDC_NAMESPACE if (u != v) { // When the vertices land on top of each other, move the // first vertex away from the boundaries. @@ -302,11 +292,6 @@ fruchterman_reingold_force_directed_layout typedef typename graph_traits::vertex_descriptor vertex_descriptor; typedef typename graph_traits::edge_iterator edge_iterator; -#ifndef BOOST_NO_STDC_NAMESPACE - using std::sqrt; - using std::pow; -#endif // BOOST_NO_STDC_NAMESPACE - double volume = 1.; for (std::size_t i = 0; i < Topology::point_difference_type::dimensions; ++i) volume *= extent[i]; From 63fae9d6588b7c8085a4abc5d71a5c36c28d14da Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Sat, 4 Apr 2009 20:02:25 +0000 Subject: [PATCH 111/224] Fixed regression test errors and warnings [SVN r52172] --- include/boost/graph/fruchterman_reingold.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/boost/graph/fruchterman_reingold.hpp b/include/boost/graph/fruchterman_reingold.hpp index 531317f9..65b4a938 100644 --- a/include/boost/graph/fruchterman_reingold.hpp +++ b/include/boost/graph/fruchterman_reingold.hpp @@ -104,7 +104,7 @@ struct grid_force_pairs PositionMap position, const Graph& g) : topology(topology), extent(extent), origin(origin), position(position) { - two_k = 2. * topology.volume(extent) / std::sqrt(num_vertices(g)); + two_k = 2. * this->topology.volume(this->extent) / std::sqrt((double)num_vertices(g)); } template From cdde244b46712a82723b593a4cb28d63904e3c03 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Mon, 6 Apr 2009 15:19:56 +0000 Subject: [PATCH 112/224] Made some things public for VisualAge C++ [SVN r52213] --- include/boost/graph/topology.hpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/include/boost/graph/topology.hpp b/include/boost/graph/topology.hpp index f6d74f38..8c8262f0 100644 --- a/include/boost/graph/topology.hpp +++ b/include/boost/graph/topology.hpp @@ -31,6 +31,7 @@ namespace boost { template class convex_topology { + public: // For VisualAge C++ struct point { BOOST_STATIC_CONSTANT(std::size_t, dimensions = Dims); @@ -42,7 +43,7 @@ class convex_topology double values[Dims]; }; - friend struct point_difference; // Workaround for VisualAge C++ bug + public: // For VisualAge C++ struct point_difference { BOOST_STATIC_CONSTANT(std::size_t, dimensions = Dims); From aec4a0f3017d80b11eebec137f86de1d9c9ba769 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Mon, 6 Apr 2009 16:52:47 +0000 Subject: [PATCH 113/224] Removed include of distributed generator and blank line [SVN r52214] --- include/boost/graph/rmat_graph_generator.hpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/include/boost/graph/rmat_graph_generator.hpp b/include/boost/graph/rmat_graph_generator.hpp index 22c44b8a..775505bf 100644 --- a/include/boost/graph/rmat_graph_generator.hpp +++ b/include/boost/graph/rmat_graph_generator.hpp @@ -573,7 +573,4 @@ namespace boost { } // end namespace boost -#include - #endif // BOOST_GRAPH_RMAT_GENERATOR_HPP - From 0185fdf67e169e3381c278657839c3a02ba6f03e Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Mon, 6 Apr 2009 16:53:08 +0000 Subject: [PATCH 114/224] Added enable_if to match PBGL [SVN r52215] --- include/boost/graph/dijkstra_shortest_paths.hpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/include/boost/graph/dijkstra_shortest_paths.hpp b/include/boost/graph/dijkstra_shortest_paths.hpp index c454517b..d9b19acd 100644 --- a/include/boost/graph/dijkstra_shortest_paths.hpp +++ b/include/boost/graph/dijkstra_shortest_paths.hpp @@ -344,7 +344,8 @@ namespace boost { PredecessorMap predecessor, DistanceMap distance, WeightMap weight, IndexMap index_map, Compare compare, Combine combine, DistInf inf, DistZero zero, - DijkstraVisitor vis) + DijkstraVisitor vis + 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, From 0dfbf04a753873f377b37f6fe4a3ad1744663abd Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Mon, 6 Apr 2009 16:59:38 +0000 Subject: [PATCH 115/224] Added generator_test from Nick Edmonds [SVN r52216] --- test/CMakeLists.txt | 1 + test/Jamfile.v2 | 1 + test/generator_test.cpp | 115 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 117 insertions(+) create mode 100644 test/generator_test.cpp diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 4ff827db..fd459b3f 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -18,6 +18,7 @@ boost_test_run(dominator_tree_test) boost_test_run(relaxed_heap_test ARGS 5000 15000) boost_test_compile(edge_list_cc) boost_test_compile(filtered_graph_cc) +boost_test_run(generator_test) boost_test_run(graph) boost_test_compile(graph_concepts) boost_test_run(graphviz_test diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index fd1b3ce4..549e0d0a 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -50,6 +50,7 @@ test-suite graph_test : [ run relaxed_heap_test.cpp : 5000 15000 ] [ compile edge_list_cc.cpp ] [ compile filtered_graph_cc.cpp ] + [ run generator_test.cpp ] [ run graph.cpp ] [ compile graph_concepts.cpp ] [ run graphviz_test.cpp diff --git a/test/generator_test.cpp b/test/generator_test.cpp new file mode 100644 index 00000000..8289409c --- /dev/null +++ b/test/generator_test.cpp @@ -0,0 +1,115 @@ +#include +#include + +#include +#include +#include +#include +#include + +#include + +using namespace boost; + +int test_main(int argc, char** argv) { + + typedef rand48 RandomGenerator; + + typedef adjacency_list Graph; + + RandomGenerator gen; + + size_t N = 100; + size_t M = 1000; + double p = 0.05; + + // Test Erdos-Renyi generator + { + erdos_renyi_iterator start(gen, N, p); + erdos_renyi_iterator end; + + while (start != end) ++start; + + BOOST_CHECK(start == end); + } + + { + sorted_erdos_renyi_iterator start(gen, N, p); + sorted_erdos_renyi_iterator end; + + while (start != end) ++start; + + BOOST_CHECK(start == end); + } + + // Test Small World generator + { + small_world_iterator start(gen, N, M, p); + small_world_iterator end; + + while (start != end) ++start; + + BOOST_CHECK(start == end); + } + + // Test SSCA generator + { + ssca_iterator start(gen, N, 5, 0.5, 5, p); + ssca_iterator end; + + while (start != end) ++start; + + BOOST_CHECK(start == end); + } + + // Test Mesh generator + { + mesh_iterator start(N, N); + mesh_iterator end; + + while (start != end) ++start; + + BOOST_CHECK(start == end); + } + + // Test R-MAT generator + double a = 0.57, b = 0.19, c = 0.19, d = 0.05; + + { + rmat_iterator start(gen, N, M, a, b, c, d); + rmat_iterator end; + + while (start != end) ++start; + + BOOST_CHECK(start == end); + } + + { + unique_rmat_iterator start(gen, N, M, a, b, c, d); + unique_rmat_iterator end; + + while (start != end) ++start; + + BOOST_CHECK(start == end); + } + + { + sorted_unique_rmat_iterator start(gen, N, M, a, b, c, d); + sorted_unique_rmat_iterator end; + + while (start != end) ++start; + + BOOST_CHECK(start == end); + } + + { + sorted_unique_rmat_iterator start(gen, N, M, a, b, c, d, true); + sorted_unique_rmat_iterator end; + + while (start != end) ++start; + + BOOST_CHECK(start == end); + } + + return 0; +} From 891cf5584c7f86fb6c261b319f60c5ee33baaaab Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Mon, 6 Apr 2009 16:59:52 +0000 Subject: [PATCH 116/224] Fixed bug [SVN r52217] --- include/boost/graph/rmat_graph_generator.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/boost/graph/rmat_graph_generator.hpp b/include/boost/graph/rmat_graph_generator.hpp index 775505bf..9c81e500 100644 --- a/include/boost/graph/rmat_graph_generator.hpp +++ b/include/boost/graph/rmat_graph_generator.hpp @@ -159,7 +159,7 @@ namespace boost { else current = std::make_pair(u, v); - edge; + --edge; } reference operator*() const { return current; } From 0960281a15aea9836763deaca87176ee9f8eee49 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Mon, 6 Apr 2009 17:05:00 +0000 Subject: [PATCH 117/224] Fixed documentation [SVN r52218] --- include/boost/graph/kamada_kawai_spring_layout.hpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/include/boost/graph/kamada_kawai_spring_layout.hpp b/include/boost/graph/kamada_kawai_spring_layout.hpp index d846cd5d..0262e1fc 100644 --- a/include/boost/graph/kamada_kawai_spring_layout.hpp +++ b/include/boost/graph/kamada_kawai_spring_layout.hpp @@ -428,6 +428,9 @@ namespace boost { * \param weight (IN) must be a model of Readable Property Map, * which provides the weight of each edge in the graph @p g. * + * \param topology (IN) must be a topology object (see topology.hpp), + * which provides operations on points and differences between them. + * * \param edge_or_side_length (IN) provides either the unit length * @c e of an edge in the layout or the length of a side @c s of the * display area, and must be either @c boost::edge_length(e) or @c From 1c52b10253100f339a5bbdb3868d169ead592a7f Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Mon, 6 Apr 2009 17:09:50 +0000 Subject: [PATCH 118/224] Fixed spelling [SVN r52219] --- test/Jamfile.v2 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 549e0d0a..cfa8bd8b 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -114,11 +114,11 @@ test-suite graph_test : # Run SDB tests only when -sSDB= is set. if [ modules.peek : SDB ] != "" { - local SDB_DEPENDCIES = + local SDB_DEPENDENCIES = $(SGB) $(SGB)/libgb.a ; compile stanford_graph_cc.cpp - $(SDB_DEPENDCIES) ; + $(SDB_DEPENDENCIES) ; } # Run LEDA tests only when -sLEDA= is set. From a2843c2352b8ae776878725a50c0668add3aefc4 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Mon, 6 Apr 2009 20:48:42 +0000 Subject: [PATCH 119/224] Added copyright and license info [SVN r52220] --- test/generator_test.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/test/generator_test.cpp b/test/generator_test.cpp index 8289409c..15f47408 100644 --- a/test/generator_test.cpp +++ b/test/generator_test.cpp @@ -1,3 +1,12 @@ +// Copyright 2009 The Trustees of Indiana University. + +// 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) + +// Authors: Nicholas Edmonds +// Andrew Lumsdaine + #include #include From 8d4c3cc7d6ef99158796198b798fb2b3dc543b56 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Tue, 7 Apr 2009 01:28:38 +0000 Subject: [PATCH 120/224] Moved property map library into property_map/ directory; made old files into stubs with #warnings; converted uses and docs of property map library to use new names [SVN r52226] --- doc/PlanarEmbedding.html | 4 ++-- doc/biconnected_components.w | 2 +- doc/eg1-iso.cpp | 2 +- doc/isomorphism-impl.w | 2 +- doc/trouble_shooting.html | 3 ++- doc/using_property_maps.html | 2 +- example/adjacency_list.cpp | 2 +- example/bfs.cpp | 2 +- example/bfs_neighbor.cpp | 2 +- example/canonical_ordering.cpp | 2 +- example/city_visitor.cpp | 2 +- example/edge_property.cpp | 2 +- example/exterior_properties.cpp | 2 +- example/exterior_property_map.cpp | 2 +- example/interior_pmap_bundled.cpp | 2 +- example/interior_property_map.cpp | 2 +- example/iterator-property-map-eg.cpp | 2 +- example/johnson-eg.cpp | 2 +- example/knights-tour.cpp | 2 +- example/kuratowski_subgraph.cpp | 2 +- example/make_biconnected_planar.cpp | 2 +- example/make_connected.cpp | 2 +- example/make_maximal_planar.cpp | 2 +- example/neighbor_bfs.cpp | 2 +- example/planar_face_traversal.cpp | 2 +- example/put-get-helper-eg.cpp | 2 +- example/straight_line_drawing.cpp | 2 +- include/boost/graph/adjacency_list.hpp | 2 +- include/boost/graph/astar_search.hpp | 4 ++-- include/boost/graph/bc_clustering.hpp | 2 +- include/boost/graph/betweenness_centrality.hpp | 2 +- include/boost/graph/biconnected_components.hpp | 2 +- include/boost/graph/chrobak_payne_drawing.hpp | 2 +- include/boost/graph/copy.hpp | 2 +- include/boost/graph/create_condensation_graph.hpp | 2 +- include/boost/graph/detail/adjacency_list.hpp | 2 +- include/boost/graph/detail/d_ary_heap.hpp | 2 +- include/boost/graph/detail/read_graphviz_spirit.hpp | 2 +- include/boost/graph/detail/self_avoiding_walk.hpp | 2 +- include/boost/graph/detail/sparse_ordering.hpp | 2 +- include/boost/graph/dijkstra_shortest_paths.hpp | 4 ++-- include/boost/graph/edmonds_karp_max_flow.hpp | 2 +- include/boost/graph/floyd_warshall_shortest.hpp | 2 +- include/boost/graph/graph_archetypes.hpp | 2 +- include/boost/graph/graph_as_tree.hpp | 2 +- include/boost/graph/graph_concepts.hpp | 2 +- include/boost/graph/graphviz.hpp | 4 ++-- include/boost/graph/is_kuratowski_subgraph.hpp | 2 +- include/boost/graph/is_straight_line_drawing.hpp | 2 +- include/boost/graph/johnson_all_pairs_shortest.hpp | 2 +- include/boost/graph/kolmogorov_max_flow.hpp | 2 +- include/boost/graph/kruskal_min_spanning_tree.hpp | 2 +- include/boost/graph/make_biconnected_planar.hpp | 2 +- include/boost/graph/make_connected.hpp | 2 +- include/boost/graph/make_maximal_planar.hpp | 2 +- include/boost/graph/max_cardinality_matching.hpp | 2 +- include/boost/graph/minimum_degree_ordering.hpp | 2 +- include/boost/graph/page_rank.hpp | 2 +- include/boost/graph/planar_canonical_ordering.hpp | 2 +- include/boost/graph/planar_detail/add_edge_visitors.hpp | 2 +- include/boost/graph/planar_detail/boyer_myrvold_impl.hpp | 2 +- include/boost/graph/planar_detail/bucket_sort.hpp | 2 +- include/boost/graph/properties.hpp | 4 ++-- include/boost/graph/property_iter_range.hpp | 2 +- include/boost/graph/property_maps/constant_property_map.hpp | 2 +- include/boost/graph/property_maps/container_property_map.hpp | 2 +- include/boost/graph/relax.hpp | 2 +- include/boost/graph/sequential_vertex_coloring.hpp | 2 +- include/boost/graph/sloan_ordering.hpp | 2 +- include/boost/graph/stanford_graph.hpp | 2 +- include/boost/graph/topological_sort.hpp | 2 +- include/boost/graph/two_bit_color_map.hpp | 2 +- include/boost/graph/vector_as_graph.hpp | 2 +- include/boost/graph/visitors.hpp | 2 +- include/boost/pending/fibonacci_heap.hpp | 2 +- include/boost/pending/indirect_cmp.hpp | 2 +- include/boost/pending/mutable_queue.hpp | 2 +- include/boost/pending/relaxed_heap.hpp | 2 +- module.cmake | 2 +- test/adjacency_matrix_test.cpp | 2 +- test/all_planar_input_files_test.cpp | 2 +- test/basic_planarity_test.cpp | 4 ++-- test/betweenness_centrality_test.cpp | 2 +- test/core_numbers_test.cpp | 2 +- test/dag_longest_paths.cpp | 2 +- test/graphviz_test.cpp | 2 +- test/is_straight_line_draw_test.cpp | 2 +- test/isomorphism.cpp | 2 +- test/johnson-test.cpp | 2 +- test/kolmogorov_max_flow_test.cpp | 2 +- test/make_bicon_planar_test.cpp | 4 ++-- test/make_connected_test.cpp | 4 ++-- test/make_maximal_planar_test.cpp | 4 ++-- test/matching_test.cpp | 2 +- test/max_flow_test.cpp | 2 +- test/parallel_edges_loops_test.cpp | 2 +- test/random_matching_test.cpp | 2 +- 97 files changed, 107 insertions(+), 106 deletions(-) mode change 100755 => 100644 test/matching_test.cpp mode change 100755 => 100644 test/random_matching_test.cpp diff --git a/doc/PlanarEmbedding.html b/doc/PlanarEmbedding.html index 7e3739f5..b8234a72 100644 --- a/doc/PlanarEmbedding.html +++ b/doc/PlanarEmbedding.html @@ -137,7 +137,7 @@ concept. Below is an example of using this approach to create a model of PlanarEmbedding:
    -#include <boost/property_map.hpp>
    +#include <boost/property_map/property_map.hpp>
     #include <vector>
     
     ...
    @@ -175,4 +175,4 @@ planar_embedding_t planar_embedding(planar_embedding_storage.begin(),
     Copyright © 2007 Aaron Windsor (
     aaron.windsor@gmail.com) 
     
    -
    \ No newline at end of file
    +
    diff --git a/doc/biconnected_components.w b/doc/biconnected_components.w
    index 1aec2a55..97ba5dc8 100644
    --- a/doc/biconnected_components.w
    +++ b/doc/biconnected_components.w
    @@ -285,7 +285,7 @@ S.pop();
     #include 
     #include 
     #include 
    -#include 
    +#include 
     
     namespace boost {
       @
    diff --git a/doc/eg1-iso.cpp b/doc/eg1-iso.cpp
    index 7a82c7e7..7ba5cb24 100644
    --- a/doc/eg1-iso.cpp
    +++ b/doc/eg1-iso.cpp
    @@ -20,7 +20,7 @@
     #include 
     #include 
     //#include "isomorphism-v3.hpp"
    -#include 
    +#include 
     #include 
     #include 
     #include 
    diff --git a/doc/isomorphism-impl.w b/doc/isomorphism-impl.w
    index 728485a0..58b4bed8 100644
    --- a/doc/isomorphism-impl.w
    +++ b/doc/isomorphism-impl.w
    @@ -1007,7 +1007,7 @@ code parts into namespace \code{boost}.
     #include 
     #include 
     #include 
    -#include 
    +#include 
     #include 
     #include 
     #include 
    diff --git a/doc/trouble_shooting.html b/doc/trouble_shooting.html
    index 21c657ff..8e0328ed 100644
    --- a/doc/trouble_shooting.html
    +++ b/doc/trouble_shooting.html
    @@ -50,7 +50,8 @@ using the boost:: prefix, i.e., boost::source(e, g) instead of
     
     

    There is a VC++ bug that appears when using get(property, graph, edge). A workaround is to use get(get(property, -graph), edge) instead. +graph), edge) instead. Note that boost/property_map.hpp has +now been moved to boost/property_map/property_map.hpp.


    diff --git a/doc/using_property_maps.html b/doc/using_property_maps.html index 412b5fe5..cc23b01b 100644 --- a/doc/using_property_maps.html +++ b/doc/using_property_maps.html @@ -287,7 +287,7 @@ with pointers as vertex property maps. The reason that pointers can be used as property maps is that there are several overloaded functions and a specialization of property_traits in the header boost/property_map.hpp +href="../../../boost/property_map/property_map.hpp">boost/property_map/property_map.hpp that implement the property map interface in terms of pointers. The definition of those functions is listed here. diff --git a/example/adjacency_list.cpp b/example/adjacency_list.cpp index 4d8c165d..6d805379 100644 --- a/example/adjacency_list.cpp +++ b/example/adjacency_list.cpp @@ -14,7 +14,7 @@ #include #include -#include +#include /* Sample Output diff --git a/example/bfs.cpp b/example/bfs.cpp index 71b12008..1f34c155 100644 --- a/example/bfs.cpp +++ b/example/bfs.cpp @@ -17,7 +17,7 @@ #include #include #include -#include +#include #include /* diff --git a/example/bfs_neighbor.cpp b/example/bfs_neighbor.cpp index 5bac52b5..050362f6 100644 --- a/example/bfs_neighbor.cpp +++ b/example/bfs_neighbor.cpp @@ -18,7 +18,7 @@ #include #include #include -#include +#include /* diff --git a/example/canonical_ordering.cpp b/example/canonical_ordering.cpp index 04f96635..770b251e 100644 --- a/example/canonical_ordering.cpp +++ b/example/canonical_ordering.cpp @@ -9,7 +9,7 @@ #include #include #include -#include +#include #include #include diff --git a/example/city_visitor.cpp b/example/city_visitor.cpp index 44a4a09c..85415a6f 100644 --- a/example/city_visitor.cpp +++ b/example/city_visitor.cpp @@ -16,7 +16,7 @@ #include #include #include -#include +#include #include // for boost::make_list diff --git a/example/edge_property.cpp b/example/edge_property.cpp index bcd60357..5adac08e 100644 --- a/example/edge_property.cpp +++ b/example/edge_property.cpp @@ -52,7 +52,7 @@ #include #include -#include +#include #include diff --git a/example/exterior_properties.cpp b/example/exterior_properties.cpp index 5e453979..3ca4edc3 100644 --- a/example/exterior_properties.cpp +++ b/example/exterior_properties.cpp @@ -36,7 +36,7 @@ #include #include #include -#include +#include template void print_network(Graph& G, Capacity capacity, Flow flow) diff --git a/example/exterior_property_map.cpp b/example/exterior_property_map.cpp index 8917c7f7..9b9ac79e 100644 --- a/example/exterior_property_map.cpp +++ b/example/exterior_property_map.cpp @@ -12,7 +12,7 @@ #include #include #include -#include +#include using namespace std; using namespace boost; diff --git a/example/interior_pmap_bundled.cpp b/example/interior_pmap_bundled.cpp index 09cd8dec..cee50169 100644 --- a/example/interior_pmap_bundled.cpp +++ b/example/interior_pmap_bundled.cpp @@ -12,7 +12,7 @@ #include #include #include -#include +#include #include using namespace std; diff --git a/example/interior_property_map.cpp b/example/interior_property_map.cpp index dde734d9..7083d663 100644 --- a/example/interior_property_map.cpp +++ b/example/interior_property_map.cpp @@ -11,7 +11,7 @@ #include #include #include -#include +#include #include using namespace std; diff --git a/example/iterator-property-map-eg.cpp b/example/iterator-property-map-eg.cpp index 549a4b9b..9257af4e 100644 --- a/example/iterator-property-map-eg.cpp +++ b/example/iterator-property-map-eg.cpp @@ -6,7 +6,7 @@ // http://www.boost.org/LICENSE_1_0.txt) //======================================================================= #include -#include +#include int main() diff --git a/example/johnson-eg.cpp b/example/johnson-eg.cpp index 8ad5471b..fa56081a 100644 --- a/example/johnson-eg.cpp +++ b/example/johnson-eg.cpp @@ -10,7 +10,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/example/knights-tour.cpp b/example/knights-tour.cpp index 292bdfa2..bbd0d800 100644 --- a/example/knights-tour.cpp +++ b/example/knights-tour.cpp @@ -13,7 +13,7 @@ #include #include #include -#include +#include using namespace boost; diff --git a/example/kuratowski_subgraph.cpp b/example/kuratowski_subgraph.cpp index 4a70fbdb..5b080f46 100644 --- a/example/kuratowski_subgraph.cpp +++ b/example/kuratowski_subgraph.cpp @@ -9,7 +9,7 @@ #include #include #include -#include +#include #include #include diff --git a/example/make_biconnected_planar.cpp b/example/make_biconnected_planar.cpp index 027ab440..3c4a7745 100644 --- a/example/make_biconnected_planar.cpp +++ b/example/make_biconnected_planar.cpp @@ -9,7 +9,7 @@ #include #include #include -#include +#include #include #include diff --git a/example/make_connected.cpp b/example/make_connected.cpp index 48eb9d97..91ceb9a7 100644 --- a/example/make_connected.cpp +++ b/example/make_connected.cpp @@ -9,7 +9,7 @@ #include #include #include -#include +#include #include #include diff --git a/example/make_maximal_planar.cpp b/example/make_maximal_planar.cpp index 76c1ae50..70fd9b3f 100644 --- a/example/make_maximal_planar.cpp +++ b/example/make_maximal_planar.cpp @@ -9,7 +9,7 @@ #include #include #include -#include +#include #include #include diff --git a/example/neighbor_bfs.cpp b/example/neighbor_bfs.cpp index e5b88840..7b3e339a 100644 --- a/example/neighbor_bfs.cpp +++ b/example/neighbor_bfs.cpp @@ -18,7 +18,7 @@ #include #include #include -#include +#include /* diff --git a/example/planar_face_traversal.cpp b/example/planar_face_traversal.cpp index 479f683c..8d4daab4 100644 --- a/example/planar_face_traversal.cpp +++ b/example/planar_face_traversal.cpp @@ -9,7 +9,7 @@ #include #include #include -#include +#include #include #include diff --git a/example/put-get-helper-eg.cpp b/example/put-get-helper-eg.cpp index 6bb911db..1134c029 100644 --- a/example/put-get-helper-eg.cpp +++ b/example/put-get-helper-eg.cpp @@ -7,7 +7,7 @@ //======================================================================= #include #include -#include +#include #ifdef BOOST_NO_STD_ITERATOR_TRAITS #error This examples requires a compiler that provides a working std::iterator_traits diff --git a/example/straight_line_drawing.cpp b/example/straight_line_drawing.cpp index 2f6871d4..06d1145f 100644 --- a/example/straight_line_drawing.cpp +++ b/example/straight_line_drawing.cpp @@ -9,7 +9,7 @@ #include #include #include -#include +#include #include #include diff --git a/include/boost/graph/adjacency_list.hpp b/include/boost/graph/adjacency_list.hpp index eedda09d..36e86878 100644 --- a/include/boost/graph/adjacency_list.hpp +++ b/include/boost/graph/adjacency_list.hpp @@ -38,7 +38,7 @@ #include #include -#include +#include #include #include #include diff --git a/include/boost/graph/astar_search.hpp b/include/boost/graph/astar_search.hpp index fc1993d4..8eca6517 100644 --- a/include/boost/graph/astar_search.hpp +++ b/include/boost/graph/astar_search.hpp @@ -22,8 +22,8 @@ #include #include #include -#include -#include +#include +#include namespace boost { diff --git a/include/boost/graph/bc_clustering.hpp b/include/boost/graph/bc_clustering.hpp index eb438c14..d60f053f 100644 --- a/include/boost/graph/bc_clustering.hpp +++ b/include/boost/graph/bc_clustering.hpp @@ -14,7 +14,7 @@ #include #include #include -#include +#include namespace boost { diff --git a/include/boost/graph/betweenness_centrality.hpp b/include/boost/graph/betweenness_centrality.hpp index 132602e5..15cfe741 100644 --- a/include/boost/graph/betweenness_centrality.hpp +++ b/include/boost/graph/betweenness_centrality.hpp @@ -20,7 +20,7 @@ #include #include #include -#include +#include #include #include diff --git a/include/boost/graph/biconnected_components.hpp b/include/boost/graph/biconnected_components.hpp index 2d8b271d..ac220659 100644 --- a/include/boost/graph/biconnected_components.hpp +++ b/include/boost/graph/biconnected_components.hpp @@ -17,7 +17,7 @@ #include #include #include -#include +#include #include #include diff --git a/include/boost/graph/chrobak_payne_drawing.hpp b/include/boost/graph/chrobak_payne_drawing.hpp index e8a9104b..9e3a2f36 100644 --- a/include/boost/graph/chrobak_payne_drawing.hpp +++ b/include/boost/graph/chrobak_payne_drawing.hpp @@ -14,7 +14,7 @@ #include #include //for next and prior #include -#include +#include namespace boost diff --git a/include/boost/graph/copy.hpp b/include/boost/graph/copy.hpp index fd98a426..c566503a 100644 --- a/include/boost/graph/copy.hpp +++ b/include/boost/graph/copy.hpp @@ -44,7 +44,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/include/boost/graph/create_condensation_graph.hpp b/include/boost/graph/create_condensation_graph.hpp index f3d1113a..4f3316f6 100644 --- a/include/boost/graph/create_condensation_graph.hpp +++ b/include/boost/graph/create_condensation_graph.hpp @@ -11,7 +11,7 @@ #define BOOST_CREATE_CONDENSATION_GRAPH_HPP #include -#include +#include namespace boost { diff --git a/include/boost/graph/detail/adjacency_list.hpp b/include/boost/graph/detail/adjacency_list.hpp index ae6db307..0641247a 100644 --- a/include/boost/graph/detail/adjacency_list.hpp +++ b/include/boost/graph/detail/adjacency_list.hpp @@ -15,7 +15,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/include/boost/graph/detail/d_ary_heap.hpp b/include/boost/graph/detail/d_ary_heap.hpp index 548b06dd..2ec716d3 100644 --- a/include/boost/graph/detail/d_ary_heap.hpp +++ b/include/boost/graph/detail/d_ary_heap.hpp @@ -18,7 +18,7 @@ #include #include #include -#include +#include namespace boost { diff --git a/include/boost/graph/detail/read_graphviz_spirit.hpp b/include/boost/graph/detail/read_graphviz_spirit.hpp index baaa6e1f..815befe9 100644 --- a/include/boost/graph/detail/read_graphviz_spirit.hpp +++ b/include/boost/graph/detail/read_graphviz_spirit.hpp @@ -43,7 +43,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/include/boost/graph/detail/self_avoiding_walk.hpp b/include/boost/graph/detail/self_avoiding_walk.hpp index def0c6ee..c171897f 100644 --- a/include/boost/graph/detail/self_avoiding_walk.hpp +++ b/include/boost/graph/detail/self_avoiding_walk.hpp @@ -29,7 +29,7 @@ #include #include #include -#include +#include #define SAW_SENTINAL -1 diff --git a/include/boost/graph/detail/sparse_ordering.hpp b/include/boost/graph/detail/sparse_ordering.hpp index d70e906d..593d8c85 100644 --- a/include/boost/graph/detail/sparse_ordering.hpp +++ b/include/boost/graph/detail/sparse_ordering.hpp @@ -20,7 +20,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/include/boost/graph/dijkstra_shortest_paths.hpp b/include/boost/graph/dijkstra_shortest_paths.hpp index d9b19acd..14cf377e 100644 --- a/include/boost/graph/dijkstra_shortest_paths.hpp +++ b/include/boost/graph/dijkstra_shortest_paths.hpp @@ -27,8 +27,8 @@ #include #include #include -#include -#include +#include +#include #include #ifdef BOOST_GRAPH_DIJKSTRA_TESTING diff --git a/include/boost/graph/edmonds_karp_max_flow.hpp b/include/boost/graph/edmonds_karp_max_flow.hpp index 2564acd6..fed4d69f 100644 --- a/include/boost/graph/edmonds_karp_max_flow.hpp +++ b/include/boost/graph/edmonds_karp_max_flow.hpp @@ -15,7 +15,7 @@ #include // for std::min and std::max #include #include -#include +#include #include #include #include diff --git a/include/boost/graph/floyd_warshall_shortest.hpp b/include/boost/graph/floyd_warshall_shortest.hpp index 699d610c..d57f13c1 100644 --- a/include/boost/graph/floyd_warshall_shortest.hpp +++ b/include/boost/graph/floyd_warshall_shortest.hpp @@ -29,7 +29,7 @@ #ifndef BOOST_GRAPH_FLOYD_WARSHALL_HPP #define BOOST_GRAPH_FLOYD_WARSHALL_HPP -#include +#include #include #include #include diff --git a/include/boost/graph/graph_archetypes.hpp b/include/boost/graph/graph_archetypes.hpp index ce4c85fd..7408783f 100644 --- a/include/boost/graph/graph_archetypes.hpp +++ b/include/boost/graph/graph_archetypes.hpp @@ -10,7 +10,7 @@ #ifndef BOOST_GRAPH_ARCHETYPES_HPP #define BOOST_GRAPH_ARCHETYPES_HPP -#include +#include #include namespace boost { // should use a different namespace for this diff --git a/include/boost/graph/graph_as_tree.hpp b/include/boost/graph/graph_as_tree.hpp index 7619dfcc..3758c3f0 100644 --- a/include/boost/graph/graph_as_tree.hpp +++ b/include/boost/graph/graph_as_tree.hpp @@ -13,7 +13,7 @@ #include #include -#include +#include #include #include #include diff --git a/include/boost/graph/graph_concepts.hpp b/include/boost/graph/graph_concepts.hpp index 3f5ac0d9..fe331336 100644 --- a/include/boost/graph/graph_concepts.hpp +++ b/include/boost/graph/graph_concepts.hpp @@ -14,7 +14,7 @@ #define BOOST_GRAPH_CONCEPTS_HPP #include -#include +#include #include #include #include diff --git a/include/boost/graph/graphviz.hpp b/include/boost/graph/graphviz.hpp index 9935b4be..43387883 100644 --- a/include/boost/graph/graphviz.hpp +++ b/include/boost/graph/graphviz.hpp @@ -16,13 +16,13 @@ #include #include #include // for FILE -#include +#include #include #include #include #include #include -#include +#include #include #ifdef BOOST_HAS_DECLSPEC diff --git a/include/boost/graph/is_kuratowski_subgraph.hpp b/include/boost/graph/is_kuratowski_subgraph.hpp index 0b498e5b..fab0b024 100644 --- a/include/boost/graph/is_kuratowski_subgraph.hpp +++ b/include/boost/graph/is_kuratowski_subgraph.hpp @@ -11,7 +11,7 @@ #include #include //for next/prior #include //for tie -#include +#include #include #include #include diff --git a/include/boost/graph/is_straight_line_drawing.hpp b/include/boost/graph/is_straight_line_drawing.hpp index bff43771..f78fa05c 100644 --- a/include/boost/graph/is_straight_line_drawing.hpp +++ b/include/boost/graph/is_straight_line_drawing.hpp @@ -12,7 +12,7 @@ #include //for next and prior #include #include -#include +#include #include #include diff --git a/include/boost/graph/johnson_all_pairs_shortest.hpp b/include/boost/graph/johnson_all_pairs_shortest.hpp index 4d557724..a8e6fbd4 100644 --- a/include/boost/graph/johnson_all_pairs_shortest.hpp +++ b/include/boost/graph/johnson_all_pairs_shortest.hpp @@ -23,7 +23,7 @@ #define BOOST_GRAPH_JOHNSON_HPP #include -#include +#include #include #include #include diff --git a/include/boost/graph/kolmogorov_max_flow.hpp b/include/boost/graph/kolmogorov_max_flow.hpp index 23a48978..328bd303 100644 --- a/include/boost/graph/kolmogorov_max_flow.hpp +++ b/include/boost/graph/kolmogorov_max_flow.hpp @@ -42,7 +42,7 @@ #include #include -#include +#include #include #include #include diff --git a/include/boost/graph/kruskal_min_spanning_tree.hpp b/include/boost/graph/kruskal_min_spanning_tree.hpp index 50fc8049..a847e3f1 100644 --- a/include/boost/graph/kruskal_min_spanning_tree.hpp +++ b/include/boost/graph/kruskal_min_spanning_tree.hpp @@ -23,7 +23,7 @@ #include #include -#include +#include #include #include #include diff --git a/include/boost/graph/make_biconnected_planar.hpp b/include/boost/graph/make_biconnected_planar.hpp index c5f2b6d5..86a955a6 100644 --- a/include/boost/graph/make_biconnected_planar.hpp +++ b/include/boost/graph/make_biconnected_planar.hpp @@ -11,7 +11,7 @@ #include #include //for tie #include -#include +#include #include #include #include diff --git a/include/boost/graph/make_connected.hpp b/include/boost/graph/make_connected.hpp index 94e57295..6fdbfd25 100644 --- a/include/boost/graph/make_connected.hpp +++ b/include/boost/graph/make_connected.hpp @@ -12,7 +12,7 @@ #include //for next #include //for tie #include -#include +#include #include #include diff --git a/include/boost/graph/make_maximal_planar.hpp b/include/boost/graph/make_maximal_planar.hpp index 458de0a7..8d44afb6 100644 --- a/include/boost/graph/make_maximal_planar.hpp +++ b/include/boost/graph/make_maximal_planar.hpp @@ -11,7 +11,7 @@ #include #include //for tie #include -#include +#include #include #include #include diff --git a/include/boost/graph/max_cardinality_matching.hpp b/include/boost/graph/max_cardinality_matching.hpp index 6656aeaf..ef9ed9e4 100644 --- a/include/boost/graph/max_cardinality_matching.hpp +++ b/include/boost/graph/max_cardinality_matching.hpp @@ -15,7 +15,7 @@ #include #include // for std::sort and std::stable_sort #include // for std::pair -#include +#include #include // for boost::tie #include #include diff --git a/include/boost/graph/minimum_degree_ordering.hpp b/include/boost/graph/minimum_degree_ordering.hpp index 6aa242dc..39c3dcfb 100644 --- a/include/boost/graph/minimum_degree_ordering.hpp +++ b/include/boost/graph/minimum_degree_ordering.hpp @@ -17,7 +17,7 @@ #include #include // for integer_traits #include -#include +#include namespace boost { diff --git a/include/boost/graph/page_rank.hpp b/include/boost/graph/page_rank.hpp index 5f97e14b..f7c38985 100644 --- a/include/boost/graph/page_rank.hpp +++ b/include/boost/graph/page_rank.hpp @@ -11,7 +11,7 @@ #ifndef BOOST_GRAPH_PAGE_RANK_HPP #define BOOST_GRAPH_PAGE_RANK_HPP -#include +#include #include #include #include diff --git a/include/boost/graph/planar_canonical_ordering.hpp b/include/boost/graph/planar_canonical_ordering.hpp index 4211fc84..006b465e 100644 --- a/include/boost/graph/planar_canonical_ordering.hpp +++ b/include/boost/graph/planar_canonical_ordering.hpp @@ -14,7 +14,7 @@ #include #include //for next and prior #include -#include +#include namespace boost diff --git a/include/boost/graph/planar_detail/add_edge_visitors.hpp b/include/boost/graph/planar_detail/add_edge_visitors.hpp index 3ad65b82..96353769 100644 --- a/include/boost/graph/planar_detail/add_edge_visitors.hpp +++ b/include/boost/graph/planar_detail/add_edge_visitors.hpp @@ -8,7 +8,7 @@ #ifndef __ADD_EDGE_VISITORS_HPP__ #define __ADD_EDGE_VISITORS_HPP__ -#include +#include namespace boost { diff --git a/include/boost/graph/planar_detail/boyer_myrvold_impl.hpp b/include/boost/graph/planar_detail/boyer_myrvold_impl.hpp index 1fba01d5..f09caa5d 100644 --- a/include/boost/graph/planar_detail/boyer_myrvold_impl.hpp +++ b/include/boost/graph/planar_detail/boyer_myrvold_impl.hpp @@ -14,7 +14,7 @@ #include //for std::min macros #include #include -#include +#include #include #include #include diff --git a/include/boost/graph/planar_detail/bucket_sort.hpp b/include/boost/graph/planar_detail/bucket_sort.hpp index f0726285..4ec95d8e 100644 --- a/include/boost/graph/planar_detail/bucket_sort.hpp +++ b/include/boost/graph/planar_detail/bucket_sort.hpp @@ -10,7 +10,7 @@ #include #include -#include +#include diff --git a/include/boost/graph/properties.hpp b/include/boost/graph/properties.hpp index 78e52cb0..044e0732 100644 --- a/include/boost/graph/properties.hpp +++ b/include/boost/graph/properties.hpp @@ -12,7 +12,7 @@ #include #include #include -#include +#include #include #include #include @@ -285,7 +285,7 @@ namespace boost { //======================================================================== // Iterator Property Map Generating Functions contributed by // Kevin Vanhorn. (see also the property map generating functions - // in boost/property_map.hpp) + // in boost/property_map/property_map.hpp) #if !defined(BOOST_NO_STD_ITERATOR_TRAITS) // A helper function for creating a vertex property map out of a diff --git a/include/boost/graph/property_iter_range.hpp b/include/boost/graph/property_iter_range.hpp index 69ff7f00..2518ad7b 100644 --- a/include/boost/graph/property_iter_range.hpp +++ b/include/boost/graph/property_iter_range.hpp @@ -18,7 +18,7 @@ #ifndef BOOST_GRAPH_PROPERTY_ITER_RANGE_HPP #define BOOST_GRAPH_PROPERTY_ITER_RANGE_HPP -#include +#include #include #include #include diff --git a/include/boost/graph/property_maps/constant_property_map.hpp b/include/boost/graph/property_maps/constant_property_map.hpp index 99ac72d8..9f7f0394 100644 --- a/include/boost/graph/property_maps/constant_property_map.hpp +++ b/include/boost/graph/property_maps/constant_property_map.hpp @@ -7,7 +7,7 @@ #ifndef BOOST_GRAPH_CONSTANT_PROPERTY_HPP #define BOOST_GRAPH_CONSTANT_PROPERTY_HPP -#include +#include // TODO: This should really be part of the property maps library rather than diff --git a/include/boost/graph/property_maps/container_property_map.hpp b/include/boost/graph/property_maps/container_property_map.hpp index f29e28bb..e07cd330 100644 --- a/include/boost/graph/property_maps/container_property_map.hpp +++ b/include/boost/graph/property_maps/container_property_map.hpp @@ -8,7 +8,7 @@ #define BOOST_GRAPH_CONTAINER_PROPERTY_MAP_HPP #include -#include +#include namespace boost { diff --git a/include/boost/graph/relax.hpp b/include/boost/graph/relax.hpp index 8a23908a..d4d9e841 100644 --- a/include/boost/graph/relax.hpp +++ b/include/boost/graph/relax.hpp @@ -12,7 +12,7 @@ #include #include // for numeric limits #include -#include +#include namespace boost { diff --git a/include/boost/graph/sequential_vertex_coloring.hpp b/include/boost/graph/sequential_vertex_coloring.hpp index 606f2e52..f5362b3c 100644 --- a/include/boost/graph/sequential_vertex_coloring.hpp +++ b/include/boost/graph/sequential_vertex_coloring.hpp @@ -13,7 +13,7 @@ #include #include #include -#include +#include #include #ifdef BOOST_NO_TEMPLATED_ITERATOR_CONSTRUCTORS diff --git a/include/boost/graph/sloan_ordering.hpp b/include/boost/graph/sloan_ordering.hpp index 9011c5b8..ff5748dd 100644 --- a/include/boost/graph/sloan_ordering.hpp +++ b/include/boost/graph/sloan_ordering.hpp @@ -25,7 +25,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/include/boost/graph/stanford_graph.hpp b/include/boost/graph/stanford_graph.hpp index c98bba11..0bb798c0 100644 --- a/include/boost/graph/stanford_graph.hpp +++ b/include/boost/graph/stanford_graph.hpp @@ -12,7 +12,7 @@ #include #include #include -#include +#include #include #include diff --git a/include/boost/graph/topological_sort.hpp b/include/boost/graph/topological_sort.hpp index dc8d9eb7..9a7f6eb8 100644 --- a/include/boost/graph/topological_sort.hpp +++ b/include/boost/graph/topological_sort.hpp @@ -12,7 +12,7 @@ #define BOOST_GRAPH_TOPOLOGICAL_SORT_HPP #include -#include +#include #include #include #include diff --git a/include/boost/graph/two_bit_color_map.hpp b/include/boost/graph/two_bit_color_map.hpp index 7d6ce871..1b2c7705 100644 --- a/include/boost/graph/two_bit_color_map.hpp +++ b/include/boost/graph/two_bit_color_map.hpp @@ -13,7 +13,7 @@ #ifndef BOOST_TWO_BIT_COLOR_MAP_HPP #define BOOST_TWO_BIT_COLOR_MAP_HPP -#include +#include #include #include diff --git a/include/boost/graph/vector_as_graph.hpp b/include/boost/graph/vector_as_graph.hpp index 711b799e..8ca1b916 100644 --- a/include/boost/graph/vector_as_graph.hpp +++ b/include/boost/graph/vector_as_graph.hpp @@ -21,7 +21,7 @@ #include #include #include -#include +#include #include #include diff --git a/include/boost/graph/visitors.hpp b/include/boost/graph/visitors.hpp index 2b88ed06..d42a1f89 100644 --- a/include/boost/graph/visitors.hpp +++ b/include/boost/graph/visitors.hpp @@ -15,7 +15,7 @@ #include #include -#include +#include #include #include #include diff --git a/include/boost/pending/fibonacci_heap.hpp b/include/boost/pending/fibonacci_heap.hpp index dfaae4a4..5fc04187 100644 --- a/include/boost/pending/fibonacci_heap.hpp +++ b/include/boost/pending/fibonacci_heap.hpp @@ -14,7 +14,7 @@ #include #include #include -#include +#include // // An adaptation of Knuth's Fibonacci heap implementation diff --git a/include/boost/pending/indirect_cmp.hpp b/include/boost/pending/indirect_cmp.hpp index c9759493..5e866561 100644 --- a/include/boost/pending/indirect_cmp.hpp +++ b/include/boost/pending/indirect_cmp.hpp @@ -14,7 +14,7 @@ #include #include -#include +#include namespace boost { diff --git a/include/boost/pending/mutable_queue.hpp b/include/boost/pending/mutable_queue.hpp index b0f1073f..a4e2050d 100644 --- a/include/boost/pending/mutable_queue.hpp +++ b/include/boost/pending/mutable_queue.hpp @@ -14,7 +14,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/include/boost/pending/relaxed_heap.hpp b/include/boost/pending/relaxed_heap.hpp index 727009a6..b3ab2ed2 100644 --- a/include/boost/pending/relaxed_heap.hpp +++ b/include/boost/pending/relaxed_heap.hpp @@ -10,7 +10,7 @@ #define BOOST_RELAXED_HEAP_HEADER #include -#include +#include #include #include #include // for CHAR_BIT diff --git a/module.cmake b/module.cmake index 738381c6..6ffdf592 100644 --- a/module.cmake +++ b/module.cmake @@ -1,3 +1,3 @@ boost_module(graph DEPENDS property_map tuple multi_index any random) -# any is there because of the dependency on boost/dynamic_property_map.hpp +# any is there because of the dependency on boost/property_map/dynamic_property_map.hpp diff --git a/test/adjacency_matrix_test.cpp b/test/adjacency_matrix_test.cpp index 7b87e8ac..a3b942a9 100644 --- a/test/adjacency_matrix_test.cpp +++ b/test/adjacency_matrix_test.cpp @@ -16,7 +16,7 @@ * Defines the boost::property_map class template and the boost::get and * boost::put function templates. */ -#include +#include /* * Defines the boost::graph_traits class template. diff --git a/test/all_planar_input_files_test.cpp b/test/all_planar_input_files_test.cpp index c45567d8..b0d5289d 100644 --- a/test/all_planar_input_files_test.cpp +++ b/test/all_planar_input_files_test.cpp @@ -25,7 +25,7 @@ This test needs to be linked against Boost.Filesystem. #include -#include +#include #include #include #include diff --git a/test/basic_planarity_test.cpp b/test/basic_planarity_test.cpp index 793a3d61..cd79591f 100644 --- a/test/basic_planarity_test.cpp +++ b/test/basic_planarity_test.cpp @@ -9,8 +9,8 @@ #include #include #include -#include -#include +#include +#include #include diff --git a/test/betweenness_centrality_test.cpp b/test/betweenness_centrality_test.cpp index 5ec86354..506ccdac 100644 --- a/test/betweenness_centrality_test.cpp +++ b/test/betweenness_centrality_test.cpp @@ -12,7 +12,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/test/core_numbers_test.cpp b/test/core_numbers_test.cpp index 337c285c..0349d8e6 100644 --- a/test/core_numbers_test.cpp +++ b/test/core_numbers_test.cpp @@ -2,7 +2,7 @@ #include #include #include -#include +#include using namespace boost; diff --git a/test/dag_longest_paths.cpp b/test/dag_longest_paths.cpp index 59f64b54..a3793082 100644 --- a/test/dag_longest_paths.cpp +++ b/test/dag_longest_paths.cpp @@ -6,7 +6,7 @@ #include #include -#include +#include #include using namespace boost; diff --git a/test/graphviz_test.cpp b/test/graphviz_test.cpp index 37e6ac48..e2dac5f9 100644 --- a/test/graphviz_test.cpp +++ b/test/graphviz_test.cpp @@ -18,7 +18,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/test/is_straight_line_draw_test.cpp b/test/is_straight_line_draw_test.cpp index 03cc56ac..397ded53 100644 --- a/test/is_straight_line_draw_test.cpp +++ b/test/is_straight_line_draw_test.cpp @@ -6,7 +6,7 @@ // http://www.boost.org/LICENSE_1_0.txt) //======================================================================= -#include +#include #include #include #include diff --git a/test/isomorphism.cpp b/test/isomorphism.cpp index 7e09f452..3650fdbb 100644 --- a/test/isomorphism.cpp +++ b/test/isomorphism.cpp @@ -24,7 +24,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/test/johnson-test.cpp b/test/johnson-test.cpp index c6a469a8..f07eccea 100644 --- a/test/johnson-test.cpp +++ b/test/johnson-test.cpp @@ -27,7 +27,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/test/kolmogorov_max_flow_test.cpp b/test/kolmogorov_max_flow_test.cpp index 5f4b00ae..8786afc0 100644 --- a/test/kolmogorov_max_flow_test.cpp +++ b/test/kolmogorov_max_flow_test.cpp @@ -41,7 +41,7 @@ #include #include #include -#include +#include #include #include diff --git a/test/make_bicon_planar_test.cpp b/test/make_bicon_planar_test.cpp index 13ee0849..55e013a2 100644 --- a/test/make_bicon_planar_test.cpp +++ b/test/make_bicon_planar_test.cpp @@ -11,8 +11,8 @@ #include #include #include -#include -#include +#include +#include #include diff --git a/test/make_connected_test.cpp b/test/make_connected_test.cpp index 3d41e9e8..a33ee9a8 100644 --- a/test/make_connected_test.cpp +++ b/test/make_connected_test.cpp @@ -10,8 +10,8 @@ #include #include #include -#include -#include +#include +#include #include diff --git a/test/make_maximal_planar_test.cpp b/test/make_maximal_planar_test.cpp index 31d3f0e0..341c105e 100644 --- a/test/make_maximal_planar_test.cpp +++ b/test/make_maximal_planar_test.cpp @@ -10,8 +10,8 @@ #include #include #include -#include -#include +#include +#include #include diff --git a/test/matching_test.cpp b/test/matching_test.cpp old mode 100755 new mode 100644 index 7ab742e8..d9a1f8a0 --- a/test/matching_test.cpp +++ b/test/matching_test.cpp @@ -10,7 +10,7 @@ #include #include // for std::cout -#include +#include #include #include #include diff --git a/test/max_flow_test.cpp b/test/max_flow_test.cpp index 02d829de..ec36cdc0 100644 --- a/test/max_flow_test.cpp +++ b/test/max_flow_test.cpp @@ -43,7 +43,7 @@ //boost utilities we use #include #include -#include +#include #include #include diff --git a/test/parallel_edges_loops_test.cpp b/test/parallel_edges_loops_test.cpp index 9ccc6d34..27ccf3ec 100644 --- a/test/parallel_edges_loops_test.cpp +++ b/test/parallel_edges_loops_test.cpp @@ -23,7 +23,7 @@ This test needs to be linked against Boost.Filesystem. #include -#include +#include #include #include #include diff --git a/test/random_matching_test.cpp b/test/random_matching_test.cpp old mode 100755 new mode 100644 index c30ff434..e5d55773 --- a/test/random_matching_test.cpp +++ b/test/random_matching_test.cpp @@ -8,7 +8,7 @@ //======================================================================= #include #include -#include +#include #include #include #include From 0cb233c412dc7f844ddc9600eac698c9b085ba39 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Tue, 7 Apr 2009 15:53:05 +0000 Subject: [PATCH 121/224] Fixed types from bug #2480 [SVN r52228] --- doc/dijkstra_shortest_paths.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/dijkstra_shortest_paths.html b/doc/dijkstra_shortest_paths.html index e80dc8f4..57a1f778 100644 --- a/doc/dijkstra_shortest_paths.html +++ b/doc/dijkstra_shortest_paths.html @@ -80,8 +80,8 @@ record the shortest paths tree in a predecessor map: for each vertex u in V, p[u] will be the predecessor of u in the shortest paths tree (unless p[u] = u, in which case u is either the source or a vertex unreachable from the source). In -addition to these two options, the user can provide there own -custom-made visitor that can takes actions during any of the +addition to these two options, the user can provide their own +custom-made visitor that takes actions during any of the algorithm's event points.

    From 03532e0d20104b805e4f412582557fe4bb40f8bd Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Tue, 7 Apr 2009 16:06:02 +0000 Subject: [PATCH 122/224] Fixes #402 [SVN r52229] --- include/boost/graph/random.hpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/include/boost/graph/random.hpp b/include/boost/graph/random.hpp index 4159a024..bc53b8f3 100644 --- a/include/boost/graph/random.hpp +++ b/include/boost/graph/random.hpp @@ -16,6 +16,7 @@ #include #include +#include #include #include @@ -41,8 +42,7 @@ namespace boost { #endif typename graph_traits::vertex_iterator i = vertices(g).first; - while (n-- > 0) ++i; // std::advance not VC++ portable - return *i; + return *(boost::next(i, n)); } else return *vertices(g).first; } @@ -62,8 +62,7 @@ namespace boost { #endif typename graph_traits::edge_iterator i = edges(g).first; - while (n-- > 0) ++i; // std::advance not VC++ portable - return *i; + return *(boost::next(i, n)); } else return *edges(g).first; } From cd2f3a3a5ced48353575f602bd3f8d5c29618ec4 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Tue, 7 Apr 2009 16:08:58 +0000 Subject: [PATCH 123/224] Applied change from Dementyev Maxim, fixes #2920 [SVN r52230] --- 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 2100b316..f31482a4 100644 --- a/include/boost/graph/read_dimacs.hpp +++ b/include/boost/graph/read_dimacs.hpp @@ -55,7 +55,7 @@ int read_dimacs_max_flow(Graph& g, no_alines=0; /* no of arc-lines */ std::string in_line; /* for reading input line */ - char pr_type[3]; /* for reading type of the problem */ + char pr_type[4]; /* for reading type of the problem */ char nd; /* source (s) or sink (t) */ int k, /* temporary */ From cbbfe23b81b44b86b4b914632036e2ed04fa190e Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Tue, 7 Apr 2009 21:05:25 +0000 Subject: [PATCH 124/224] Added METIS reader test from Nick Edmonds [SVN r52244] --- test/Jamfile.v2 | 3 +++ test/metis_test.cpp | 43 ++++++++++++++++++++++++++++++++++++++++++ test/weighted_graph.gr | 6 ++++++ 3 files changed, 52 insertions(+) create mode 100644 test/metis_test.cpp create mode 100644 test/weighted_graph.gr diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index cfa8bd8b..c1562ee2 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -15,6 +15,8 @@ path-constant PLANAR_INPUT_FILES : ./planar_input_graphs ; path-constant CYCLE_RATIO_INPUT_FILE : ./cycle_ratio_s382.90.dot ; +path-constant METIS_INPUT_FILE : ./weighted_graph.gr ; + if [ modules.peek : EXPAT_INCLUDE ] && [ modules.peek : EXPAT_LIBPATH ] { optional_tests += [ run graphml_test.cpp ../build//boost_graph : : "graphml_test.xml" ] ; @@ -56,6 +58,7 @@ test-suite graph_test : [ run graphviz_test.cpp /boost/test//boost_test_exec_monitor/static ../build//boost_graph ] + [ run metis_test.cpp : $(METIS_INPUT_FILE) ] [ run gursoy_atun_layout_test.cpp ] [ run layout_test.cpp : : : always_show_run_output intel:off ] diff --git a/test/metis_test.cpp b/test/metis_test.cpp new file mode 100644 index 00000000..fd93868b --- /dev/null +++ b/test/metis_test.cpp @@ -0,0 +1,43 @@ +// Copyright (C) 2004-2008 The Trustees of Indiana University. + +// 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 + +#ifdef BOOST_NO_EXCEPTIONS +void +boost::throw_exception(std::exception const& ex) +{ + std::cout << ex.what() << std::endl; + abort(); +} +#endif + +using namespace boost; + +/* An undirected graph with distance values stored on the vertices. */ +typedef adjacency_list > + Graph; + +int main(int argc, char* argv[]) +{ + // Parse command-line options + const char* filename = "weighted_graph.gr"; + if (argc > 1) filename = argv[1]; + + // Open the METIS input file + std::ifstream in(filename); + graph::metis_reader reader(in); + + // Load the graph using the default distribution + Graph g(reader.begin(), reader.end(), + reader.num_vertices()); + + return 0; +} diff --git a/test/weighted_graph.gr b/test/weighted_graph.gr new file mode 100644 index 00000000..1aaa2618 --- /dev/null +++ b/test/weighted_graph.gr @@ -0,0 +1,6 @@ +5 9 1 +3 1 +2 2 4 1 5 2 +2 7 4 3 +5 1 +1 1 2 1 \ No newline at end of file From 0f708da558159e2ad80c26b54743aa707506dcc0 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Thu, 9 Apr 2009 00:48:35 +0000 Subject: [PATCH 125/224] Changed some uses of operator[] to get() to reduce property map requirements [SVN r52273] --- include/boost/graph/johnson_all_pairs_shortest.hpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/include/boost/graph/johnson_all_pairs_shortest.hpp b/include/boost/graph/johnson_all_pairs_shortest.hpp index a8e6fbd4..aafcffc6 100644 --- a/include/boost/graph/johnson_all_pairs_shortest.hpp +++ b/include/boost/graph/johnson_all_pairs_shortest.hpp @@ -99,7 +99,7 @@ namespace boost { iterator_property_map h(h_vec.begin(), id2); for (tie(v, v_end) = vertices(g2); v != v_end; ++v) - d[*v] = inf; + put(d, *v, inf); put(d, s, zero); // Using the non-named parameter versions of bellman_ford and @@ -122,8 +122,8 @@ namespace boost { for (tie(v, v_end) = vertices(g2); v != v_end; ++v) { if (*u != s && *v != s) { typename Traits1::vertex_descriptor u1, v1; - u1 = verts1[id2[*u]]; v1 = verts1[id2[*v]]; - D[id2[*u]-1][id2[*v]-1] = combine(get(d, *v), (get(h, *v) - get(h, *u))); + 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))); } } } From 39ffc159eb80a534284ac9bc433b25fab7444e82 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Thu, 9 Apr 2009 00:48:56 +0000 Subject: [PATCH 126/224] Added dot product [SVN r52274] --- include/boost/graph/topology.hpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/include/boost/graph/topology.hpp b/include/boost/graph/topology.hpp index 8c8262f0..79847137 100644 --- a/include/boost/graph/topology.hpp +++ b/include/boost/graph/topology.hpp @@ -114,6 +114,13 @@ class convex_topology return result; } + friend double dot(const point_difference& a, const point_difference& b) { + double result = 0; + for (std::size_t i = 0; i < Dims; ++i) + result += a[i] * b[i]; + return result; + } + private: double values[Dims]; }; From 809904f268eb719e400fb20a4b62e17c45247066 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Thu, 9 Apr 2009 00:50:23 +0000 Subject: [PATCH 127/224] Added construction of CSR graph from an unsorted list of edges; removed property that targets of out-edges of a single vertex are sorted; removed edge and edge_range functions because they are not supportable under that model; changed tests and docs accordingly [SVN r52275] --- doc/compressed_sparse_row.html | 3901 ++++++++++++++++- .../graph/compressed_sparse_row_graph.hpp | 130 +- test/csr_graph_test.cpp | 49 +- 3 files changed, 3962 insertions(+), 118 deletions(-) diff --git a/doc/compressed_sparse_row.html b/doc/compressed_sparse_row.html index 1ed2639a..c40c22b8 100644 --- a/doc/compressed_sparse_row.html +++ b/doc/compressed_sparse_row.html @@ -1,11 +1,11 @@ Compressed Sparse Row Graph @@ -103,14 +103,27 @@ public: // Graph constructors compressed_sparse_row_graph(); + template<typename MultiPassInputIterator> + compressed_sparse_row_graph(MultiPassInputIterator edge_begin, MultiPassInputIterator edge_end, + vertices_size_type numverts, + const GraphProperty& prop = GraphProperty()); + + template<typename MultiPassInputIterator, typename EdgePropertyIterator> + compressed_sparse_row_graph(MultiPassInputIterator edge_begin, MultiPassInputIterator edge_end, + EdgePropertyIterator ep_iter, + vertices_size_type numverts, + const GraphProperty& prop = GraphProperty()); + template<typename InputIterator> - compressed_sparse_row_graph(InputIterator edge_begin, InputIterator edge_end, + compressed_sparse_row_graph(edges_are_sorted_t, + InputIterator edge_begin, InputIterator edge_end, vertices_size_type numverts, edges_size_type numedges = 0, const GraphProperty& prop = GraphProperty()); template<typename InputIterator, typename EdgePropertyIterator> - compressed_sparse_row_graph(InputIterator edge_begin, InputIterator edge_end, + compressed_sparse_row_graph(edges_are_sorted_t, + InputIterator edge_begin, InputIterator edge_end, EdgePropertyIterator ep_iter, vertices_size_type numverts, edges_size_type numedges = 0, @@ -167,13 +180,6 @@ edges_size_type num_edges(const compressed_sparse_row_graph&); // Vertex access vertex_descriptor vertex(vertices_size_type i, const compressed_sparse_row_graph&); -// Edge access -std::pair<out_edge_iterator, out_edge_iterator> - edge_range(vertex_descriptor u, vertex_descriptor v, const compressed_sparse_row_graph&); -std::pair<edge_descriptor, bool> - edge(vertex_descriptor u, vertex_descriptor v, const compressed_sparse_row_graph&); -edge_descriptor edge_from_index(edges_size_type i, const compressed_sparse_row_graph&); - // Property map accessors template<typename PropertyTag> property_map<compressed_sparse_row_graph, PropertyTag>::type @@ -338,6 +344,3844 @@ edge_descriptor add_vertices(vertex_descriptor src, vert


    +
    
    +  template<typename MultiPassInputIterator>
    +  compressed_sparse_row_graph(MultiPassInputIterator edge_begin, MultiPassInputIterator edge_end,
    +                              vertices_size_type numverts,
    +                              const GraphProperty& prop = GraphProperty());
    +    
    + +

    + Constructs a graph with numverts vertices whose + edges are specified by the iterator range [edge_begin, + edge_end). The MultiPassInputIterator must be a model of + MultiPassInputIterator + whose value_type is an std::pair of + integer values. These integer values are the source and target + vertices for the edges, and must fall within the range [0, + numverts). The edges in [edge_begin, + edge_end) do not need to be sorted. +

    + +

    + The value prop will be used to initialize the graph + property. +

    + +
    + +
    
    +  template<typename MultiPassInputIterator, typename EdgePropertyIterator>
    +  compressed_sparse_row_graph(MultiPassInputIterator edge_begin, MultiPassInputIterator edge_end,
    +                              EdgePropertyIterator ep_iter,
    +                              vertices_size_type numverts,
    +                              const GraphProperty& prop = GraphProperty());
    +    
    +

    + This constructor constructs a graph with numverts + vertices and the edges provided in the iterator range + [edge_begin, edge_end). Its semantics are identical + to the edge range constructor, except + that edge properties are also initialized. The type + EdgePropertyIterator must be a model of the MultiPassInputIterator + concept whose value_type is convertible to + EdgeProperty. The iterator range [ep_iter, ep_ter + + m) will be used to initialize the properties on the edges + of the graph, where m is distance from + edge_begin to edge_end. +

    + +
    + +
    
    +  template<typename InputIterator>
    +  compressed_sparse_row_graph(edges_are_sorted_t,
    +                              InputIterator edge_begin, InputIterator edge_end,
    +                              vertices_size_type numverts,
    +                              edges_size_type numedges = 0,
    +                              const GraphProperty& prop = GraphProperty());
    +    
    + +

    + Constructs a graph with numverts vertices whose + edges are specified by the iterator range [edge_begin, + edge_end). The argument of type edges_are_sorted_t is + a tag used to distinguish this constructor; the value + edges_are_sorted can be used to initialize this parameter. + The InputIterator must be a model of + InputIterator + whose value_type is an std::pair of + integer values. These integer values are the source and target + vertices for the edges, and must fall within the range [0, + numverts). The edges in [edge_begin, + edge_end) must be sorted so that all edges originating + from vertex i preceed any edges originating from all + vertices j where j > i. +

    + +

    + The value numedges, if provided, tells how many + edges are in the range [edge_begin, edge_end) and + will be used to preallocate data structures to save both memory + and time during construction. +

    + +

    + The value prop will be used to initialize the graph + property. +

    + +
    + +
    
    +  template<typename InputIterator, typename EdgePropertyIterator>
    +  compressed_sparse_row_graph(edges_are_sorted_t,
    +                              InputIterator edge_begin, InputIterator edge_end,
    +                              EdgePropertyIterator ep_iter,
    +                              vertices_size_type numverts,
    +                              edges_size_type numedges = 0,
    +                              const GraphProperty& prop = GraphProperty());
    +    
    +

    + This constructor constructs a graph with numverts + vertices and the edges provided in the iterator range + [edge_begin, edge_end). Its semantics are identical + to the edge range constructor, except + that edge properties are also initialized. The type + EdgePropertyIterator must be a model of the InputIterator + concept whose value_type is convertible to + EdgeProperty. The iterator range [ep_iter, ep_ter + + m) will be used to initialize the properties on the edges + of the graph, where m is distance from + edge_begin to edge_end. +

    + +
    + +
    
    +  template<typename InputIterator>
    +  compressed_sparse_row_graph(InputIterator edge_begin, InputIterator edge_end,
    +                              vertices_size_type numverts,
    +                              edges_size_type numedges = 0,
    +                              const GraphProperty& prop = GraphProperty());
    +    
    + +

    + Constructs a graph with numverts vertices whose + edges are specified by the iterator range [edge_begin, + edge_end). The InputIterator must be a model of + InputIterator + whose value_type is an std::pair of + integer values. These integer values are the source and target + vertices for the edges, and must fall within the range [0, + numverts). The edges in [edge_begin, + edge_end) must be sorted so that all edges originating + from vertex i preceed any edges originating from all + vertices j where j > i. +

    + +

    + The value numedges, if provided, tells how many + edges are in the range [edge_begin, edge_end) and + will be used to preallocate data structures to save both memory + and time during construction. +

    + +

    + The value prop will be used to initialize the graph + property. +

    + +
    + +
    
    +  template<typename InputIterator, typename EdgePropertyIterator>
    +  compressed_sparse_row_graph(InputIterator edge_begin, InputIterator edge_end,
    +                              EdgePropertyIterator ep_iter,
    +                              vertices_size_type numverts,
    +                              edges_size_type numedges = 0,
    +                              const GraphProperty& prop = GraphProperty());
    +    
    +

    + This constructor constructs a graph with numverts + vertices and the edges provided in the iterator range + [edge_begin, edge_end). Its semantics are identical + to the edge range constructor, except + that edge properties are also initialized. The type + EdgePropertyIterator must be a model of the InputIterator + concept whose value_type is convertible to + EdgeProperty. The iterator range [ep_iter, ep_ter + + m) will be used to initialize the properties on the edges + of the graph, where m is distance from + edge_begin to edge_end. +

    + +
    + +
    
    +  template<typename InputIterator>
    +  compressed_sparse_row_graph(InputIterator edge_begin, InputIterator edge_end,
    +                              vertices_size_type numverts,
    +                              edges_size_type numedges = 0,
    +                              const GraphProperty& prop = GraphProperty());
    +    
    + +

    + Constructs a graph with numverts vertices whose + edges are specified by the iterator range [edge_begin, + edge_end). The InputIterator must be a model of + InputIterator + whose value_type is an std::pair of + integer values. These integer values are the source and target + vertices for the edges, and must fall within the range [0, + numverts). The edges in [edge_begin, + edge_end) must be sorted so that all edges originating + from vertex i preceed any edges originating from all + vertices j where j > i. +

    + +

    + The value numedges, if provided, tells how many + edges are in the range [edge_begin, edge_end) and + will be used to preallocate data structures to save both memory + and time during construction. +

    + +

    + The value prop will be used to initialize the graph + property. +

    + +
    + +
    
    +  template<typename InputIterator, typename EdgePropertyIterator>
    +  compressed_sparse_row_graph(InputIterator edge_begin, InputIterator edge_end,
    +                              EdgePropertyIterator ep_iter,
    +                              vertices_size_type numverts,
    +                              edges_size_type numedges = 0,
    +                              const GraphProperty& prop = GraphProperty());
    +    
    +

    + This constructor constructs a graph with numverts + vertices and the edges provided in the iterator range + [edge_begin, edge_end). Its semantics are identical + to the edge range constructor, except + that edge properties are also initialized. The type + EdgePropertyIterator must be a model of the InputIterator + concept whose value_type is convertible to + EdgeProperty. The iterator range [ep_iter, ep_ter + + m) will be used to initialize the properties on the edges + of the graph, where m is distance from + edge_begin to edge_end. +

    + +
    + +
    
    +  template<typename InputIterator>
    +  compressed_sparse_row_graph(InputIterator edge_begin, InputIterator edge_end,
    +                              vertices_size_type numverts,
    +                              edges_size_type numedges = 0,
    +                              const GraphProperty& prop = GraphProperty());
    +    
    + +

    + Constructs a graph with numverts vertices whose + edges are specified by the iterator range [edge_begin, + edge_end). The InputIterator must be a model of + InputIterator + whose value_type is an std::pair of + integer values. These integer values are the source and target + vertices for the edges, and must fall within the range [0, + numverts). The edges in [edge_begin, + edge_end) must be sorted so that all edges originating + from vertex i preceed any edges originating from all + vertices j where j > i. +

    + +

    + The value numedges, if provided, tells how many + edges are in the range [edge_begin, edge_end) and + will be used to preallocate data structures to save both memory + and time during construction. +

    + +

    + The value prop will be used to initialize the graph + property. +

    + +
    + +
    
    +  template<typename InputIterator, typename EdgePropertyIterator>
    +  compressed_sparse_row_graph(InputIterator edge_begin, InputIterator edge_end,
    +                              EdgePropertyIterator ep_iter,
    +                              vertices_size_type numverts,
    +                              edges_size_type numedges = 0,
    +                              const GraphProperty& prop = GraphProperty());
    +    
    +

    + This constructor constructs a graph with numverts + vertices and the edges provided in the iterator range + [edge_begin, edge_end). Its semantics are identical + to the edge range constructor, except + that edge properties are also initialized. The type + EdgePropertyIterator must be a model of the InputIterator + concept whose value_type is convertible to + EdgeProperty. The iterator range [ep_iter, ep_ter + + m) will be used to initialize the properties on the edges + of the graph, where m is distance from + edge_begin to edge_end. +

    + +
    + +
    
    +  template<typename InputIterator>
    +  compressed_sparse_row_graph(InputIterator edge_begin, InputIterator edge_end,
    +                              vertices_size_type numverts,
    +                              edges_size_type numedges = 0,
    +                              const GraphProperty& prop = GraphProperty());
    +    
    + +

    + Constructs a graph with numverts vertices whose + edges are specified by the iterator range [edge_begin, + edge_end). The InputIterator must be a model of + InputIterator + whose value_type is an std::pair of + integer values. These integer values are the source and target + vertices for the edges, and must fall within the range [0, + numverts). The edges in [edge_begin, + edge_end) must be sorted so that all edges originating + from vertex i preceed any edges originating from all + vertices j where j > i. +

    + +

    + The value numedges, if provided, tells how many + edges are in the range [edge_begin, edge_end) and + will be used to preallocate data structures to save both memory + and time during construction. +

    + +

    + The value prop will be used to initialize the graph + property. +

    + +
    + +
    
    +  template<typename InputIterator, typename EdgePropertyIterator>
    +  compressed_sparse_row_graph(InputIterator edge_begin, InputIterator edge_end,
    +                              EdgePropertyIterator ep_iter,
    +                              vertices_size_type numverts,
    +                              edges_size_type numedges = 0,
    +                              const GraphProperty& prop = GraphProperty());
    +    
    +

    + This constructor constructs a graph with numverts + vertices and the edges provided in the iterator range + [edge_begin, edge_end). Its semantics are identical + to the edge range constructor, except + that edge properties are also initialized. The type + EdgePropertyIterator must be a model of the InputIterator + concept whose value_type is convertible to + EdgeProperty. The iterator range [ep_iter, ep_ter + + m) will be used to initialize the properties on the edges + of the graph, where m is distance from + edge_begin to edge_end. +

    + +
    + +
    
    +  template<typename InputIterator>
    +  compressed_sparse_row_graph(InputIterator edge_begin, InputIterator edge_end,
    +                              vertices_size_type numverts,
    +                              edges_size_type numedges = 0,
    +                              const GraphProperty& prop = GraphProperty());
    +    
    + +

    + Constructs a graph with numverts vertices whose + edges are specified by the iterator range [edge_begin, + edge_end). The InputIterator must be a model of + InputIterator + whose value_type is an std::pair of + integer values. These integer values are the source and target + vertices for the edges, and must fall within the range [0, + numverts). The edges in [edge_begin, + edge_end) must be sorted so that all edges originating + from vertex i preceed any edges originating from all + vertices j where j > i. +

    + +

    + The value numedges, if provided, tells how many + edges are in the range [edge_begin, edge_end) and + will be used to preallocate data structures to save both memory + and time during construction. +

    + +

    + The value prop will be used to initialize the graph + property. +

    + +
    + +
    
    +  template<typename InputIterator, typename EdgePropertyIterator>
    +  compressed_sparse_row_graph(InputIterator edge_begin, InputIterator edge_end,
    +                              EdgePropertyIterator ep_iter,
    +                              vertices_size_type numverts,
    +                              edges_size_type numedges = 0,
    +                              const GraphProperty& prop = GraphProperty());
    +    
    +

    + This constructor constructs a graph with numverts + vertices and the edges provided in the iterator range + [edge_begin, edge_end). Its semantics are identical + to the edge range constructor, except + that edge properties are also initialized. The type + EdgePropertyIterator must be a model of the InputIterator + concept whose value_type is convertible to + EdgeProperty. The iterator range [ep_iter, ep_ter + + m) will be used to initialize the properties on the edges + of the graph, where m is distance from + edge_begin to edge_end. +

    + +
    + +
    
    +  template<typename InputIterator>
    +  compressed_sparse_row_graph(InputIterator edge_begin, InputIterator edge_end,
    +                              vertices_size_type numverts,
    +                              edges_size_type numedges = 0,
    +                              const GraphProperty& prop = GraphProperty());
    +    
    + +

    + Constructs a graph with numverts vertices whose + edges are specified by the iterator range [edge_begin, + edge_end). The InputIterator must be a model of + InputIterator + whose value_type is an std::pair of + integer values. These integer values are the source and target + vertices for the edges, and must fall within the range [0, + numverts). The edges in [edge_begin, + edge_end) must be sorted so that all edges originating + from vertex i preceed any edges originating from all + vertices j where j > i. +

    + +

    + The value numedges, if provided, tells how many + edges are in the range [edge_begin, edge_end) and + will be used to preallocate data structures to save both memory + and time during construction. +

    + +

    + The value prop will be used to initialize the graph + property. +

    + +
    + +
    
    +  template<typename InputIterator, typename EdgePropertyIterator>
    +  compressed_sparse_row_graph(InputIterator edge_begin, InputIterator edge_end,
    +                              EdgePropertyIterator ep_iter,
    +                              vertices_size_type numverts,
    +                              edges_size_type numedges = 0,
    +                              const GraphProperty& prop = GraphProperty());
    +    
    +

    + This constructor constructs a graph with numverts + vertices and the edges provided in the iterator range + [edge_begin, edge_end). Its semantics are identical + to the edge range constructor, except + that edge properties are also initialized. The type + EdgePropertyIterator must be a model of the InputIterator + concept whose value_type is convertible to + EdgeProperty. The iterator range [ep_iter, ep_ter + + m) will be used to initialize the properties on the edges + of the graph, where m is distance from + edge_begin to edge_end. +

    + +
    + +
    
    +  template<typename InputIterator>
    +  compressed_sparse_row_graph(InputIterator edge_begin, InputIterator edge_end,
    +                              vertices_size_type numverts,
    +                              edges_size_type numedges = 0,
    +                              const GraphProperty& prop = GraphProperty());
    +    
    + +

    + Constructs a graph with numverts vertices whose + edges are specified by the iterator range [edge_begin, + edge_end). The InputIterator must be a model of + InputIterator + whose value_type is an std::pair of + integer values. These integer values are the source and target + vertices for the edges, and must fall within the range [0, + numverts). The edges in [edge_begin, + edge_end) must be sorted so that all edges originating + from vertex i preceed any edges originating from all + vertices j where j > i. +

    + +

    + The value numedges, if provided, tells how many + edges are in the range [edge_begin, edge_end) and + will be used to preallocate data structures to save both memory + and time during construction. +

    + +

    + The value prop will be used to initialize the graph + property. +

    + +
    + +
    
    +  template<typename InputIterator, typename EdgePropertyIterator>
    +  compressed_sparse_row_graph(InputIterator edge_begin, InputIterator edge_end,
    +                              EdgePropertyIterator ep_iter,
    +                              vertices_size_type numverts,
    +                              edges_size_type numedges = 0,
    +                              const GraphProperty& prop = GraphProperty());
    +    
    +

    + This constructor constructs a graph with numverts + vertices and the edges provided in the iterator range + [edge_begin, edge_end). Its semantics are identical + to the edge range constructor, except + that edge properties are also initialized. The type + EdgePropertyIterator must be a model of the InputIterator + concept whose value_type is convertible to + EdgeProperty. The iterator range [ep_iter, ep_ter + + m) will be used to initialize the properties on the edges + of the graph, where m is distance from + edge_begin to edge_end. +

    + +
    + +
    
    +  template<typename InputIterator>
    +  compressed_sparse_row_graph(InputIterator edge_begin, InputIterator edge_end,
    +                              vertices_size_type numverts,
    +                              edges_size_type numedges = 0,
    +                              const GraphProperty& prop = GraphProperty());
    +    
    + +

    + Constructs a graph with numverts vertices whose + edges are specified by the iterator range [edge_begin, + edge_end). The InputIterator must be a model of + InputIterator + whose value_type is an std::pair of + integer values. These integer values are the source and target + vertices for the edges, and must fall within the range [0, + numverts). The edges in [edge_begin, + edge_end) must be sorted so that all edges originating + from vertex i preceed any edges originating from all + vertices j where j > i. +

    + +

    + The value numedges, if provided, tells how many + edges are in the range [edge_begin, edge_end) and + will be used to preallocate data structures to save both memory + and time during construction. +

    + +

    + The value prop will be used to initialize the graph + property. +

    + +
    + +
    
    +  template<typename InputIterator, typename EdgePropertyIterator>
    +  compressed_sparse_row_graph(InputIterator edge_begin, InputIterator edge_end,
    +                              EdgePropertyIterator ep_iter,
    +                              vertices_size_type numverts,
    +                              edges_size_type numedges = 0,
    +                              const GraphProperty& prop = GraphProperty());
    +    
    +

    + This constructor constructs a graph with numverts + vertices and the edges provided in the iterator range + [edge_begin, edge_end). Its semantics are identical + to the edge range constructor, except + that edge properties are also initialized. The type + EdgePropertyIterator must be a model of the InputIterator + concept whose value_type is convertible to + EdgeProperty. The iterator range [ep_iter, ep_ter + + m) will be used to initialize the properties on the edges + of the graph, where m is distance from + edge_begin to edge_end. +

    + +
    + +
    
    +  template<typename InputIterator>
    +  compressed_sparse_row_graph(InputIterator edge_begin, InputIterator edge_end,
    +                              vertices_size_type numverts,
    +                              edges_size_type numedges = 0,
    +                              const GraphProperty& prop = GraphProperty());
    +    
    + +

    + Constructs a graph with numverts vertices whose + edges are specified by the iterator range [edge_begin, + edge_end). The InputIterator must be a model of + InputIterator + whose value_type is an std::pair of + integer values. These integer values are the source and target + vertices for the edges, and must fall within the range [0, + numverts). The edges in [edge_begin, + edge_end) must be sorted so that all edges originating + from vertex i preceed any edges originating from all + vertices j where j > i. +

    + +

    + The value numedges, if provided, tells how many + edges are in the range [edge_begin, edge_end) and + will be used to preallocate data structures to save both memory + and time during construction. +

    + +

    + The value prop will be used to initialize the graph + property. +

    + +
    + +
    
    +  template<typename InputIterator, typename EdgePropertyIterator>
    +  compressed_sparse_row_graph(InputIterator edge_begin, InputIterator edge_end,
    +                              EdgePropertyIterator ep_iter,
    +                              vertices_size_type numverts,
    +                              edges_size_type numedges = 0,
    +                              const GraphProperty& prop = GraphProperty());
    +    
    +

    + This constructor constructs a graph with numverts + vertices and the edges provided in the iterator range + [edge_begin, edge_end). Its semantics are identical + to the edge range constructor, except + that edge properties are also initialized. The type + EdgePropertyIterator must be a model of the InputIterator + concept whose value_type is convertible to + EdgeProperty. The iterator range [ep_iter, ep_ter + + m) will be used to initialize the properties on the edges + of the graph, where m is distance from + edge_begin to edge_end. +

    + +
    + +
    
    +  template<typename InputIterator>
    +  compressed_sparse_row_graph(InputIterator edge_begin, InputIterator edge_end,
    +                              vertices_size_type numverts,
    +                              edges_size_type numedges = 0,
    +                              const GraphProperty& prop = GraphProperty());
    +    
    + +

    + Constructs a graph with numverts vertices whose + edges are specified by the iterator range [edge_begin, + edge_end). The InputIterator must be a model of + InputIterator + whose value_type is an std::pair of + integer values. These integer values are the source and target + vertices for the edges, and must fall within the range [0, + numverts). The edges in [edge_begin, + edge_end) must be sorted so that all edges originating + from vertex i preceed any edges originating from all + vertices j where j > i. +

    + +

    + The value numedges, if provided, tells how many + edges are in the range [edge_begin, edge_end) and + will be used to preallocate data structures to save both memory + and time during construction. +

    + +

    + The value prop will be used to initialize the graph + property. +

    + +
    + +
    
    +  template<typename InputIterator, typename EdgePropertyIterator>
    +  compressed_sparse_row_graph(InputIterator edge_begin, InputIterator edge_end,
    +                              EdgePropertyIterator ep_iter,
    +                              vertices_size_type numverts,
    +                              edges_size_type numedges = 0,
    +                              const GraphProperty& prop = GraphProperty());
    +    
    +

    + This constructor constructs a graph with numverts + vertices and the edges provided in the iterator range + [edge_begin, edge_end). Its semantics are identical + to the edge range constructor, except + that edge properties are also initialized. The type + EdgePropertyIterator must be a model of the InputIterator + concept whose value_type is convertible to + EdgeProperty. The iterator range [ep_iter, ep_ter + + m) will be used to initialize the properties on the edges + of the graph, where m is distance from + edge_begin to edge_end. +

    + +
    + +
    
    +  template<typename InputIterator>
    +  compressed_sparse_row_graph(InputIterator edge_begin, InputIterator edge_end,
    +                              vertices_size_type numverts,
    +                              edges_size_type numedges = 0,
    +                              const GraphProperty& prop = GraphProperty());
    +    
    + +

    + Constructs a graph with numverts vertices whose + edges are specified by the iterator range [edge_begin, + edge_end). The InputIterator must be a model of + InputIterator + whose value_type is an std::pair of + integer values. These integer values are the source and target + vertices for the edges, and must fall within the range [0, + numverts). The edges in [edge_begin, + edge_end) must be sorted so that all edges originating + from vertex i preceed any edges originating from all + vertices j where j > i. +

    + +

    + The value numedges, if provided, tells how many + edges are in the range [edge_begin, edge_end) and + will be used to preallocate data structures to save both memory + and time during construction. +

    + +

    + The value prop will be used to initialize the graph + property. +

    + +
    + +
    
    +  template<typename InputIterator, typename EdgePropertyIterator>
    +  compressed_sparse_row_graph(InputIterator edge_begin, InputIterator edge_end,
    +                              EdgePropertyIterator ep_iter,
    +                              vertices_size_type numverts,
    +                              edges_size_type numedges = 0,
    +                              const GraphProperty& prop = GraphProperty());
    +    
    +

    + This constructor constructs a graph with numverts + vertices and the edges provided in the iterator range + [edge_begin, edge_end). Its semantics are identical + to the edge range constructor, except + that edge properties are also initialized. The type + EdgePropertyIterator must be a model of the InputIterator + concept whose value_type is convertible to + EdgeProperty. The iterator range [ep_iter, ep_ter + + m) will be used to initialize the properties on the edges + of the graph, where m is distance from + edge_begin to edge_end. +

    + +
    + +
    
    +  template<typename InputIterator>
    +  compressed_sparse_row_graph(InputIterator edge_begin, InputIterator edge_end,
    +                              vertices_size_type numverts,
    +                              edges_size_type numedges = 0,
    +                              const GraphProperty& prop = GraphProperty());
    +    
    + +

    + Constructs a graph with numverts vertices whose + edges are specified by the iterator range [edge_begin, + edge_end). The InputIterator must be a model of + InputIterator + whose value_type is an std::pair of + integer values. These integer values are the source and target + vertices for the edges, and must fall within the range [0, + numverts). The edges in [edge_begin, + edge_end) must be sorted so that all edges originating + from vertex i preceed any edges originating from all + vertices j where j > i. +

    + +

    + The value numedges, if provided, tells how many + edges are in the range [edge_begin, edge_end) and + will be used to preallocate data structures to save both memory + and time during construction. +

    + +

    + The value prop will be used to initialize the graph + property. +

    + +
    + +
    
    +  template<typename InputIterator, typename EdgePropertyIterator>
    +  compressed_sparse_row_graph(InputIterator edge_begin, InputIterator edge_end,
    +                              EdgePropertyIterator ep_iter,
    +                              vertices_size_type numverts,
    +                              edges_size_type numedges = 0,
    +                              const GraphProperty& prop = GraphProperty());
    +    
    +

    + This constructor constructs a graph with numverts + vertices and the edges provided in the iterator range + [edge_begin, edge_end). Its semantics are identical + to the edge range constructor, except + that edge properties are also initialized. The type + EdgePropertyIterator must be a model of the InputIterator + concept whose value_type is convertible to + EdgeProperty. The iterator range [ep_iter, ep_ter + + m) will be used to initialize the properties on the edges + of the graph, where m is distance from + edge_begin to edge_end. +

    + +
    + +
    
    +  template<typename InputIterator>
    +  compressed_sparse_row_graph(InputIterator edge_begin, InputIterator edge_end,
    +                              vertices_size_type numverts,
    +                              edges_size_type numedges = 0,
    +                              const GraphProperty& prop = GraphProperty());
    +    
    + +

    + Constructs a graph with numverts vertices whose + edges are specified by the iterator range [edge_begin, + edge_end). The InputIterator must be a model of + InputIterator + whose value_type is an std::pair of + integer values. These integer values are the source and target + vertices for the edges, and must fall within the range [0, + numverts). The edges in [edge_begin, + edge_end) must be sorted so that all edges originating + from vertex i preceed any edges originating from all + vertices j where j > i. +

    + +

    + The value numedges, if provided, tells how many + edges are in the range [edge_begin, edge_end) and + will be used to preallocate data structures to save both memory + and time during construction. +

    + +

    + The value prop will be used to initialize the graph + property. +

    + +
    + +
    
    +  template<typename InputIterator, typename EdgePropertyIterator>
    +  compressed_sparse_row_graph(InputIterator edge_begin, InputIterator edge_end,
    +                              EdgePropertyIterator ep_iter,
    +                              vertices_size_type numverts,
    +                              edges_size_type numedges = 0,
    +                              const GraphProperty& prop = GraphProperty());
    +    
    +

    + This constructor constructs a graph with numverts + vertices and the edges provided in the iterator range + [edge_begin, edge_end). Its semantics are identical + to the edge range constructor, except + that edge properties are also initialized. The type + EdgePropertyIterator must be a model of the InputIterator + concept whose value_type is convertible to + EdgeProperty. The iterator range [ep_iter, ep_ter + + m) will be used to initialize the properties on the edges + of the graph, where m is distance from + edge_begin to edge_end. +

    + +
    + +
    
    +  template<typename InputIterator>
    +  compressed_sparse_row_graph(InputIterator edge_begin, InputIterator edge_end,
    +                              vertices_size_type numverts,
    +                              edges_size_type numedges = 0,
    +                              const GraphProperty& prop = GraphProperty());
    +    
    + +

    + Constructs a graph with numverts vertices whose + edges are specified by the iterator range [edge_begin, + edge_end). The InputIterator must be a model of + InputIterator + whose value_type is an std::pair of + integer values. These integer values are the source and target + vertices for the edges, and must fall within the range [0, + numverts). The edges in [edge_begin, + edge_end) must be sorted so that all edges originating + from vertex i preceed any edges originating from all + vertices j where j > i. +

    + +

    + The value numedges, if provided, tells how many + edges are in the range [edge_begin, edge_end) and + will be used to preallocate data structures to save both memory + and time during construction. +

    + +

    + The value prop will be used to initialize the graph + property. +

    + +
    + +
    
    +  template<typename InputIterator, typename EdgePropertyIterator>
    +  compressed_sparse_row_graph(InputIterator edge_begin, InputIterator edge_end,
    +                              EdgePropertyIterator ep_iter,
    +                              vertices_size_type numverts,
    +                              edges_size_type numedges = 0,
    +                              const GraphProperty& prop = GraphProperty());
    +    
    +

    + This constructor constructs a graph with numverts + vertices and the edges provided in the iterator range + [edge_begin, edge_end). Its semantics are identical + to the edge range constructor, except + that edge properties are also initialized. The type + EdgePropertyIterator must be a model of the InputIterator + concept whose value_type is convertible to + EdgeProperty. The iterator range [ep_iter, ep_ter + + m) will be used to initialize the properties on the edges + of the graph, where m is distance from + edge_begin to edge_end. +

    + +
    + +
    
    +  template<typename InputIterator>
    +  compressed_sparse_row_graph(InputIterator edge_begin, InputIterator edge_end,
    +                              vertices_size_type numverts,
    +                              edges_size_type numedges = 0,
    +                              const GraphProperty& prop = GraphProperty());
    +    
    + +

    + Constructs a graph with numverts vertices whose + edges are specified by the iterator range [edge_begin, + edge_end). The InputIterator must be a model of + InputIterator + whose value_type is an std::pair of + integer values. These integer values are the source and target + vertices for the edges, and must fall within the range [0, + numverts). The edges in [edge_begin, + edge_end) must be sorted so that all edges originating + from vertex i preceed any edges originating from all + vertices j where j > i. +

    + +

    + The value numedges, if provided, tells how many + edges are in the range [edge_begin, edge_end) and + will be used to preallocate data structures to save both memory + and time during construction. +

    + +

    + The value prop will be used to initialize the graph + property. +

    + +
    + +
    
    +  template<typename InputIterator, typename EdgePropertyIterator>
    +  compressed_sparse_row_graph(InputIterator edge_begin, InputIterator edge_end,
    +                              EdgePropertyIterator ep_iter,
    +                              vertices_size_type numverts,
    +                              edges_size_type numedges = 0,
    +                              const GraphProperty& prop = GraphProperty());
    +    
    +

    + This constructor constructs a graph with numverts + vertices and the edges provided in the iterator range + [edge_begin, edge_end). Its semantics are identical + to the edge range constructor, except + that edge properties are also initialized. The type + EdgePropertyIterator must be a model of the InputIterator + concept whose value_type is convertible to + EdgeProperty. The iterator range [ep_iter, ep_ter + + m) will be used to initialize the properties on the edges + of the graph, where m is distance from + edge_begin to edge_end. +

    + +
    + +
    
    +  template<typename InputIterator>
    +  compressed_sparse_row_graph(InputIterator edge_begin, InputIterator edge_end,
    +                              vertices_size_type numverts,
    +                              edges_size_type numedges = 0,
    +                              const GraphProperty& prop = GraphProperty());
    +    
    + +

    + Constructs a graph with numverts vertices whose + edges are specified by the iterator range [edge_begin, + edge_end). The InputIterator must be a model of + InputIterator + whose value_type is an std::pair of + integer values. These integer values are the source and target + vertices for the edges, and must fall within the range [0, + numverts). The edges in [edge_begin, + edge_end) must be sorted so that all edges originating + from vertex i preceed any edges originating from all + vertices j where j > i. +

    + +

    + The value numedges, if provided, tells how many + edges are in the range [edge_begin, edge_end) and + will be used to preallocate data structures to save both memory + and time during construction. +

    + +

    + The value prop will be used to initialize the graph + property. +

    + +
    + +
    
    +  template<typename InputIterator, typename EdgePropertyIterator>
    +  compressed_sparse_row_graph(InputIterator edge_begin, InputIterator edge_end,
    +                              EdgePropertyIterator ep_iter,
    +                              vertices_size_type numverts,
    +                              edges_size_type numedges = 0,
    +                              const GraphProperty& prop = GraphProperty());
    +    
    +

    + This constructor constructs a graph with numverts + vertices and the edges provided in the iterator range + [edge_begin, edge_end). Its semantics are identical + to the edge range constructor, except + that edge properties are also initialized. The type + EdgePropertyIterator must be a model of the InputIterator + concept whose value_type is convertible to + EdgeProperty. The iterator range [ep_iter, ep_ter + + m) will be used to initialize the properties on the edges + of the graph, where m is distance from + edge_begin to edge_end. +

    + +
    + +
    
    +  template<typename InputIterator>
    +  compressed_sparse_row_graph(InputIterator edge_begin, InputIterator edge_end,
    +                              vertices_size_type numverts,
    +                              edges_size_type numedges = 0,
    +                              const GraphProperty& prop = GraphProperty());
    +    
    + +

    + Constructs a graph with numverts vertices whose + edges are specified by the iterator range [edge_begin, + edge_end). The InputIterator must be a model of + InputIterator + whose value_type is an std::pair of + integer values. These integer values are the source and target + vertices for the edges, and must fall within the range [0, + numverts). The edges in [edge_begin, + edge_end) must be sorted so that all edges originating + from vertex i preceed any edges originating from all + vertices j where j > i. +

    + +

    + The value numedges, if provided, tells how many + edges are in the range [edge_begin, edge_end) and + will be used to preallocate data structures to save both memory + and time during construction. +

    + +

    + The value prop will be used to initialize the graph + property. +

    + +
    + +
    
    +  template<typename InputIterator, typename EdgePropertyIterator>
    +  compressed_sparse_row_graph(InputIterator edge_begin, InputIterator edge_end,
    +                              EdgePropertyIterator ep_iter,
    +                              vertices_size_type numverts,
    +                              edges_size_type numedges = 0,
    +                              const GraphProperty& prop = GraphProperty());
    +    
    +

    + This constructor constructs a graph with numverts + vertices and the edges provided in the iterator range + [edge_begin, edge_end). Its semantics are identical + to the edge range constructor, except + that edge properties are also initialized. The type + EdgePropertyIterator must be a model of the InputIterator + concept whose value_type is convertible to + EdgeProperty. The iterator range [ep_iter, ep_ter + + m) will be used to initialize the properties on the edges + of the graph, where m is distance from + edge_begin to edge_end. +

    + +
    + +
    
    +  template<typename InputIterator>
    +  compressed_sparse_row_graph(InputIterator edge_begin, InputIterator edge_end,
    +                              vertices_size_type numverts,
    +                              edges_size_type numedges = 0,
    +                              const GraphProperty& prop = GraphProperty());
    +    
    + +

    + Constructs a graph with numverts vertices whose + edges are specified by the iterator range [edge_begin, + edge_end). The InputIterator must be a model of + InputIterator + whose value_type is an std::pair of + integer values. These integer values are the source and target + vertices for the edges, and must fall within the range [0, + numverts). The edges in [edge_begin, + edge_end) must be sorted so that all edges originating + from vertex i preceed any edges originating from all + vertices j where j > i. +

    + +

    + The value numedges, if provided, tells how many + edges are in the range [edge_begin, edge_end) and + will be used to preallocate data structures to save both memory + and time during construction. +

    + +

    + The value prop will be used to initialize the graph + property. +

    + +
    + +
    
    +  template<typename InputIterator, typename EdgePropertyIterator>
    +  compressed_sparse_row_graph(InputIterator edge_begin, InputIterator edge_end,
    +                              EdgePropertyIterator ep_iter,
    +                              vertices_size_type numverts,
    +                              edges_size_type numedges = 0,
    +                              const GraphProperty& prop = GraphProperty());
    +    
    +

    + This constructor constructs a graph with numverts + vertices and the edges provided in the iterator range + [edge_begin, edge_end). Its semantics are identical + to the edge range constructor, except + that edge properties are also initialized. The type + EdgePropertyIterator must be a model of the InputIterator + concept whose value_type is convertible to + EdgeProperty. The iterator range [ep_iter, ep_ter + + m) will be used to initialize the properties on the edges + of the graph, where m is distance from + edge_begin to edge_end. +

    + +
    + +
    
    +  template<typename InputIterator>
    +  compressed_sparse_row_graph(InputIterator edge_begin, InputIterator edge_end,
    +                              vertices_size_type numverts,
    +                              edges_size_type numedges = 0,
    +                              const GraphProperty& prop = GraphProperty());
    +    
    + +

    + Constructs a graph with numverts vertices whose + edges are specified by the iterator range [edge_begin, + edge_end). The InputIterator must be a model of + InputIterator + whose value_type is an std::pair of + integer values. These integer values are the source and target + vertices for the edges, and must fall within the range [0, + numverts). The edges in [edge_begin, + edge_end) must be sorted so that all edges originating + from vertex i preceed any edges originating from all + vertices j where j > i. +

    + +

    + The value numedges, if provided, tells how many + edges are in the range [edge_begin, edge_end) and + will be used to preallocate data structures to save both memory + and time during construction. +

    + +

    + The value prop will be used to initialize the graph + property. +

    + +
    + +
    
    +  template<typename InputIterator, typename EdgePropertyIterator>
    +  compressed_sparse_row_graph(InputIterator edge_begin, InputIterator edge_end,
    +                              EdgePropertyIterator ep_iter,
    +                              vertices_size_type numverts,
    +                              edges_size_type numedges = 0,
    +                              const GraphProperty& prop = GraphProperty());
    +    
    +

    + This constructor constructs a graph with numverts + vertices and the edges provided in the iterator range + [edge_begin, edge_end). Its semantics are identical + to the edge range constructor, except + that edge properties are also initialized. The type + EdgePropertyIterator must be a model of the InputIterator + concept whose value_type is convertible to + EdgeProperty. The iterator range [ep_iter, ep_ter + + m) will be used to initialize the properties on the edges + of the graph, where m is distance from + edge_begin to edge_end. +

    + +
    + +
    
    +  template<typename InputIterator>
    +  compressed_sparse_row_graph(InputIterator edge_begin, InputIterator edge_end,
    +                              vertices_size_type numverts,
    +                              edges_size_type numedges = 0,
    +                              const GraphProperty& prop = GraphProperty());
    +    
    + +

    + Constructs a graph with numverts vertices whose + edges are specified by the iterator range [edge_begin, + edge_end). The InputIterator must be a model of + InputIterator + whose value_type is an std::pair of + integer values. These integer values are the source and target + vertices for the edges, and must fall within the range [0, + numverts). The edges in [edge_begin, + edge_end) must be sorted so that all edges originating + from vertex i preceed any edges originating from all + vertices j where j > i. +

    + +

    + The value numedges, if provided, tells how many + edges are in the range [edge_begin, edge_end) and + will be used to preallocate data structures to save both memory + and time during construction. +

    + +

    + The value prop will be used to initialize the graph + property. +

    + +
    + +
    
    +  template<typename InputIterator, typename EdgePropertyIterator>
    +  compressed_sparse_row_graph(InputIterator edge_begin, InputIterator edge_end,
    +                              EdgePropertyIterator ep_iter,
    +                              vertices_size_type numverts,
    +                              edges_size_type numedges = 0,
    +                              const GraphProperty& prop = GraphProperty());
    +    
    +

    + This constructor constructs a graph with numverts + vertices and the edges provided in the iterator range + [edge_begin, edge_end). Its semantics are identical + to the edge range constructor, except + that edge properties are also initialized. The type + EdgePropertyIterator must be a model of the InputIterator + concept whose value_type is convertible to + EdgeProperty. The iterator range [ep_iter, ep_ter + + m) will be used to initialize the properties on the edges + of the graph, where m is distance from + edge_begin to edge_end. +

    + +
    + +
    
    +  template<typename InputIterator>
    +  compressed_sparse_row_graph(InputIterator edge_begin, InputIterator edge_end,
    +                              vertices_size_type numverts,
    +                              edges_size_type numedges = 0,
    +                              const GraphProperty& prop = GraphProperty());
    +    
    + +

    + Constructs a graph with numverts vertices whose + edges are specified by the iterator range [edge_begin, + edge_end). The InputIterator must be a model of + InputIterator + whose value_type is an std::pair of + integer values. These integer values are the source and target + vertices for the edges, and must fall within the range [0, + numverts). The edges in [edge_begin, + edge_end) must be sorted so that all edges originating + from vertex i preceed any edges originating from all + vertices j where j > i. +

    + +

    + The value numedges, if provided, tells how many + edges are in the range [edge_begin, edge_end) and + will be used to preallocate data structures to save both memory + and time during construction. +

    + +

    + The value prop will be used to initialize the graph + property. +

    + +
    + +
    
    +  template<typename InputIterator, typename EdgePropertyIterator>
    +  compressed_sparse_row_graph(InputIterator edge_begin, InputIterator edge_end,
    +                              EdgePropertyIterator ep_iter,
    +                              vertices_size_type numverts,
    +                              edges_size_type numedges = 0,
    +                              const GraphProperty& prop = GraphProperty());
    +    
    +

    + This constructor constructs a graph with numverts + vertices and the edges provided in the iterator range + [edge_begin, edge_end). Its semantics are identical + to the edge range constructor, except + that edge properties are also initialized. The type + EdgePropertyIterator must be a model of the InputIterator + concept whose value_type is convertible to + EdgeProperty. The iterator range [ep_iter, ep_ter + + m) will be used to initialize the properties on the edges + of the graph, where m is distance from + edge_begin to edge_end. +

    + +
    + +
    
    +  template<typename InputIterator>
    +  compressed_sparse_row_graph(InputIterator edge_begin, InputIterator edge_end,
    +                              vertices_size_type numverts,
    +                              edges_size_type numedges = 0,
    +                              const GraphProperty& prop = GraphProperty());
    +    
    + +

    + Constructs a graph with numverts vertices whose + edges are specified by the iterator range [edge_begin, + edge_end). The InputIterator must be a model of + InputIterator + whose value_type is an std::pair of + integer values. These integer values are the source and target + vertices for the edges, and must fall within the range [0, + numverts). The edges in [edge_begin, + edge_end) must be sorted so that all edges originating + from vertex i preceed any edges originating from all + vertices j where j > i. +

    + +

    + The value numedges, if provided, tells how many + edges are in the range [edge_begin, edge_end) and + will be used to preallocate data structures to save both memory + and time during construction. +

    + +

    + The value prop will be used to initialize the graph + property. +

    + +
    + +
    
    +  template<typename InputIterator, typename EdgePropertyIterator>
    +  compressed_sparse_row_graph(InputIterator edge_begin, InputIterator edge_end,
    +                              EdgePropertyIterator ep_iter,
    +                              vertices_size_type numverts,
    +                              edges_size_type numedges = 0,
    +                              const GraphProperty& prop = GraphProperty());
    +    
    +

    + This constructor constructs a graph with numverts + vertices and the edges provided in the iterator range + [edge_begin, edge_end). Its semantics are identical + to the edge range constructor, except + that edge properties are also initialized. The type + EdgePropertyIterator must be a model of the InputIterator + concept whose value_type is convertible to + EdgeProperty. The iterator range [ep_iter, ep_ter + + m) will be used to initialize the properties on the edges + of the graph, where m is distance from + edge_begin to edge_end. +

    + +
    + +
    
    +  template<typename InputIterator>
    +  compressed_sparse_row_graph(InputIterator edge_begin, InputIterator edge_end,
    +                              vertices_size_type numverts,
    +                              edges_size_type numedges = 0,
    +                              const GraphProperty& prop = GraphProperty());
    +    
    + +

    + Constructs a graph with numverts vertices whose + edges are specified by the iterator range [edge_begin, + edge_end). The InputIterator must be a model of + InputIterator + whose value_type is an std::pair of + integer values. These integer values are the source and target + vertices for the edges, and must fall within the range [0, + numverts). The edges in [edge_begin, + edge_end) must be sorted so that all edges originating + from vertex i preceed any edges originating from all + vertices j where j > i. +

    + +

    + The value numedges, if provided, tells how many + edges are in the range [edge_begin, edge_end) and + will be used to preallocate data structures to save both memory + and time during construction. +

    + +

    + The value prop will be used to initialize the graph + property. +

    + +
    + +
    
    +  template<typename InputIterator, typename EdgePropertyIterator>
    +  compressed_sparse_row_graph(InputIterator edge_begin, InputIterator edge_end,
    +                              EdgePropertyIterator ep_iter,
    +                              vertices_size_type numverts,
    +                              edges_size_type numedges = 0,
    +                              const GraphProperty& prop = GraphProperty());
    +    
    +

    + This constructor constructs a graph with numverts + vertices and the edges provided in the iterator range + [edge_begin, edge_end). Its semantics are identical + to the edge range constructor, except + that edge properties are also initialized. The type + EdgePropertyIterator must be a model of the InputIterator + concept whose value_type is convertible to + EdgeProperty. The iterator range [ep_iter, ep_ter + + m) will be used to initialize the properties on the edges + of the graph, where m is distance from + edge_begin to edge_end. +

    + +
    + +
    
    +  template<typename InputIterator>
    +  compressed_sparse_row_graph(InputIterator edge_begin, InputIterator edge_end,
    +                              vertices_size_type numverts,
    +                              edges_size_type numedges = 0,
    +                              const GraphProperty& prop = GraphProperty());
    +    
    + +

    + Constructs a graph with numverts vertices whose + edges are specified by the iterator range [edge_begin, + edge_end). The InputIterator must be a model of + InputIterator + whose value_type is an std::pair of + integer values. These integer values are the source and target + vertices for the edges, and must fall within the range [0, + numverts). The edges in [edge_begin, + edge_end) must be sorted so that all edges originating + from vertex i preceed any edges originating from all + vertices j where j > i. +

    + +

    + The value numedges, if provided, tells how many + edges are in the range [edge_begin, edge_end) and + will be used to preallocate data structures to save both memory + and time during construction. +

    + +

    + The value prop will be used to initialize the graph + property. +

    + +
    + +
    
    +  template<typename InputIterator, typename EdgePropertyIterator>
    +  compressed_sparse_row_graph(InputIterator edge_begin, InputIterator edge_end,
    +                              EdgePropertyIterator ep_iter,
    +                              vertices_size_type numverts,
    +                              edges_size_type numedges = 0,
    +                              const GraphProperty& prop = GraphProperty());
    +    
    +

    + This constructor constructs a graph with numverts + vertices and the edges provided in the iterator range + [edge_begin, edge_end). Its semantics are identical + to the edge range constructor, except + that edge properties are also initialized. The type + EdgePropertyIterator must be a model of the InputIterator + concept whose value_type is convertible to + EdgeProperty. The iterator range [ep_iter, ep_ter + + m) will be used to initialize the properties on the edges + of the graph, where m is distance from + edge_begin to edge_end. +

    + +
    + +
    
    +  template<typename InputIterator>
    +  compressed_sparse_row_graph(InputIterator edge_begin, InputIterator edge_end,
    +                              vertices_size_type numverts,
    +                              edges_size_type numedges = 0,
    +                              const GraphProperty& prop = GraphProperty());
    +    
    + +

    + Constructs a graph with numverts vertices whose + edges are specified by the iterator range [edge_begin, + edge_end). The InputIterator must be a model of + InputIterator + whose value_type is an std::pair of + integer values. These integer values are the source and target + vertices for the edges, and must fall within the range [0, + numverts). The edges in [edge_begin, + edge_end) must be sorted so that all edges originating + from vertex i preceed any edges originating from all + vertices j where j > i. +

    + +

    + The value numedges, if provided, tells how many + edges are in the range [edge_begin, edge_end) and + will be used to preallocate data structures to save both memory + and time during construction. +

    + +

    + The value prop will be used to initialize the graph + property. +

    + +
    + +
    
    +  template<typename InputIterator, typename EdgePropertyIterator>
    +  compressed_sparse_row_graph(InputIterator edge_begin, InputIterator edge_end,
    +                              EdgePropertyIterator ep_iter,
    +                              vertices_size_type numverts,
    +                              edges_size_type numedges = 0,
    +                              const GraphProperty& prop = GraphProperty());
    +    
    +

    + This constructor constructs a graph with numverts + vertices and the edges provided in the iterator range + [edge_begin, edge_end). Its semantics are identical + to the edge range constructor, except + that edge properties are also initialized. The type + EdgePropertyIterator must be a model of the InputIterator + concept whose value_type is convertible to + EdgeProperty. The iterator range [ep_iter, ep_ter + + m) will be used to initialize the properties on the edges + of the graph, where m is distance from + edge_begin to edge_end. +

    + +
    + +
    
    +  template<typename InputIterator>
    +  compressed_sparse_row_graph(InputIterator edge_begin, InputIterator edge_end,
    +                              vertices_size_type numverts,
    +                              edges_size_type numedges = 0,
    +                              const GraphProperty& prop = GraphProperty());
    +    
    + +

    + Constructs a graph with numverts vertices whose + edges are specified by the iterator range [edge_begin, + edge_end). The InputIterator must be a model of + InputIterator + whose value_type is an std::pair of + integer values. These integer values are the source and target + vertices for the edges, and must fall within the range [0, + numverts). The edges in [edge_begin, + edge_end) must be sorted so that all edges originating + from vertex i preceed any edges originating from all + vertices j where j > i. +

    + +

    + The value numedges, if provided, tells how many + edges are in the range [edge_begin, edge_end) and + will be used to preallocate data structures to save both memory + and time during construction. +

    + +

    + The value prop will be used to initialize the graph + property. +

    + +
    + +
    
    +  template<typename InputIterator, typename EdgePropertyIterator>
    +  compressed_sparse_row_graph(InputIterator edge_begin, InputIterator edge_end,
    +                              EdgePropertyIterator ep_iter,
    +                              vertices_size_type numverts,
    +                              edges_size_type numedges = 0,
    +                              const GraphProperty& prop = GraphProperty());
    +    
    +

    + This constructor constructs a graph with numverts + vertices and the edges provided in the iterator range + [edge_begin, edge_end). Its semantics are identical + to the edge range constructor, except + that edge properties are also initialized. The type + EdgePropertyIterator must be a model of the InputIterator + concept whose value_type is convertible to + EdgeProperty. The iterator range [ep_iter, ep_ter + + m) will be used to initialize the properties on the edges + of the graph, where m is distance from + edge_begin to edge_end. +

    + +
    + +
    
    +  template<typename InputIterator>
    +  compressed_sparse_row_graph(InputIterator edge_begin, InputIterator edge_end,
    +                              vertices_size_type numverts,
    +                              edges_size_type numedges = 0,
    +                              const GraphProperty& prop = GraphProperty());
    +    
    + +

    + Constructs a graph with numverts vertices whose + edges are specified by the iterator range [edge_begin, + edge_end). The InputIterator must be a model of + InputIterator + whose value_type is an std::pair of + integer values. These integer values are the source and target + vertices for the edges, and must fall within the range [0, + numverts). The edges in [edge_begin, + edge_end) must be sorted so that all edges originating + from vertex i preceed any edges originating from all + vertices j where j > i. +

    + +

    + The value numedges, if provided, tells how many + edges are in the range [edge_begin, edge_end) and + will be used to preallocate data structures to save both memory + and time during construction. +

    + +

    + The value prop will be used to initialize the graph + property. +

    + +
    + +
    
    +  template<typename InputIterator, typename EdgePropertyIterator>
    +  compressed_sparse_row_graph(InputIterator edge_begin, InputIterator edge_end,
    +                              EdgePropertyIterator ep_iter,
    +                              vertices_size_type numverts,
    +                              edges_size_type numedges = 0,
    +                              const GraphProperty& prop = GraphProperty());
    +    
    +

    + This constructor constructs a graph with numverts + vertices and the edges provided in the iterator range + [edge_begin, edge_end). Its semantics are identical + to the edge range constructor, except + that edge properties are also initialized. The type + EdgePropertyIterator must be a model of the InputIterator + concept whose value_type is convertible to + EdgeProperty. The iterator range [ep_iter, ep_ter + + m) will be used to initialize the properties on the edges + of the graph, where m is distance from + edge_begin to edge_end. +

    + +
    + +
    
    +  template<typename InputIterator>
    +  compressed_sparse_row_graph(InputIterator edge_begin, InputIterator edge_end,
    +                              vertices_size_type numverts,
    +                              edges_size_type numedges = 0,
    +                              const GraphProperty& prop = GraphProperty());
    +    
    + +

    + Constructs a graph with numverts vertices whose + edges are specified by the iterator range [edge_begin, + edge_end). The InputIterator must be a model of + InputIterator + whose value_type is an std::pair of + integer values. These integer values are the source and target + vertices for the edges, and must fall within the range [0, + numverts). The edges in [edge_begin, + edge_end) must be sorted so that all edges originating + from vertex i preceed any edges originating from all + vertices j where j > i. +

    + +

    + The value numedges, if provided, tells how many + edges are in the range [edge_begin, edge_end) and + will be used to preallocate data structures to save both memory + and time during construction. +

    + +

    + The value prop will be used to initialize the graph + property. +

    + +
    + +
    
    +  template<typename InputIterator, typename EdgePropertyIterator>
    +  compressed_sparse_row_graph(InputIterator edge_begin, InputIterator edge_end,
    +                              EdgePropertyIterator ep_iter,
    +                              vertices_size_type numverts,
    +                              edges_size_type numedges = 0,
    +                              const GraphProperty& prop = GraphProperty());
    +    
    +

    + This constructor constructs a graph with numverts + vertices and the edges provided in the iterator range + [edge_begin, edge_end). Its semantics are identical + to the edge range constructor, except + that edge properties are also initialized. The type + EdgePropertyIterator must be a model of the InputIterator + concept whose value_type is convertible to + EdgeProperty. The iterator range [ep_iter, ep_ter + + m) will be used to initialize the properties on the edges + of the graph, where m is distance from + edge_begin to edge_end. +

    + +
    + +
    
    +  template<typename InputIterator>
    +  compressed_sparse_row_graph(InputIterator edge_begin, InputIterator edge_end,
    +                              vertices_size_type numverts,
    +                              edges_size_type numedges = 0,
    +                              const GraphProperty& prop = GraphProperty());
    +    
    + +

    + Constructs a graph with numverts vertices whose + edges are specified by the iterator range [edge_begin, + edge_end). The InputIterator must be a model of + InputIterator + whose value_type is an std::pair of + integer values. These integer values are the source and target + vertices for the edges, and must fall within the range [0, + numverts). The edges in [edge_begin, + edge_end) must be sorted so that all edges originating + from vertex i preceed any edges originating from all + vertices j where j > i. +

    + +

    + The value numedges, if provided, tells how many + edges are in the range [edge_begin, edge_end) and + will be used to preallocate data structures to save both memory + and time during construction. +

    + +

    + The value prop will be used to initialize the graph + property. +

    + +
    + +
    
    +  template<typename InputIterator, typename EdgePropertyIterator>
    +  compressed_sparse_row_graph(InputIterator edge_begin, InputIterator edge_end,
    +                              EdgePropertyIterator ep_iter,
    +                              vertices_size_type numverts,
    +                              edges_size_type numedges = 0,
    +                              const GraphProperty& prop = GraphProperty());
    +    
    +

    + This constructor constructs a graph with numverts + vertices and the edges provided in the iterator range + [edge_begin, edge_end). Its semantics are identical + to the edge range constructor, except + that edge properties are also initialized. The type + EdgePropertyIterator must be a model of the InputIterator + concept whose value_type is convertible to + EdgeProperty. The iterator range [ep_iter, ep_ter + + m) will be used to initialize the properties on the edges + of the graph, where m is distance from + edge_begin to edge_end. +

    + +
    + +
    
    +  template<typename InputIterator>
    +  compressed_sparse_row_graph(InputIterator edge_begin, InputIterator edge_end,
    +                              vertices_size_type numverts,
    +                              edges_size_type numedges = 0,
    +                              const GraphProperty& prop = GraphProperty());
    +    
    + +

    + Constructs a graph with numverts vertices whose + edges are specified by the iterator range [edge_begin, + edge_end). The InputIterator must be a model of + InputIterator + whose value_type is an std::pair of + integer values. These integer values are the source and target + vertices for the edges, and must fall within the range [0, + numverts). The edges in [edge_begin, + edge_end) must be sorted so that all edges originating + from vertex i preceed any edges originating from all + vertices j where j > i. +

    + +

    + The value numedges, if provided, tells how many + edges are in the range [edge_begin, edge_end) and + will be used to preallocate data structures to save both memory + and time during construction. +

    + +

    + The value prop will be used to initialize the graph + property. +

    + +
    + +
    
    +  template<typename InputIterator, typename EdgePropertyIterator>
    +  compressed_sparse_row_graph(InputIterator edge_begin, InputIterator edge_end,
    +                              EdgePropertyIterator ep_iter,
    +                              vertices_size_type numverts,
    +                              edges_size_type numedges = 0,
    +                              const GraphProperty& prop = GraphProperty());
    +    
    +

    + This constructor constructs a graph with numverts + vertices and the edges provided in the iterator range + [edge_begin, edge_end). Its semantics are identical + to the edge range constructor, except + that edge properties are also initialized. The type + EdgePropertyIterator must be a model of the InputIterator + concept whose value_type is convertible to + EdgeProperty. The iterator range [ep_iter, ep_ter + + m) will be used to initialize the properties on the edges + of the graph, where m is distance from + edge_begin to edge_end. +

    + +
    + +
    
    +  template<typename InputIterator>
    +  compressed_sparse_row_graph(InputIterator edge_begin, InputIterator edge_end,
    +                              vertices_size_type numverts,
    +                              edges_size_type numedges = 0,
    +                              const GraphProperty& prop = GraphProperty());
    +    
    + +

    + Constructs a graph with numverts vertices whose + edges are specified by the iterator range [edge_begin, + edge_end). The InputIterator must be a model of + InputIterator + whose value_type is an std::pair of + integer values. These integer values are the source and target + vertices for the edges, and must fall within the range [0, + numverts). The edges in [edge_begin, + edge_end) must be sorted so that all edges originating + from vertex i preceed any edges originating from all + vertices j where j > i. +

    + +

    + The value numedges, if provided, tells how many + edges are in the range [edge_begin, edge_end) and + will be used to preallocate data structures to save both memory + and time during construction. +

    + +

    + The value prop will be used to initialize the graph + property. +

    + +
    + +
    
    +  template<typename InputIterator, typename EdgePropertyIterator>
    +  compressed_sparse_row_graph(InputIterator edge_begin, InputIterator edge_end,
    +                              EdgePropertyIterator ep_iter,
    +                              vertices_size_type numverts,
    +                              edges_size_type numedges = 0,
    +                              const GraphProperty& prop = GraphProperty());
    +    
    +

    + This constructor constructs a graph with numverts + vertices and the edges provided in the iterator range + [edge_begin, edge_end). Its semantics are identical + to the edge range constructor, except + that edge properties are also initialized. The type + EdgePropertyIterator must be a model of the InputIterator + concept whose value_type is convertible to + EdgeProperty. The iterator range [ep_iter, ep_ter + + m) will be used to initialize the properties on the edges + of the graph, where m is distance from + edge_begin to edge_end. +

    + +
    + +
    
    +  template<typename InputIterator>
    +  compressed_sparse_row_graph(InputIterator edge_begin, InputIterator edge_end,
    +                              vertices_size_type numverts,
    +                              edges_size_type numedges = 0,
    +                              const GraphProperty& prop = GraphProperty());
    +    
    + +

    + Constructs a graph with numverts vertices whose + edges are specified by the iterator range [edge_begin, + edge_end). The InputIterator must be a model of + InputIterator + whose value_type is an std::pair of + integer values. These integer values are the source and target + vertices for the edges, and must fall within the range [0, + numverts). The edges in [edge_begin, + edge_end) must be sorted so that all edges originating + from vertex i preceed any edges originating from all + vertices j where j > i. +

    + +

    + The value numedges, if provided, tells how many + edges are in the range [edge_begin, edge_end) and + will be used to preallocate data structures to save both memory + and time during construction. +

    + +

    + The value prop will be used to initialize the graph + property. +

    + +
    + +
    
    +  template<typename InputIterator, typename EdgePropertyIterator>
    +  compressed_sparse_row_graph(InputIterator edge_begin, InputIterator edge_end,
    +                              EdgePropertyIterator ep_iter,
    +                              vertices_size_type numverts,
    +                              edges_size_type numedges = 0,
    +                              const GraphProperty& prop = GraphProperty());
    +    
    +

    + This constructor constructs a graph with numverts + vertices and the edges provided in the iterator range + [edge_begin, edge_end). Its semantics are identical + to the edge range constructor, except + that edge properties are also initialized. The type + EdgePropertyIterator must be a model of the InputIterator + concept whose value_type is convertible to + EdgeProperty. The iterator range [ep_iter, ep_ter + + m) will be used to initialize the properties on the edges + of the graph, where m is distance from + edge_begin to edge_end. +

    + +
    + +
    
    +  template<typename InputIterator>
    +  compressed_sparse_row_graph(InputIterator edge_begin, InputIterator edge_end,
    +                              vertices_size_type numverts,
    +                              edges_size_type numedges = 0,
    +                              const GraphProperty& prop = GraphProperty());
    +    
    + +

    + Constructs a graph with numverts vertices whose + edges are specified by the iterator range [edge_begin, + edge_end). The InputIterator must be a model of + InputIterator + whose value_type is an std::pair of + integer values. These integer values are the source and target + vertices for the edges, and must fall within the range [0, + numverts). The edges in [edge_begin, + edge_end) must be sorted so that all edges originating + from vertex i preceed any edges originating from all + vertices j where j > i. +

    + +

    + The value numedges, if provided, tells how many + edges are in the range [edge_begin, edge_end) and + will be used to preallocate data structures to save both memory + and time during construction. +

    + +

    + The value prop will be used to initialize the graph + property. +

    + +
    + +
    
    +  template<typename InputIterator, typename EdgePropertyIterator>
    +  compressed_sparse_row_graph(InputIterator edge_begin, InputIterator edge_end,
    +                              EdgePropertyIterator ep_iter,
    +                              vertices_size_type numverts,
    +                              edges_size_type numedges = 0,
    +                              const GraphProperty& prop = GraphProperty());
    +    
    +

    + This constructor constructs a graph with numverts + vertices and the edges provided in the iterator range + [edge_begin, edge_end). Its semantics are identical + to the edge range constructor, except + that edge properties are also initialized. The type + EdgePropertyIterator must be a model of the InputIterator + concept whose value_type is convertible to + EdgeProperty. The iterator range [ep_iter, ep_ter + + m) will be used to initialize the properties on the edges + of the graph, where m is distance from + edge_begin to edge_end. +

    + +
    + +
    
    +  template<typename InputIterator>
    +  compressed_sparse_row_graph(InputIterator edge_begin, InputIterator edge_end,
    +                              vertices_size_type numverts,
    +                              edges_size_type numedges = 0,
    +                              const GraphProperty& prop = GraphProperty());
    +    
    + +

    + Constructs a graph with numverts vertices whose + edges are specified by the iterator range [edge_begin, + edge_end). The InputIterator must be a model of + InputIterator + whose value_type is an std::pair of + integer values. These integer values are the source and target + vertices for the edges, and must fall within the range [0, + numverts). The edges in [edge_begin, + edge_end) must be sorted so that all edges originating + from vertex i preceed any edges originating from all + vertices j where j > i. +

    + +

    + The value numedges, if provided, tells how many + edges are in the range [edge_begin, edge_end) and + will be used to preallocate data structures to save both memory + and time during construction. +

    + +

    + The value prop will be used to initialize the graph + property. +

    + +
    + +
    
    +  template<typename InputIterator, typename EdgePropertyIterator>
    +  compressed_sparse_row_graph(InputIterator edge_begin, InputIterator edge_end,
    +                              EdgePropertyIterator ep_iter,
    +                              vertices_size_type numverts,
    +                              edges_size_type numedges = 0,
    +                              const GraphProperty& prop = GraphProperty());
    +    
    +

    + This constructor constructs a graph with numverts + vertices and the edges provided in the iterator range + [edge_begin, edge_end). Its semantics are identical + to the edge range constructor, except + that edge properties are also initialized. The type + EdgePropertyIterator must be a model of the InputIterator + concept whose value_type is convertible to + EdgeProperty. The iterator range [ep_iter, ep_ter + + m) will be used to initialize the properties on the edges + of the graph, where m is distance from + edge_begin to edge_end. +

    + +
    + +
    
    +  template<typename InputIterator>
    +  compressed_sparse_row_graph(InputIterator edge_begin, InputIterator edge_end,
    +                              vertices_size_type numverts,
    +                              edges_size_type numedges = 0,
    +                              const GraphProperty& prop = GraphProperty());
    +    
    + +

    + Constructs a graph with numverts vertices whose + edges are specified by the iterator range [edge_begin, + edge_end). The InputIterator must be a model of + InputIterator + whose value_type is an std::pair of + integer values. These integer values are the source and target + vertices for the edges, and must fall within the range [0, + numverts). The edges in [edge_begin, + edge_end) must be sorted so that all edges originating + from vertex i preceed any edges originating from all + vertices j where j > i. +

    + +

    + The value numedges, if provided, tells how many + edges are in the range [edge_begin, edge_end) and + will be used to preallocate data structures to save both memory + and time during construction. +

    + +

    + The value prop will be used to initialize the graph + property. +

    + +
    + +
    
    +  template<typename InputIterator, typename EdgePropertyIterator>
    +  compressed_sparse_row_graph(InputIterator edge_begin, InputIterator edge_end,
    +                              EdgePropertyIterator ep_iter,
    +                              vertices_size_type numverts,
    +                              edges_size_type numedges = 0,
    +                              const GraphProperty& prop = GraphProperty());
    +    
    +

    + This constructor constructs a graph with numverts + vertices and the edges provided in the iterator range + [edge_begin, edge_end). Its semantics are identical + to the edge range constructor, except + that edge properties are also initialized. The type + EdgePropertyIterator must be a model of the InputIterator + concept whose value_type is convertible to + EdgeProperty. The iterator range [ep_iter, ep_ter + + m) will be used to initialize the properties on the edges + of the graph, where m is distance from + edge_begin to edge_end. +

    + +
    + +
    
    +  template<typename InputIterator>
    +  compressed_sparse_row_graph(InputIterator edge_begin, InputIterator edge_end,
    +                              vertices_size_type numverts,
    +                              edges_size_type numedges = 0,
    +                              const GraphProperty& prop = GraphProperty());
    +    
    + +

    + Constructs a graph with numverts vertices whose + edges are specified by the iterator range [edge_begin, + edge_end). The InputIterator must be a model of + InputIterator + whose value_type is an std::pair of + integer values. These integer values are the source and target + vertices for the edges, and must fall within the range [0, + numverts). The edges in [edge_begin, + edge_end) must be sorted so that all edges originating + from vertex i preceed any edges originating from all + vertices j where j > i. +

    + +

    + The value numedges, if provided, tells how many + edges are in the range [edge_begin, edge_end) and + will be used to preallocate data structures to save both memory + and time during construction. +

    + +

    + The value prop will be used to initialize the graph + property. +

    + +
    + +
    
    +  template<typename InputIterator, typename EdgePropertyIterator>
    +  compressed_sparse_row_graph(InputIterator edge_begin, InputIterator edge_end,
    +                              EdgePropertyIterator ep_iter,
    +                              vertices_size_type numverts,
    +                              edges_size_type numedges = 0,
    +                              const GraphProperty& prop = GraphProperty());
    +    
    +

    + This constructor constructs a graph with numverts + vertices and the edges provided in the iterator range + [edge_begin, edge_end). Its semantics are identical + to the edge range constructor, except + that edge properties are also initialized. The type + EdgePropertyIterator must be a model of the InputIterator + concept whose value_type is convertible to + EdgeProperty. The iterator range [ep_iter, ep_ter + + m) will be used to initialize the properties on the edges + of the graph, where m is distance from + edge_begin to edge_end. +

    + +
    + +
    
    +  template<typename InputIterator>
    +  compressed_sparse_row_graph(InputIterator edge_begin, InputIterator edge_end,
    +                              vertices_size_type numverts,
    +                              edges_size_type numedges = 0,
    +                              const GraphProperty& prop = GraphProperty());
    +    
    + +

    + Constructs a graph with numverts vertices whose + edges are specified by the iterator range [edge_begin, + edge_end). The InputIterator must be a model of + InputIterator + whose value_type is an std::pair of + integer values. These integer values are the source and target + vertices for the edges, and must fall within the range [0, + numverts). The edges in [edge_begin, + edge_end) must be sorted so that all edges originating + from vertex i preceed any edges originating from all + vertices j where j > i. +

    + +

    + The value numedges, if provided, tells how many + edges are in the range [edge_begin, edge_end) and + will be used to preallocate data structures to save both memory + and time during construction. +

    + +

    + The value prop will be used to initialize the graph + property. +

    + +
    + +
    
    +  template<typename InputIterator, typename EdgePropertyIterator>
    +  compressed_sparse_row_graph(InputIterator edge_begin, InputIterator edge_end,
    +                              EdgePropertyIterator ep_iter,
    +                              vertices_size_type numverts,
    +                              edges_size_type numedges = 0,
    +                              const GraphProperty& prop = GraphProperty());
    +    
    +

    + This constructor constructs a graph with numverts + vertices and the edges provided in the iterator range + [edge_begin, edge_end). Its semantics are identical + to the edge range constructor, except + that edge properties are also initialized. The type + EdgePropertyIterator must be a model of the InputIterator + concept whose value_type is convertible to + EdgeProperty. The iterator range [ep_iter, ep_ter + + m) will be used to initialize the properties on the edges + of the graph, where m is distance from + edge_begin to edge_end. +

    + +
    + +
    
    +  template<typename InputIterator>
    +  compressed_sparse_row_graph(InputIterator edge_begin, InputIterator edge_end,
    +                              vertices_size_type numverts,
    +                              edges_size_type numedges = 0,
    +                              const GraphProperty& prop = GraphProperty());
    +    
    + +

    + Constructs a graph with numverts vertices whose + edges are specified by the iterator range [edge_begin, + edge_end). The InputIterator must be a model of + InputIterator + whose value_type is an std::pair of + integer values. These integer values are the source and target + vertices for the edges, and must fall within the range [0, + numverts). The edges in [edge_begin, + edge_end) must be sorted so that all edges originating + from vertex i preceed any edges originating from all + vertices j where j > i. +

    + +

    + The value numedges, if provided, tells how many + edges are in the range [edge_begin, edge_end) and + will be used to preallocate data structures to save both memory + and time during construction. +

    + +

    + The value prop will be used to initialize the graph + property. +

    + +
    + +
    
    +  template<typename InputIterator, typename EdgePropertyIterator>
    +  compressed_sparse_row_graph(InputIterator edge_begin, InputIterator edge_end,
    +                              EdgePropertyIterator ep_iter,
    +                              vertices_size_type numverts,
    +                              edges_size_type numedges = 0,
    +                              const GraphProperty& prop = GraphProperty());
    +    
    +

    + This constructor constructs a graph with numverts + vertices and the edges provided in the iterator range + [edge_begin, edge_end). Its semantics are identical + to the edge range constructor, except + that edge properties are also initialized. The type + EdgePropertyIterator must be a model of the InputIterator + concept whose value_type is convertible to + EdgeProperty. The iterator range [ep_iter, ep_ter + + m) will be used to initialize the properties on the edges + of the graph, where m is distance from + edge_begin to edge_end. +

    + +
    + +
    
    +  template<typename InputIterator>
    +  compressed_sparse_row_graph(InputIterator edge_begin, InputIterator edge_end,
    +                              vertices_size_type numverts,
    +                              edges_size_type numedges = 0,
    +                              const GraphProperty& prop = GraphProperty());
    +    
    + +

    + Constructs a graph with numverts vertices whose + edges are specified by the iterator range [edge_begin, + edge_end). The InputIterator must be a model of + InputIterator + whose value_type is an std::pair of + integer values. These integer values are the source and target + vertices for the edges, and must fall within the range [0, + numverts). The edges in [edge_begin, + edge_end) must be sorted so that all edges originating + from vertex i preceed any edges originating from all + vertices j where j > i. +

    + +

    + The value numedges, if provided, tells how many + edges are in the range [edge_begin, edge_end) and + will be used to preallocate data structures to save both memory + and time during construction. +

    + +

    + The value prop will be used to initialize the graph + property. +

    + +
    + +
    
    +  template<typename InputIterator, typename EdgePropertyIterator>
    +  compressed_sparse_row_graph(InputIterator edge_begin, InputIterator edge_end,
    +                              EdgePropertyIterator ep_iter,
    +                              vertices_size_type numverts,
    +                              edges_size_type numedges = 0,
    +                              const GraphProperty& prop = GraphProperty());
    +    
    +

    + This constructor constructs a graph with numverts + vertices and the edges provided in the iterator range + [edge_begin, edge_end). Its semantics are identical + to the edge range constructor, except + that edge properties are also initialized. The type + EdgePropertyIterator must be a model of the InputIterator + concept whose value_type is convertible to + EdgeProperty. The iterator range [ep_iter, ep_ter + + m) will be used to initialize the properties on the edges + of the graph, where m is distance from + edge_begin to edge_end. +

    + +
    + +
    
    +  template<typename InputIterator>
    +  compressed_sparse_row_graph(InputIterator edge_begin, InputIterator edge_end,
    +                              vertices_size_type numverts,
    +                              edges_size_type numedges = 0,
    +                              const GraphProperty& prop = GraphProperty());
    +    
    + +

    + Constructs a graph with numverts vertices whose + edges are specified by the iterator range [edge_begin, + edge_end). The InputIterator must be a model of + InputIterator + whose value_type is an std::pair of + integer values. These integer values are the source and target + vertices for the edges, and must fall within the range [0, + numverts). The edges in [edge_begin, + edge_end) must be sorted so that all edges originating + from vertex i preceed any edges originating from all + vertices j where j > i. +

    + +

    + The value numedges, if provided, tells how many + edges are in the range [edge_begin, edge_end) and + will be used to preallocate data structures to save both memory + and time during construction. +

    + +

    + The value prop will be used to initialize the graph + property. +

    + +
    + +
    
    +  template<typename InputIterator, typename EdgePropertyIterator>
    +  compressed_sparse_row_graph(InputIterator edge_begin, InputIterator edge_end,
    +                              EdgePropertyIterator ep_iter,
    +                              vertices_size_type numverts,
    +                              edges_size_type numedges = 0,
    +                              const GraphProperty& prop = GraphProperty());
    +    
    +

    + This constructor constructs a graph with numverts + vertices and the edges provided in the iterator range + [edge_begin, edge_end). Its semantics are identical + to the edge range constructor, except + that edge properties are also initialized. The type + EdgePropertyIterator must be a model of the InputIterator + concept whose value_type is convertible to + EdgeProperty. The iterator range [ep_iter, ep_ter + + m) will be used to initialize the properties on the edges + of the graph, where m is distance from + edge_begin to edge_end. +

    + +
    + +
    
    +  template<typename InputIterator>
    +  compressed_sparse_row_graph(InputIterator edge_begin, InputIterator edge_end,
    +                              vertices_size_type numverts,
    +                              edges_size_type numedges = 0,
    +                              const GraphProperty& prop = GraphProperty());
    +    
    + +

    + Constructs a graph with numverts vertices whose + edges are specified by the iterator range [edge_begin, + edge_end). The InputIterator must be a model of + InputIterator + whose value_type is an std::pair of + integer values. These integer values are the source and target + vertices for the edges, and must fall within the range [0, + numverts). The edges in [edge_begin, + edge_end) must be sorted so that all edges originating + from vertex i preceed any edges originating from all + vertices j where j > i. +

    + +

    + The value numedges, if provided, tells how many + edges are in the range [edge_begin, edge_end) and + will be used to preallocate data structures to save both memory + and time during construction. +

    + +

    + The value prop will be used to initialize the graph + property. +

    + +
    + +
    
    +  template<typename InputIterator, typename EdgePropertyIterator>
    +  compressed_sparse_row_graph(InputIterator edge_begin, InputIterator edge_end,
    +                              EdgePropertyIterator ep_iter,
    +                              vertices_size_type numverts,
    +                              edges_size_type numedges = 0,
    +                              const GraphProperty& prop = GraphProperty());
    +    
    +

    + This constructor constructs a graph with numverts + vertices and the edges provided in the iterator range + [edge_begin, edge_end). Its semantics are identical + to the edge range constructor, except + that edge properties are also initialized. The type + EdgePropertyIterator must be a model of the InputIterator + concept whose value_type is convertible to + EdgeProperty. The iterator range [ep_iter, ep_ter + + m) will be used to initialize the properties on the edges + of the graph, where m is distance from + edge_begin to edge_end. +

    + +
    + +
    
    +  template<typename InputIterator>
    +  compressed_sparse_row_graph(InputIterator edge_begin, InputIterator edge_end,
    +                              vertices_size_type numverts,
    +                              edges_size_type numedges = 0,
    +                              const GraphProperty& prop = GraphProperty());
    +    
    + +

    + Constructs a graph with numverts vertices whose + edges are specified by the iterator range [edge_begin, + edge_end). The InputIterator must be a model of + InputIterator + whose value_type is an std::pair of + integer values. These integer values are the source and target + vertices for the edges, and must fall within the range [0, + numverts). The edges in [edge_begin, + edge_end) must be sorted so that all edges originating + from vertex i preceed any edges originating from all + vertices j where j > i. +

    + +

    + The value numedges, if provided, tells how many + edges are in the range [edge_begin, edge_end) and + will be used to preallocate data structures to save both memory + and time during construction. +

    + +

    + The value prop will be used to initialize the graph + property. +

    + +
    + +
    
    +  template<typename InputIterator, typename EdgePropertyIterator>
    +  compressed_sparse_row_graph(InputIterator edge_begin, InputIterator edge_end,
    +                              EdgePropertyIterator ep_iter,
    +                              vertices_size_type numverts,
    +                              edges_size_type numedges = 0,
    +                              const GraphProperty& prop = GraphProperty());
    +    
    +

    + This constructor constructs a graph with numverts + vertices and the edges provided in the iterator range + [edge_begin, edge_end). Its semantics are identical + to the edge range constructor, except + that edge properties are also initialized. The type + EdgePropertyIterator must be a model of the InputIterator + concept whose value_type is convertible to + EdgeProperty. The iterator range [ep_iter, ep_ter + + m) will be used to initialize the properties on the edges + of the graph, where m is distance from + edge_begin to edge_end. +

    + +
    + +
    
    +  template<typename InputIterator>
    +  compressed_sparse_row_graph(InputIterator edge_begin, InputIterator edge_end,
    +                              vertices_size_type numverts,
    +                              edges_size_type numedges = 0,
    +                              const GraphProperty& prop = GraphProperty());
    +    
    + +

    + Constructs a graph with numverts vertices whose + edges are specified by the iterator range [edge_begin, + edge_end). The InputIterator must be a model of + InputIterator + whose value_type is an std::pair of + integer values. These integer values are the source and target + vertices for the edges, and must fall within the range [0, + numverts). The edges in [edge_begin, + edge_end) must be sorted so that all edges originating + from vertex i preceed any edges originating from all + vertices j where j > i. +

    + +

    + The value numedges, if provided, tells how many + edges are in the range [edge_begin, edge_end) and + will be used to preallocate data structures to save both memory + and time during construction. +

    + +

    + The value prop will be used to initialize the graph + property. +

    + +
    + +
    
    +  template<typename InputIterator, typename EdgePropertyIterator>
    +  compressed_sparse_row_graph(InputIterator edge_begin, InputIterator edge_end,
    +                              EdgePropertyIterator ep_iter,
    +                              vertices_size_type numverts,
    +                              edges_size_type numedges = 0,
    +                              const GraphProperty& prop = GraphProperty());
    +    
    +

    + This constructor constructs a graph with numverts + vertices and the edges provided in the iterator range + [edge_begin, edge_end). Its semantics are identical + to the edge range constructor, except + that edge properties are also initialized. The type + EdgePropertyIterator must be a model of the InputIterator + concept whose value_type is convertible to + EdgeProperty. The iterator range [ep_iter, ep_ter + + m) will be used to initialize the properties on the edges + of the graph, where m is distance from + edge_begin to edge_end. +

    + +
    + +
    
    +  template<typename InputIterator>
    +  compressed_sparse_row_graph(InputIterator edge_begin, InputIterator edge_end,
    +                              vertices_size_type numverts,
    +                              edges_size_type numedges = 0,
    +                              const GraphProperty& prop = GraphProperty());
    +    
    + +

    + Constructs a graph with numverts vertices whose + edges are specified by the iterator range [edge_begin, + edge_end). The InputIterator must be a model of + InputIterator + whose value_type is an std::pair of + integer values. These integer values are the source and target + vertices for the edges, and must fall within the range [0, + numverts). The edges in [edge_begin, + edge_end) must be sorted so that all edges originating + from vertex i preceed any edges originating from all + vertices j where j > i. +

    + +

    + The value numedges, if provided, tells how many + edges are in the range [edge_begin, edge_end) and + will be used to preallocate data structures to save both memory + and time during construction. +

    + +

    + The value prop will be used to initialize the graph + property. +

    + +
    + +
    
    +  template<typename InputIterator, typename EdgePropertyIterator>
    +  compressed_sparse_row_graph(InputIterator edge_begin, InputIterator edge_end,
    +                              EdgePropertyIterator ep_iter,
    +                              vertices_size_type numverts,
    +                              edges_size_type numedges = 0,
    +                              const GraphProperty& prop = GraphProperty());
    +    
    +

    + This constructor constructs a graph with numverts + vertices and the edges provided in the iterator range + [edge_begin, edge_end). Its semantics are identical + to the edge range constructor, except + that edge properties are also initialized. The type + EdgePropertyIterator must be a model of the InputIterator + concept whose value_type is convertible to + EdgeProperty. The iterator range [ep_iter, ep_ter + + m) will be used to initialize the properties on the edges + of the graph, where m is distance from + edge_begin to edge_end. +

    + +
    + +
    
    +  template<typename InputIterator>
    +  compressed_sparse_row_graph(InputIterator edge_begin, InputIterator edge_end,
    +                              vertices_size_type numverts,
    +                              edges_size_type numedges = 0,
    +                              const GraphProperty& prop = GraphProperty());
    +    
    + +

    + Constructs a graph with numverts vertices whose + edges are specified by the iterator range [edge_begin, + edge_end). The InputIterator must be a model of + InputIterator + whose value_type is an std::pair of + integer values. These integer values are the source and target + vertices for the edges, and must fall within the range [0, + numverts). The edges in [edge_begin, + edge_end) must be sorted so that all edges originating + from vertex i preceed any edges originating from all + vertices j where j > i. +

    + +

    + The value numedges, if provided, tells how many + edges are in the range [edge_begin, edge_end) and + will be used to preallocate data structures to save both memory + and time during construction. +

    + +

    + The value prop will be used to initialize the graph + property. +

    + +
    + +
    
    +  template<typename InputIterator, typename EdgePropertyIterator>
    +  compressed_sparse_row_graph(InputIterator edge_begin, InputIterator edge_end,
    +                              EdgePropertyIterator ep_iter,
    +                              vertices_size_type numverts,
    +                              edges_size_type numedges = 0,
    +                              const GraphProperty& prop = GraphProperty());
    +    
    +

    + This constructor constructs a graph with numverts + vertices and the edges provided in the iterator range + [edge_begin, edge_end). Its semantics are identical + to the edge range constructor, except + that edge properties are also initialized. The type + EdgePropertyIterator must be a model of the InputIterator + concept whose value_type is convertible to + EdgeProperty. The iterator range [ep_iter, ep_ter + + m) will be used to initialize the properties on the edges + of the graph, where m is distance from + edge_begin to edge_end. +

    + +
    + +
    
    +  template<typename InputIterator>
    +  compressed_sparse_row_graph(InputIterator edge_begin, InputIterator edge_end,
    +                              vertices_size_type numverts,
    +                              edges_size_type numedges = 0,
    +                              const GraphProperty& prop = GraphProperty());
    +    
    + +

    + Constructs a graph with numverts vertices whose + edges are specified by the iterator range [edge_begin, + edge_end). The InputIterator must be a model of + InputIterator + whose value_type is an std::pair of + integer values. These integer values are the source and target + vertices for the edges, and must fall within the range [0, + numverts). The edges in [edge_begin, + edge_end) must be sorted so that all edges originating + from vertex i preceed any edges originating from all + vertices j where j > i. +

    + +

    + The value numedges, if provided, tells how many + edges are in the range [edge_begin, edge_end) and + will be used to preallocate data structures to save both memory + and time during construction. +

    + +

    + The value prop will be used to initialize the graph + property. +

    + +
    + +
    
    +  template<typename InputIterator, typename EdgePropertyIterator>
    +  compressed_sparse_row_graph(InputIterator edge_begin, InputIterator edge_end,
    +                              EdgePropertyIterator ep_iter,
    +                              vertices_size_type numverts,
    +                              edges_size_type numedges = 0,
    +                              const GraphProperty& prop = GraphProperty());
    +    
    +

    + This constructor constructs a graph with numverts + vertices and the edges provided in the iterator range + [edge_begin, edge_end). Its semantics are identical + to the edge range constructor, except + that edge properties are also initialized. The type + EdgePropertyIterator must be a model of the InputIterator + concept whose value_type is convertible to + EdgeProperty. The iterator range [ep_iter, ep_ter + + m) will be used to initialize the properties on the edges + of the graph, where m is distance from + edge_begin to edge_end. +

    + +
    + +
    
    +  template<typename InputIterator>
    +  compressed_sparse_row_graph(InputIterator edge_begin, InputIterator edge_end,
    +                              vertices_size_type numverts,
    +                              edges_size_type numedges = 0,
    +                              const GraphProperty& prop = GraphProperty());
    +    
    + +

    + Constructs a graph with numverts vertices whose + edges are specified by the iterator range [edge_begin, + edge_end). The InputIterator must be a model of + InputIterator + whose value_type is an std::pair of + integer values. These integer values are the source and target + vertices for the edges, and must fall within the range [0, + numverts). The edges in [edge_begin, + edge_end) must be sorted so that all edges originating + from vertex i preceed any edges originating from all + vertices j where j > i. +

    + +

    + The value numedges, if provided, tells how many + edges are in the range [edge_begin, edge_end) and + will be used to preallocate data structures to save both memory + and time during construction. +

    + +

    + The value prop will be used to initialize the graph + property. +

    + +
    + +
    
    +  template<typename InputIterator, typename EdgePropertyIterator>
    +  compressed_sparse_row_graph(InputIterator edge_begin, InputIterator edge_end,
    +                              EdgePropertyIterator ep_iter,
    +                              vertices_size_type numverts,
    +                              edges_size_type numedges = 0,
    +                              const GraphProperty& prop = GraphProperty());
    +    
    +

    + This constructor constructs a graph with numverts + vertices and the edges provided in the iterator range + [edge_begin, edge_end). Its semantics are identical + to the edge range constructor, except + that edge properties are also initialized. The type + EdgePropertyIterator must be a model of the InputIterator + concept whose value_type is convertible to + EdgeProperty. The iterator range [ep_iter, ep_ter + + m) will be used to initialize the properties on the edges + of the graph, where m is distance from + edge_begin to edge_end. +

    + +
    + +
    
    +  template<typename InputIterator>
    +  compressed_sparse_row_graph(InputIterator edge_begin, InputIterator edge_end,
    +                              vertices_size_type numverts,
    +                              edges_size_type numedges = 0,
    +                              const GraphProperty& prop = GraphProperty());
    +    
    + +

    + Constructs a graph with numverts vertices whose + edges are specified by the iterator range [edge_begin, + edge_end). The InputIterator must be a model of + InputIterator + whose value_type is an std::pair of + integer values. These integer values are the source and target + vertices for the edges, and must fall within the range [0, + numverts). The edges in [edge_begin, + edge_end) must be sorted so that all edges originating + from vertex i preceed any edges originating from all + vertices j where j > i. +

    + +

    + The value numedges, if provided, tells how many + edges are in the range [edge_begin, edge_end) and + will be used to preallocate data structures to save both memory + and time during construction. +

    + +

    + The value prop will be used to initialize the graph + property. +

    + +
    + +
    
    +  template<typename InputIterator, typename EdgePropertyIterator>
    +  compressed_sparse_row_graph(InputIterator edge_begin, InputIterator edge_end,
    +                              EdgePropertyIterator ep_iter,
    +                              vertices_size_type numverts,
    +                              edges_size_type numedges = 0,
    +                              const GraphProperty& prop = GraphProperty());
    +    
    +

    + This constructor constructs a graph with numverts + vertices and the edges provided in the iterator range + [edge_begin, edge_end). Its semantics are identical + to the edge range constructor, except + that edge properties are also initialized. The type + EdgePropertyIterator must be a model of the InputIterator + concept whose value_type is convertible to + EdgeProperty. The iterator range [ep_iter, ep_ter + + m) will be used to initialize the properties on the edges + of the graph, where m is distance from + edge_begin to edge_end. +

    + +
    + +
    
    +  template<typename InputIterator>
    +  compressed_sparse_row_graph(InputIterator edge_begin, InputIterator edge_end,
    +                              vertices_size_type numverts,
    +                              edges_size_type numedges = 0,
    +                              const GraphProperty& prop = GraphProperty());
    +    
    + +

    + Constructs a graph with numverts vertices whose + edges are specified by the iterator range [edge_begin, + edge_end). The InputIterator must be a model of + InputIterator + whose value_type is an std::pair of + integer values. These integer values are the source and target + vertices for the edges, and must fall within the range [0, + numverts). The edges in [edge_begin, + edge_end) must be sorted so that all edges originating + from vertex i preceed any edges originating from all + vertices j where j > i. +

    + +

    + The value numedges, if provided, tells how many + edges are in the range [edge_begin, edge_end) and + will be used to preallocate data structures to save both memory + and time during construction. +

    + +

    + The value prop will be used to initialize the graph + property. +

    + +
    + +
    
    +  template<typename InputIterator, typename EdgePropertyIterator>
    +  compressed_sparse_row_graph(InputIterator edge_begin, InputIterator edge_end,
    +                              EdgePropertyIterator ep_iter,
    +                              vertices_size_type numverts,
    +                              edges_size_type numedges = 0,
    +                              const GraphProperty& prop = GraphProperty());
    +    
    +

    + This constructor constructs a graph with numverts + vertices and the edges provided in the iterator range + [edge_begin, edge_end). Its semantics are identical + to the edge range constructor, except + that edge properties are also initialized. The type + EdgePropertyIterator must be a model of the InputIterator + concept whose value_type is convertible to + EdgeProperty. The iterator range [ep_iter, ep_ter + + m) will be used to initialize the properties on the edges + of the graph, where m is distance from + edge_begin to edge_end. +

    + +
    + +
    
    +  template<typename InputIterator>
    +  compressed_sparse_row_graph(InputIterator edge_begin, InputIterator edge_end,
    +                              vertices_size_type numverts,
    +                              edges_size_type numedges = 0,
    +                              const GraphProperty& prop = GraphProperty());
    +    
    + +

    + Constructs a graph with numverts vertices whose + edges are specified by the iterator range [edge_begin, + edge_end). The InputIterator must be a model of + InputIterator + whose value_type is an std::pair of + integer values. These integer values are the source and target + vertices for the edges, and must fall within the range [0, + numverts). The edges in [edge_begin, + edge_end) must be sorted so that all edges originating + from vertex i preceed any edges originating from all + vertices j where j > i. +

    + +

    + The value numedges, if provided, tells how many + edges are in the range [edge_begin, edge_end) and + will be used to preallocate data structures to save both memory + and time during construction. +

    + +

    + The value prop will be used to initialize the graph + property. +

    + +
    + +
    
    +  template<typename InputIterator, typename EdgePropertyIterator>
    +  compressed_sparse_row_graph(InputIterator edge_begin, InputIterator edge_end,
    +                              EdgePropertyIterator ep_iter,
    +                              vertices_size_type numverts,
    +                              edges_size_type numedges = 0,
    +                              const GraphProperty& prop = GraphProperty());
    +    
    +

    + This constructor constructs a graph with numverts + vertices and the edges provided in the iterator range + [edge_begin, edge_end). Its semantics are identical + to the edge range constructor, except + that edge properties are also initialized. The type + EdgePropertyIterator must be a model of the InputIterator + concept whose value_type is convertible to + EdgeProperty. The iterator range [ep_iter, ep_ter + + m) will be used to initialize the properties on the edges + of the graph, where m is distance from + edge_begin to edge_end. +

    + +
    + +
    
    +  template<typename InputIterator>
    +  compressed_sparse_row_graph(InputIterator edge_begin, InputIterator edge_end,
    +                              vertices_size_type numverts,
    +                              edges_size_type numedges = 0,
    +                              const GraphProperty& prop = GraphProperty());
    +    
    + +

    + Constructs a graph with numverts vertices whose + edges are specified by the iterator range [edge_begin, + edge_end). The InputIterator must be a model of + InputIterator + whose value_type is an std::pair of + integer values. These integer values are the source and target + vertices for the edges, and must fall within the range [0, + numverts). The edges in [edge_begin, + edge_end) must be sorted so that all edges originating + from vertex i preceed any edges originating from all + vertices j where j > i. +

    + +

    + The value numedges, if provided, tells how many + edges are in the range [edge_begin, edge_end) and + will be used to preallocate data structures to save both memory + and time during construction. +

    + +

    + The value prop will be used to initialize the graph + property. +

    + +
    + +
    
    +  template<typename InputIterator, typename EdgePropertyIterator>
    +  compressed_sparse_row_graph(InputIterator edge_begin, InputIterator edge_end,
    +                              EdgePropertyIterator ep_iter,
    +                              vertices_size_type numverts,
    +                              edges_size_type numedges = 0,
    +                              const GraphProperty& prop = GraphProperty());
    +    
    +

    + This constructor constructs a graph with numverts + vertices and the edges provided in the iterator range + [edge_begin, edge_end). Its semantics are identical + to the edge range constructor, except + that edge properties are also initialized. The type + EdgePropertyIterator must be a model of the InputIterator + concept whose value_type is convertible to + EdgeProperty. The iterator range [ep_iter, ep_ter + + m) will be used to initialize the properties on the edges + of the graph, where m is distance from + edge_begin to edge_end. +

    + +
    + +
    
    +  template<typename InputIterator>
    +  compressed_sparse_row_graph(InputIterator edge_begin, InputIterator edge_end,
    +                              vertices_size_type numverts,
    +                              edges_size_type numedges = 0,
    +                              const GraphProperty& prop = GraphProperty());
    +    
    + +

    + Constructs a graph with numverts vertices whose + edges are specified by the iterator range [edge_begin, + edge_end). The InputIterator must be a model of + InputIterator + whose value_type is an std::pair of + integer values. These integer values are the source and target + vertices for the edges, and must fall within the range [0, + numverts). The edges in [edge_begin, + edge_end) must be sorted so that all edges originating + from vertex i preceed any edges originating from all + vertices j where j > i. +

    + +

    + The value numedges, if provided, tells how many + edges are in the range [edge_begin, edge_end) and + will be used to preallocate data structures to save both memory + and time during construction. +

    + +

    + The value prop will be used to initialize the graph + property. +

    + +
    + +
    
    +  template<typename InputIterator, typename EdgePropertyIterator>
    +  compressed_sparse_row_graph(InputIterator edge_begin, InputIterator edge_end,
    +                              EdgePropertyIterator ep_iter,
    +                              vertices_size_type numverts,
    +                              edges_size_type numedges = 0,
    +                              const GraphProperty& prop = GraphProperty());
    +    
    +

    + This constructor constructs a graph with numverts + vertices and the edges provided in the iterator range + [edge_begin, edge_end). Its semantics are identical + to the edge range constructor, except + that edge properties are also initialized. The type + EdgePropertyIterator must be a model of the InputIterator + concept whose value_type is convertible to + EdgeProperty. The iterator range [ep_iter, ep_ter + + m) will be used to initialize the properties on the edges + of the graph, where m is distance from + edge_begin to edge_end. +

    + +
    + +
    
    +  template<typename InputIterator>
    +  compressed_sparse_row_graph(InputIterator edge_begin, InputIterator edge_end,
    +                              vertices_size_type numverts,
    +                              edges_size_type numedges = 0,
    +                              const GraphProperty& prop = GraphProperty());
    +    
    + +

    + Constructs a graph with numverts vertices whose + edges are specified by the iterator range [edge_begin, + edge_end). The InputIterator must be a model of + InputIterator + whose value_type is an std::pair of + integer values. These integer values are the source and target + vertices for the edges, and must fall within the range [0, + numverts). The edges in [edge_begin, + edge_end) must be sorted so that all edges originating + from vertex i preceed any edges originating from all + vertices j where j > i. +

    + +

    + The value numedges, if provided, tells how many + edges are in the range [edge_begin, edge_end) and + will be used to preallocate data structures to save both memory + and time during construction. +

    + +

    + The value prop will be used to initialize the graph + property. +

    + +
    + +
    
    +  template<typename InputIterator, typename EdgePropertyIterator>
    +  compressed_sparse_row_graph(InputIterator edge_begin, InputIterator edge_end,
    +                              EdgePropertyIterator ep_iter,
    +                              vertices_size_type numverts,
    +                              edges_size_type numedges = 0,
    +                              const GraphProperty& prop = GraphProperty());
    +    
    +

    + This constructor constructs a graph with numverts + vertices and the edges provided in the iterator range + [edge_begin, edge_end). Its semantics are identical + to the edge range constructor, except + that edge properties are also initialized. The type + EdgePropertyIterator must be a model of the InputIterator + concept whose value_type is convertible to + EdgeProperty. The iterator range [ep_iter, ep_ter + + m) will be used to initialize the properties on the edges + of the graph, where m is distance from + edge_begin to edge_end. +

    + +
    + +
    
    +  template<typename InputIterator>
    +  compressed_sparse_row_graph(InputIterator edge_begin, InputIterator edge_end,
    +                              vertices_size_type numverts,
    +                              edges_size_type numedges = 0,
    +                              const GraphProperty& prop = GraphProperty());
    +    
    + +

    + Constructs a graph with numverts vertices whose + edges are specified by the iterator range [edge_begin, + edge_end). The InputIterator must be a model of + InputIterator + whose value_type is an std::pair of + integer values. These integer values are the source and target + vertices for the edges, and must fall within the range [0, + numverts). The edges in [edge_begin, + edge_end) must be sorted so that all edges originating + from vertex i preceed any edges originating from all + vertices j where j > i. +

    + +

    + The value numedges, if provided, tells how many + edges are in the range [edge_begin, edge_end) and + will be used to preallocate data structures to save both memory + and time during construction. +

    + +

    + The value prop will be used to initialize the graph + property. +

    + +
    + +
    
    +  template<typename InputIterator, typename EdgePropertyIterator>
    +  compressed_sparse_row_graph(InputIterator edge_begin, InputIterator edge_end,
    +                              EdgePropertyIterator ep_iter,
    +                              vertices_size_type numverts,
    +                              edges_size_type numedges = 0,
    +                              const GraphProperty& prop = GraphProperty());
    +    
    +

    + This constructor constructs a graph with numverts + vertices and the edges provided in the iterator range + [edge_begin, edge_end). Its semantics are identical + to the edge range constructor, except + that edge properties are also initialized. The type + EdgePropertyIterator must be a model of the InputIterator + concept whose value_type is convertible to + EdgeProperty. The iterator range [ep_iter, ep_ter + + m) will be used to initialize the properties on the edges + of the graph, where m is distance from + edge_begin to edge_end. +

    + +
    + +
    
    +  template<typename InputIterator>
    +  compressed_sparse_row_graph(InputIterator edge_begin, InputIterator edge_end,
    +                              vertices_size_type numverts,
    +                              edges_size_type numedges = 0,
    +                              const GraphProperty& prop = GraphProperty());
    +    
    + +

    + Constructs a graph with numverts vertices whose + edges are specified by the iterator range [edge_begin, + edge_end). The InputIterator must be a model of + InputIterator + whose value_type is an std::pair of + integer values. These integer values are the source and target + vertices for the edges, and must fall within the range [0, + numverts). The edges in [edge_begin, + edge_end) must be sorted so that all edges originating + from vertex i preceed any edges originating from all + vertices j where j > i. +

    + +

    + The value numedges, if provided, tells how many + edges are in the range [edge_begin, edge_end) and + will be used to preallocate data structures to save both memory + and time during construction. +

    + +

    + The value prop will be used to initialize the graph + property. +

    + +
    + +
    
    +  template<typename InputIterator, typename EdgePropertyIterator>
    +  compressed_sparse_row_graph(InputIterator edge_begin, InputIterator edge_end,
    +                              EdgePropertyIterator ep_iter,
    +                              vertices_size_type numverts,
    +                              edges_size_type numedges = 0,
    +                              const GraphProperty& prop = GraphProperty());
    +    
    +

    + This constructor constructs a graph with numverts + vertices and the edges provided in the iterator range + [edge_begin, edge_end). Its semantics are identical + to the edge range constructor, except + that edge properties are also initialized. The type + EdgePropertyIterator must be a model of the InputIterator + concept whose value_type is convertible to + EdgeProperty. The iterator range [ep_iter, ep_ter + + m) will be used to initialize the properties on the edges + of the graph, where m is distance from + edge_begin to edge_end. +

    + +
    + +
    
    +  template<typename InputIterator>
    +  compressed_sparse_row_graph(InputIterator edge_begin, InputIterator edge_end,
    +                              vertices_size_type numverts,
    +                              edges_size_type numedges = 0,
    +                              const GraphProperty& prop = GraphProperty());
    +    
    + +

    + Constructs a graph with numverts vertices whose + edges are specified by the iterator range [edge_begin, + edge_end). The InputIterator must be a model of + InputIterator + whose value_type is an std::pair of + integer values. These integer values are the source and target + vertices for the edges, and must fall within the range [0, + numverts). The edges in [edge_begin, + edge_end) must be sorted so that all edges originating + from vertex i preceed any edges originating from all + vertices j where j > i. +

    + +

    + The value numedges, if provided, tells how many + edges are in the range [edge_begin, edge_end) and + will be used to preallocate data structures to save both memory + and time during construction. +

    + +

    + The value prop will be used to initialize the graph + property. +

    + +
    + +
    
    +  template<typename InputIterator, typename EdgePropertyIterator>
    +  compressed_sparse_row_graph(InputIterator edge_begin, InputIterator edge_end,
    +                              EdgePropertyIterator ep_iter,
    +                              vertices_size_type numverts,
    +                              edges_size_type numedges = 0,
    +                              const GraphProperty& prop = GraphProperty());
    +    
    +

    + This constructor constructs a graph with numverts + vertices and the edges provided in the iterator range + [edge_begin, edge_end). Its semantics are identical + to the edge range constructor, except + that edge properties are also initialized. The type + EdgePropertyIterator must be a model of the InputIterator + concept whose value_type is convertible to + EdgeProperty. The iterator range [ep_iter, ep_ter + + m) will be used to initialize the properties on the edges + of the graph, where m is distance from + edge_begin to edge_end. +

    + +
    + +
    
    +  template<typename InputIterator>
    +  compressed_sparse_row_graph(InputIterator edge_begin, InputIterator edge_end,
    +                              vertices_size_type numverts,
    +                              edges_size_type numedges = 0,
    +                              const GraphProperty& prop = GraphProperty());
    +    
    + +

    + Constructs a graph with numverts vertices whose + edges are specified by the iterator range [edge_begin, + edge_end). The InputIterator must be a model of + InputIterator + whose value_type is an std::pair of + integer values. These integer values are the source and target + vertices for the edges, and must fall within the range [0, + numverts). The edges in [edge_begin, + edge_end) must be sorted so that all edges originating + from vertex i preceed any edges originating from all + vertices j where j > i. +

    + +

    + The value numedges, if provided, tells how many + edges are in the range [edge_begin, edge_end) and + will be used to preallocate data structures to save both memory + and time during construction. +

    + +

    + The value prop will be used to initialize the graph + property. +

    + +
    + +
    
    +  template<typename InputIterator, typename EdgePropertyIterator>
    +  compressed_sparse_row_graph(InputIterator edge_begin, InputIterator edge_end,
    +                              EdgePropertyIterator ep_iter,
    +                              vertices_size_type numverts,
    +                              edges_size_type numedges = 0,
    +                              const GraphProperty& prop = GraphProperty());
    +    
    +

    + This constructor constructs a graph with numverts + vertices and the edges provided in the iterator range + [edge_begin, edge_end). Its semantics are identical + to the edge range constructor, except + that edge properties are also initialized. The type + EdgePropertyIterator must be a model of the InputIterator + concept whose value_type is convertible to + EdgeProperty. The iterator range [ep_iter, ep_ter + + m) will be used to initialize the properties on the edges + of the graph, where m is distance from + edge_begin to edge_end. +

    + +
    + +
    
    +  template<typename InputIterator>
    +  compressed_sparse_row_graph(InputIterator edge_begin, InputIterator edge_end,
    +                              vertices_size_type numverts,
    +                              edges_size_type numedges = 0,
    +                              const GraphProperty& prop = GraphProperty());
    +    
    + +

    + Constructs a graph with numverts vertices whose + edges are specified by the iterator range [edge_begin, + edge_end). The InputIterator must be a model of + InputIterator + whose value_type is an std::pair of + integer values. These integer values are the source and target + vertices for the edges, and must fall within the range [0, + numverts). The edges in [edge_begin, + edge_end) must be sorted so that all edges originating + from vertex i preceed any edges originating from all + vertices j where j > i. +

    + +

    + The value numedges, if provided, tells how many + edges are in the range [edge_begin, edge_end) and + will be used to preallocate data structures to save both memory + and time during construction. +

    + +

    + The value prop will be used to initialize the graph + property. +

    + +
    + +
    
    +  template<typename InputIterator, typename EdgePropertyIterator>
    +  compressed_sparse_row_graph(InputIterator edge_begin, InputIterator edge_end,
    +                              EdgePropertyIterator ep_iter,
    +                              vertices_size_type numverts,
    +                              edges_size_type numedges = 0,
    +                              const GraphProperty& prop = GraphProperty());
    +    
    +

    + This constructor constructs a graph with numverts + vertices and the edges provided in the iterator range + [edge_begin, edge_end). Its semantics are identical + to the edge range constructor, except + that edge properties are also initialized. The type + EdgePropertyIterator must be a model of the InputIterator + concept whose value_type is convertible to + EdgeProperty. The iterator range [ep_iter, ep_ter + + m) will be used to initialize the properties on the edges + of the graph, where m is distance from + edge_begin to edge_end. +

    + +
    + +
    
    +  template<typename InputIterator>
    +  compressed_sparse_row_graph(InputIterator edge_begin, InputIterator edge_end,
    +                              vertices_size_type numverts,
    +                              edges_size_type numedges = 0,
    +                              const GraphProperty& prop = GraphProperty());
    +    
    + +

    + Constructs a graph with numverts vertices whose + edges are specified by the iterator range [edge_begin, + edge_end). The InputIterator must be a model of + InputIterator + whose value_type is an std::pair of + integer values. These integer values are the source and target + vertices for the edges, and must fall within the range [0, + numverts). The edges in [edge_begin, + edge_end) must be sorted so that all edges originating + from vertex i preceed any edges originating from all + vertices j where j > i. +

    + +

    + The value numedges, if provided, tells how many + edges are in the range [edge_begin, edge_end) and + will be used to preallocate data structures to save both memory + and time during construction. +

    + +

    + The value prop will be used to initialize the graph + property. +

    + +
    + +
    
    +  template<typename InputIterator, typename EdgePropertyIterator>
    +  compressed_sparse_row_graph(InputIterator edge_begin, InputIterator edge_end,
    +                              EdgePropertyIterator ep_iter,
    +                              vertices_size_type numverts,
    +                              edges_size_type numedges = 0,
    +                              const GraphProperty& prop = GraphProperty());
    +    
    +

    + This constructor constructs a graph with numverts + vertices and the edges provided in the iterator range + [edge_begin, edge_end). Its semantics are identical + to the edge range constructor, except + that edge properties are also initialized. The type + EdgePropertyIterator must be a model of the InputIterator + concept whose value_type is convertible to + EdgeProperty. The iterator range [ep_iter, ep_ter + + m) will be used to initialize the properties on the edges + of the graph, where m is distance from + edge_begin to edge_end. +

    + +
    + +
    
    +  template<typename InputIterator>
    +  compressed_sparse_row_graph(InputIterator edge_begin, InputIterator edge_end,
    +                              vertices_size_type numverts,
    +                              edges_size_type numedges = 0,
    +                              const GraphProperty& prop = GraphProperty());
    +    
    + +

    + Constructs a graph with numverts vertices whose + edges are specified by the iterator range [edge_begin, + edge_end). The InputIterator must be a model of + InputIterator + whose value_type is an std::pair of + integer values. These integer values are the source and target + vertices for the edges, and must fall within the range [0, + numverts). The edges in [edge_begin, + edge_end) must be sorted so that all edges originating + from vertex i preceed any edges originating from all + vertices j where j > i. +

    + +

    + The value numedges, if provided, tells how many + edges are in the range [edge_begin, edge_end) and + will be used to preallocate data structures to save both memory + and time during construction. +

    + +

    + The value prop will be used to initialize the graph + property. +

    + +
    + +
    
    +  template<typename InputIterator, typename EdgePropertyIterator>
    +  compressed_sparse_row_graph(InputIterator edge_begin, InputIterator edge_end,
    +                              EdgePropertyIterator ep_iter,
    +                              vertices_size_type numverts,
    +                              edges_size_type numedges = 0,
    +                              const GraphProperty& prop = GraphProperty());
    +    
    +

    + This constructor constructs a graph with numverts + vertices and the edges provided in the iterator range + [edge_begin, edge_end). Its semantics are identical + to the edge range constructor, except + that edge properties are also initialized. The type + EdgePropertyIterator must be a model of the InputIterator + concept whose value_type is convertible to + EdgeProperty. The iterator range [ep_iter, ep_ter + + m) will be used to initialize the properties on the edges + of the graph, where m is distance from + edge_begin to edge_end. +

    + +
    +
    
       template<typename InputIterator>
       compressed_sparse_row_graph(InputIterator edge_begin, InputIterator edge_end,
    @@ -501,35 +4345,6 @@ edge_descriptor add_vertices(vertex_descriptor src, vert
     
         
    -

    Edge access

    -
    
    -  std::pair<out_edge_iterator, out_edge_iterator> 
    -    edge_range(vertex_descriptor u, vertex_descriptor v, const compressed_sparse_row_graph&);
    -    
    - -

    - Returns all edges from u to v. Requires time - linear in the number of edges outgoing from u. -

    - -
    - -
    
    -  std::pair<edge_descriptor, bool> 
    -    edge(vertex_descriptor u, vertex_descriptor v, const compressed_sparse_row_graph&);
    -    
    - -

    - If there exists an edge (u, v) in the graph, returns the - descriptor for that edge and true; otherwise, the - second value in the pair will be false. If multiple - edges exist from u to v, the first edge will - be returned; use edge_range - to retrieve all edges. -

    - -
    -
    
       edge_descriptor edge_from_index(edges_size_type i, const compressed_sparse_row_graph&);
         
    diff --git a/include/boost/graph/compressed_sparse_row_graph.hpp b/include/boost/graph/compressed_sparse_row_graph.hpp index f9a35030..f3bfb8f1 100644 --- a/include/boost/graph/compressed_sparse_row_graph.hpp +++ b/include/boost/graph/compressed_sparse_row_graph.hpp @@ -40,6 +40,13 @@ namespace boost { // sparse row graph. This is an internal detail of the BGL. struct csr_graph_tag; +// A type (edges_are_sorted_t) and a value (edges_are_sorted) used to indicate +// that the edge list passed into the CSR graph is already sorted by source +// vertex. +struct edges_are_sorted_internal {}; +inline void edges_are_sorted(edges_are_sorted_internal) {} +typedef void (*edges_are_sorted_t)(edges_are_sorted_internal); + /**************************************************************************** * Local helper macros to reduce typing and clutter later on. * ****************************************************************************/ @@ -167,9 +174,84 @@ class compressed_sparse_row_graph m_rowstart[v] = 0; } + // From number of vertices and unsorted list of edges + template + compressed_sparse_row_graph(MultiPassInputIterator edge_begin, + MultiPassInputIterator edge_end, + vertices_size_type numverts, + const GraphProperty& prop = GraphProperty()) + : inherited_vertex_properties(numverts), m_rowstart(numverts + 1), + m_column(0), m_property(prop), m_last_source(numverts) + { + // Put the degree of each vertex v into m_rowstart[v + 1] + for (MultiPassInputIterator i = edge_begin; i != edge_end; ++i) + ++m_rowstart[i->first + 1]; + + // Compute the partial sum of the degrees to get the actual values of + // m_rowstart + EdgeIndex start_of_this_row = 0; + m_rowstart[0] = start_of_this_row; + for (vertices_size_type i = 1; i <= numverts; ++i) { + start_of_this_row += m_rowstart[i]; + m_rowstart[i] = start_of_this_row; + } + m_column.resize(m_rowstart.back()); + + // Bucket sort the edges by their source vertices, putting the targets into + // m_column. The index current_insert_positions[v] contains the next + // location to insert out edges for vertex v. + std::vector + current_insert_positions(m_rowstart.begin(), m_rowstart.begin() + numverts); + for (; edge_begin != edge_end; ++edge_begin) + m_column[current_insert_positions[edge_begin->first]++] = edge_begin->second; + + // Default-construct properties for edges + inherited_edge_properties::resize(m_column.size()); + } + + // From number of vertices and unsorted list of edges, plus edge properties + template + compressed_sparse_row_graph(MultiPassInputIterator edge_begin, + MultiPassInputIterator edge_end, + EdgePropertyIterator ep_iter, + vertices_size_type numverts, + const GraphProperty& prop = GraphProperty()) + : inherited_vertex_properties(numverts), m_rowstart(numverts + 1), + m_column(0), m_property(prop), m_last_source(numverts) + { + // Put the degree of each vertex v into m_rowstart[v + 1] + for (MultiPassInputIterator i = edge_begin; i != edge_end; ++i) + ++m_rowstart[i->first + 1]; + + // Compute the partial sum of the degrees to get the actual values of + // m_rowstart + EdgeIndex start_of_this_row = 0; + m_rowstart[0] = start_of_this_row; + for (vertices_size_type i = 1; i <= numverts; ++i) { + start_of_this_row += m_rowstart[i]; + m_rowstart[i] = start_of_this_row; + } + m_column.resize(m_rowstart.back()); + inherited_edge_properties::resize(m_rowstart.back()); + + // Bucket sort the edges by their source vertices, putting the targets into + // m_column. The index current_insert_positions[v] contains the next + // location to insert out edges for vertex v. + std::vector + current_insert_positions(m_rowstart.begin(), m_rowstart.begin() + numverts); + for (; edge_begin != edge_end; ++edge_begin) { + vertices_size_type source = edge_begin->first; + EdgeIndex insert_pos = current_insert_positions[source]; + ++current_insert_positions[source]; + m_column[insert_pos] = edge_begin->second; + inherited_edge_properties::operator[](insert_pos) = edge_begin->second; + } + } + // From number of vertices and sorted list of edges template - compressed_sparse_row_graph(InputIterator edge_begin, InputIterator edge_end, + compressed_sparse_row_graph(edges_are_sorted_t, + InputIterator edge_begin, InputIterator edge_end, vertices_size_type numverts, edges_size_type numedges = 0, const GraphProperty& prop = GraphProperty()) @@ -209,7 +291,8 @@ class compressed_sparse_row_graph // From number of vertices and sorted list of edges template - compressed_sparse_row_graph(InputIterator edge_begin, InputIterator edge_end, + compressed_sparse_row_graph(edges_are_sorted_t, + InputIterator edge_begin, InputIterator edge_end, EdgePropertyIterator ep_iter, vertices_size_type numverts, edges_size_type numedges = 0, @@ -292,13 +375,10 @@ class compressed_sparse_row_graph for (Vertex i = 0; i != numverts; ++i) { m_rowstart[i] = current_edge; g_vertex v = vertex(i, g); - EdgeIndex num_edges_before_this_vertex = current_edge; g_out_edge_iter ei, ei_end; for (tie(ei, ei_end) = out_edges(v, g); ei != ei_end; ++ei) { m_column[current_edge++] = get(vi, target(*ei, g)); } - std::sort(m_column.begin() + num_edges_before_this_vertex, - m_column.begin() + current_edge); } m_rowstart[numverts] = current_edge; m_last_source = numverts; @@ -387,8 +467,8 @@ add_vertices(typename BOOST_CSR_GRAPH_TYPE::vertices_size_type count, BOOST_CSR_ return old_num_verts_plus_one - 1; } -// This function requires that (src, tgt) be lexicographically at least as -// large as the largest edge in the graph so far +// This function requires that src be at least as large as the largest source +// in the graph so far template inline typename BOOST_CSR_GRAPH_TYPE::edge_descriptor add_edge(Vertex src, Vertex tgt, BOOST_CSR_GRAPH_TYPE& g) { @@ -404,8 +484,8 @@ add_edge(Vertex src, Vertex tgt, BOOST_CSR_GRAPH_TYPE& g) { return typename BOOST_CSR_GRAPH_TYPE::edge_descriptor(src, num_edges_orig); } -// This function requires that (src, tgt) be lexicographically at least as -// large as the largest edge in the graph so far +// This function requires that src be at least as large as the largest source +// in the graph so far template inline typename BOOST_CSR_GRAPH_TYPE::edge_descriptor add_edge(Vertex src, Vertex tgt, @@ -532,38 +612,6 @@ vertex(typename graph_traits::vertex_descriptor i, return i; } -// Unlike for an adjacency_matrix, edge_range and edge take lg(out_degree(i)) -// time -template -inline std::pair -edge_range(Vertex i, Vertex j, const BOOST_CSR_GRAPH_TYPE& g) -{ - typedef typename std::vector::const_iterator adj_iter; - typedef typename BOOST_CSR_GRAPH_TYPE::out_edge_iterator out_edge_iter; - typedef typename BOOST_CSR_GRAPH_TYPE::edge_descriptor edge_desc; - std::pair raw_adjacencies = adjacent_vertices(i, g); - std::pair adjacencies = - std::equal_range(raw_adjacencies.first, raw_adjacencies.second, j); - EdgeIndex idx_begin = adjacencies.first - g.m_column.begin(); - EdgeIndex idx_end = adjacencies.second - g.m_column.begin(); - return std::make_pair(out_edge_iter(edge_desc(i, idx_begin)), - out_edge_iter(edge_desc(i, idx_end))); -} - -template -inline std::pair -edge(Vertex i, Vertex j, const BOOST_CSR_GRAPH_TYPE& g) -{ - typedef typename BOOST_CSR_GRAPH_TYPE::out_edge_iterator out_edge_iter; - std::pair range = edge_range(i, j, g); - if (range.first == range.second) - return std::make_pair(typename BOOST_CSR_GRAPH_TYPE::edge_descriptor(), - false); - else - return std::make_pair(*range.first, true); -} - // Find an edge given its index in the graph template inline typename BOOST_CSR_GRAPH_TYPE::edge_descriptor diff --git a/test/csr_graph_test.cpp b/test/csr_graph_test.cpp index 6bd3e334..4d3349e9 100644 --- a/test/csr_graph_test.cpp +++ b/test/csr_graph_test.cpp @@ -181,11 +181,12 @@ void graph_test(const OrigGraph& g) boost::identity_property_map()); // Check constructing a graph from iterators - CSRGraphT g3(boost::make_transform_iterator(edges(g2).first, - make_edge_to_index_pair(g2)), - boost::make_transform_iterator(edges(g2).second, - make_edge_to_index_pair(g2)), - num_vertices(g)); + CSRGraphT g3(boost::edges_are_sorted, + boost::make_transform_iterator(edges(g2).first, + make_edge_to_index_pair(g2)), + boost::make_transform_iterator(edges(g2).second, + make_edge_to_index_pair(g2)), + num_vertices(g)); check_consistency(g3); BOOST_CHECK((std::size_t)std::distance(edges(g3).first, edges(g3).second) == num_edges(g3)); @@ -216,19 +217,17 @@ void graph_test(const OrigGraph& g) // Check edge_from_index (and implicitly the edge_index property map) for // each edge in g2 - // This test also checks for the correct sorting of the edge iteration std::size_t last_src = 0, last_tgt = 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)); - BOOST_CHECK(src > last_src || (src == last_src && tgt >= last_tgt)); + BOOST_CHECK(src >= last_src); last_src = src; last_tgt = tgt; } // Check out edge iteration and vertex iteration for sortedness - // Also, check a few runs of edge and edge_range CSRGraphT::vertex_iterator vi, vi_end; std::size_t last_vertex = 0; bool first_iter = true; @@ -239,25 +238,8 @@ void graph_test(const OrigGraph& g) first_iter = false; CSRGraphT::out_edge_iterator oei, oei_end; - std::size_t last_tgt = 0; for (boost::tie(oei, oei_end) = out_edges(*vi, g2); oei != oei_end; ++oei) { BOOST_CHECK(source(*oei, g2) == *vi); - CSRGraphT::vertex_descriptor tgtd = target(*oei, g2); - std::size_t tgt = get(boost::vertex_index, g2, tgtd); - BOOST_CHECK(tgt >= last_tgt); - last_tgt = tgt; - - std::pair edge_info = edge(*vi, tgtd, g2); - BOOST_CHECK(edge_info.second == true); - BOOST_CHECK(source(edge_info.first, g2) == *vi); - BOOST_CHECK(target(edge_info.first, g2) == tgtd); - std::pair er = - edge_range(*vi, tgtd, g2); - BOOST_CHECK(er.first != er.second); - for (; er.first != er.second; ++er.first) { - BOOST_CHECK(source(*er.first, g2) == *vi); - BOOST_CHECK(target(*er.first, g2) == tgtd); - } } // Find a vertex for testing @@ -268,14 +250,6 @@ void graph_test(const OrigGraph& g) if (target(*oei2, g2) == test_vertex) ++edge_count; } - - // Test edge and edge_range on an edge that may not be present - std::pair edge_info = - edge(*vi, test_vertex, g2); - BOOST_CHECK(edge_info.second == (edge_count != 0)); - std::pair er = - edge_range(*vi, test_vertex, g2); - BOOST_CHECK(er.second - er.first == edge_count); } // Run brandes_betweenness_centrality, which touches on a whole lot @@ -356,7 +330,7 @@ void test_vertex_and_edge_properties() double weights[6] = { 1.0, 1.0, 0.5, 1.0, 1.0, 0.5 }; double centrality[5] = { 0.0, 1.5, 0.0, 1.0, 0.5 }; - CSRGraphWithPropsT g(&edges_init[0], &edges_init[0] + 6, &weights[0], 5, 6); + CSRGraphWithPropsT g(boost::edges_are_sorted, &edges_init[0], &edges_init[0] + 6, &weights[0], 5, 6); brandes_betweenness_centrality (g, centrality_map(get(&Vertex::centrality, g)). @@ -404,5 +378,12 @@ int test_main(int argc, char* argv[]) test_graph_properties(); test_vertex_and_edge_properties(); + { + std::cout << "Testing CSR graph built from unsorted edges" << std::endl; + std::pair unsorted_edges[] = {std::make_pair(5, 0), std::make_pair(3, 2), std::make_pair(4, 1), std::make_pair(4, 0), std::make_pair(0, 2), std::make_pair(5, 2)}; + CSRGraphT g(unsorted_edges, unsorted_edges + sizeof(unsorted_edges) / sizeof(*unsorted_edges), 6); + graph_test(g); + } + return 0; } From 954100837b3ad5f557e95d05590ab3767c49a068 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Thu, 9 Apr 2009 03:03:44 +0000 Subject: [PATCH 128/224] Merged more changes (to Dijkstra dispatching) from PBGL [SVN r52276] --- .../boost/graph/dijkstra_shortest_paths.hpp | 46 ++++++++++++------- 1 file changed, 30 insertions(+), 16 deletions(-) diff --git a/include/boost/graph/dijkstra_shortest_paths.hpp b/include/boost/graph/dijkstra_shortest_paths.hpp index 14cf377e..d941766f 100644 --- a/include/boost/graph/dijkstra_shortest_paths.hpp +++ b/include/boost/graph/dijkstra_shortest_paths.hpp @@ -336,7 +336,8 @@ namespace boost { template + class DistInf, class DistZero, typename T, typename Tag, + typename Base> inline void dijkstra_shortest_paths (const VertexListGraph& g, @@ -344,7 +345,8 @@ namespace boost { PredecessorMap predecessor, DistanceMap distance, WeightMap weight, IndexMap index_map, Compare compare, Combine combine, DistInf inf, DistZero zero, - DijkstraVisitor vis + DijkstraVisitor vis, + const bgl_named_params& BOOST_GRAPH_ENABLE_IF_MODELS_PARM(VertexListGraph,vertex_list_graph_tag)) { boost::two_bit_color_map color(num_vertices(g), index_map); @@ -382,18 +384,37 @@ namespace boost { index_map, compare, combine, zero, vis, color); } + // 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, predecessor, distance, weight, index_map, + compare, combine, inf, zero, vis, + no_named_parameters()); + } + namespace detail { // Handle defaults for PredecessorMap and // Distance Compare, Combine, Inf and Zero template + class IndexMap, class Params> inline void dijkstra_dispatch2 (const VertexListGraph& g, typename graph_traits::vertex_descriptor s, DistanceMap distance, WeightMap weight, IndexMap index_map, - const Params& params, ColorMap color) + const Params& params) { // Default for predecessor map dummy_property_map p_map; @@ -413,17 +434,17 @@ namespace boost { D()), choose_param(get_param(params, graph_visitor), make_dijkstra_visitor(null_visitor())), - color); + params); } template + class IndexMap, class Params> inline void dijkstra_dispatch1 (const VertexListGraph& g, typename graph_traits::vertex_descriptor s, DistanceMap distance, WeightMap weight, IndexMap index_map, - const Params& params, ColorMap color) + const Params& params) { // Default for distance map typedef typename property_traits::value_type D; @@ -431,17 +452,11 @@ namespace boost { n = is_default_param(distance) ? num_vertices(g) : 1; std::vector distance_map(n); - // Default for color map - typename std::vector::size_type - m = is_default_param(color) ? num_vertices(g) : 1; - boost::two_bit_color_map color_map(m, index_map); - detail::dijkstra_dispatch2 (g, s, choose_param(distance, make_iterator_property_map (distance_map.begin(), index_map, distance_map[0])), - weight, index_map, params, - choose_param(color, color_map)); + weight, index_map, params); } } // namespace detail @@ -460,8 +475,7 @@ namespace boost { get_param(params, vertex_distance), choose_const_pmap(get_param(params, edge_weight), g, edge_weight), choose_const_pmap(get_param(params, vertex_index), g, vertex_index), - params, - get_param(params, vertex_color)); + params); } } // namespace boost From e674c8b9c78a6f84d1190221916750a8411734ab Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Thu, 9 Apr 2009 15:27:50 +0000 Subject: [PATCH 129/224] Replaced non-ASCII names with ASCII approximations [SVN r52295] --- example/adjacency_list_io.cpp | 2 +- example/property_iterator.cpp | 4 ++-- include/boost/graph/adjacency_list_io.hpp | 2 +- include/boost/graph/property_iter_range.hpp | 2 +- test/property_iter.cpp | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/example/adjacency_list_io.cpp b/example/adjacency_list_io.cpp index 565d1bac..ab626f89 100644 --- a/example/adjacency_list_io.cpp +++ b/example/adjacency_list_io.cpp @@ -1,4 +1,4 @@ -// (C) Copyright François Faure 2001 +// (C) Copyright Francois Faure 2001 // 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) diff --git a/example/property_iterator.cpp b/example/property_iterator.cpp index dbedabc4..d8e61cc3 100644 --- a/example/property_iterator.cpp +++ b/example/property_iterator.cpp @@ -1,5 +1,5 @@ -// (C) Copyright François Faure, iMAGIS-GRAVIR / UJF, 2001. +// (C) Copyright Francois Faure, iMAGIS-GRAVIR / UJF, 2001. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at @@ -8,7 +8,7 @@ // Revision History: // 03 May 2001 Jeremy Siek // Moved property iterator code to headers. -// 02 May 2001 François Faure +// 02 May 2001 Francois Faure // Initial version. #include diff --git a/include/boost/graph/adjacency_list_io.hpp b/include/boost/graph/adjacency_list_io.hpp index fb762fe0..660b4489 100644 --- a/include/boost/graph/adjacency_list_io.hpp +++ b/include/boost/graph/adjacency_list_io.hpp @@ -1,6 +1,6 @@ //======================================================================= // Copyright 2001 Universite Joseph Fourier, Grenoble. -// Author: François Faure +// Author: Francois Faure // // Distributed under the Boost Software License, Version 1.0. (See // accompanying file LICENSE_1_0.txt or copy at diff --git a/include/boost/graph/property_iter_range.hpp b/include/boost/graph/property_iter_range.hpp index 2518ad7b..5f166b6c 100644 --- a/include/boost/graph/property_iter_range.hpp +++ b/include/boost/graph/property_iter_range.hpp @@ -12,7 +12,7 @@ // differentiate between const/mutable graphs and // added a workaround to avoid partial specialization. -// 02 May 2001 François Faure +// 02 May 2001 Francois Faure // Initial version. #ifndef BOOST_GRAPH_PROPERTY_ITER_RANGE_HPP diff --git a/test/property_iter.cpp b/test/property_iter.cpp index d12ea63e..9ff0d642 100644 --- a/test/property_iter.cpp +++ b/test/property_iter.cpp @@ -4,7 +4,7 @@ // Railway Construction and Operation, // University of Hanover, Germany // -// Author: Jürgen Hunold +// Author: Juergen Hunold // // Use, modification and distribution are subject to the // Boost Software License, Version 1.0. (See accompanying file From 0d65535a49672b34e193773679cd00a9a8afaa8c Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Thu, 9 Apr 2009 15:29:14 +0000 Subject: [PATCH 130/224] Fixed broken link [SVN r52296] --- doc/metric_tsp_approx.html | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/doc/metric_tsp_approx.html b/doc/metric_tsp_approx.html index 335ce78e..11dde904 100644 --- a/doc/metric_tsp_approx.html +++ b/doc/metric_tsp_approx.html @@ -1,10 +1,10 @@ Boost Graph Library: Metric Traveling Salesperson Approximation @@ -176,7 +176,7 @@ The time complexity is O(E log V).

    The file test/metric_tsp_approx_example.cpp +href="../test/metric_tsp_approx.cpp">test/metric_tsp_approx.cpp contains an example of using this TSP approximation algorithm. From f09e7ab08c66ff7824163fb2c74143f8e69fab73 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Thu, 9 Apr 2009 15:41:38 +0000 Subject: [PATCH 131/224] Fixed use of undefined function log2 [SVN r52297] --- include/boost/graph/rmat_graph_generator.hpp | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/include/boost/graph/rmat_graph_generator.hpp b/include/boost/graph/rmat_graph_generator.hpp index 9c81e500..ed399c33 100644 --- a/include/boost/graph/rmat_graph_generator.hpp +++ b/include/boost/graph/rmat_graph_generator.hpp @@ -24,6 +24,14 @@ using boost::shared_ptr; using boost::uniform_01; +// Returns floor(log_2(n)), and -1 when n is 0 +template +inline int int_log2(IntegerType n) { + int l = 0; + while (n > 0) {++l; n >>= 1;} + return l - 1; +} + struct keep_all_edges { template bool operator()(const T&, const T&) { return true; } @@ -137,7 +145,7 @@ namespace boost { double d, bool permute_vertices = true) : gen(), n(n), a(a), b(b), c(c), d(d), edge(m), permute_vertices(permute_vertices), - SCALE(int(floor(log2(n)))) + SCALE(int_log2(n)) { this->gen.reset(new uniform_01(gen)); @@ -261,7 +269,7 @@ namespace boost { generate_permutation_vector(gen, vertexPermutation, n); // TODO: "Clip and flip" if undirected graph - int SCALE = int(floor(log2(n))); + int SCALE = int_log2(n); for (int i = 0; i < m; ++i) { @@ -361,7 +369,7 @@ namespace boost { if (permute_vertices) generate_permutation_vector(gen, vertexPermutation, n); - int SCALE = int(floor(log2(n))); + int SCALE = int_log2(n); std::map edge_map; @@ -474,7 +482,7 @@ namespace boost { if (permute_vertices) generate_permutation_vector(gen, vertexPermutation, n); - int SCALE = int(floor(log2(n))); + int SCALE = int_log2(n); std::map edge_map; From faeb40f7c474d14600707e675d467fc8f36bbff4 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Thu, 9 Apr 2009 21:10:55 +0000 Subject: [PATCH 132/224] Merged headers and source files (but not examples, tests, or docs) from Parallel BGL [SVN r52300] --- build/Jamfile.v2 | 27 +- include/boost/graph/breadth_first_search.hpp | 21 + include/boost/graph/connected_components.hpp | 3 + include/boost/graph/depth_first_search.hpp | 3 + .../boost/graph/dijkstra_shortest_paths.hpp | 4 + include/boost/graph/fruchterman_reingold.hpp | 4 + include/boost/graph/graphviz.hpp | 4 + include/boost/graph/page_rank.hpp | 4 + include/boost/graph/rmat_graph_generator.hpp | 4 + include/boost/graph/strong_components.hpp | 4 + include/boost/graph/topology.hpp | 21 + include/boost/graph/two_bit_color_map.hpp | 4 + include/boost/graph/use_mpi.hpp | 15 + src/mpi_process_group.cpp | 1108 +++++++++++++++++ src/tag_allocator.cpp | 45 + 15 files changed, 1270 insertions(+), 1 deletion(-) create mode 100644 include/boost/graph/use_mpi.hpp create mode 100644 src/mpi_process_group.cpp create mode 100644 src/tag_allocator.cpp diff --git a/build/Jamfile.v2 b/build/Jamfile.v2 index 7e8da510..a7f70c4d 100644 --- a/build/Jamfile.v2 +++ b/build/Jamfile.v2 @@ -4,6 +4,8 @@ # (See accompanying file LICENSE_1_0.txt or copy at # http://www.boost.org/LICENSE_1_0.txt) +import mpi ; + project boost/graph : requirements ../src : source-location ../src @@ -43,10 +45,33 @@ else } explicit graphml ; +if [ mpi.configured ] +{ + alias pbgl + : mpi_process_group.cpp tag_allocator.cpp + : # requirements + ../../mpi/build//boost_mpi + /mpi//mpi [ mpi.extra-requirements ] + : # default built + : # usage requirements + ../../mpi/build//boost_mpi + /mpi//mpi [ mpi.extra-requirements ] + ; +} +else +{ + message pbgl + : "warning: Graph library does not contain MPI-based parallel components." + : "note: to enable them, add \"using mpi ;\" to your user_config.jam" + ; +} +explicit graphml ; + lib boost_graph : read_graphviz_spirit.cpp graphml + pbgl : BOOST_GRAPH_NO_LIB=1 shared:BOOST_GRAPH_DYN_LINK=1 @@ -57,4 +82,4 @@ lib boost_graph msvc-8.0:-GR- ; -boost-install boost_graph ; \ No newline at end of file +boost-install boost_graph ; diff --git a/include/boost/graph/breadth_first_search.hpp b/include/boost/graph/breadth_first_search.hpp index e59f89d8..d28ad3ff 100644 --- a/include/boost/graph/breadth_first_search.hpp +++ b/include/boost/graph/breadth_first_search.hpp @@ -25,6 +25,10 @@ #include #include +#ifdef BOOST_GRAPH_USE_MPI +#include +#endif // BOOST_GRAPH_USE_MPI + namespace boost { template @@ -230,6 +234,19 @@ namespace boost { vis, color); } +#ifdef BOOST_GRAPH_USE_MPI + template + void bfs_helper + (DistributedGraph& g, + typename graph_traits::vertex_descriptor s, + ColorMap color, + BFSVisitor vis, + const bgl_named_params& params, + BOOST_GRAPH_ENABLE_IF_MODELS(DistributedGraph, distributed_graph_tag, + void)* = 0); +#endif // BOOST_GRAPH_USE_MPI + //------------------------------------------------------------------------- // Choose between default color and color parameters. Using // function dispatching so that we don't require vertex index if @@ -329,5 +346,9 @@ namespace boost { } // namespace boost +#ifdef BOOST_GRAPH_USE_MPI +# include +#endif + #endif // BOOST_GRAPH_BREADTH_FIRST_SEARCH_HPP diff --git a/include/boost/graph/connected_components.hpp b/include/boost/graph/connected_components.hpp index 326e62da..90015e67 100644 --- a/include/boost/graph/connected_components.hpp +++ b/include/boost/graph/connected_components.hpp @@ -99,5 +99,8 @@ namespace boost { } // namespace boost +#ifdef BOOST_GRAPH_USE_MPI +# include +#endif #endif // BOOST_GRAPH_CONNECTED_COMPONENTS_HPP diff --git a/include/boost/graph/depth_first_search.hpp b/include/boost/graph/depth_first_search.hpp index b1377409..51820d7b 100644 --- a/include/boost/graph/depth_first_search.hpp +++ b/include/boost/graph/depth_first_search.hpp @@ -358,5 +358,8 @@ namespace boost { } } // namespace boost +#ifdef BOOST_GRAPH_USE_MPI +# include +#endif #endif diff --git a/include/boost/graph/dijkstra_shortest_paths.hpp b/include/boost/graph/dijkstra_shortest_paths.hpp index d941766f..d7456734 100644 --- a/include/boost/graph/dijkstra_shortest_paths.hpp +++ b/include/boost/graph/dijkstra_shortest_paths.hpp @@ -480,4 +480,8 @@ namespace boost { } // namespace boost +#ifdef BOOST_GRAPH_USE_MPI +# include +#endif + #endif // BOOST_GRAPH_DIJKSTRA_HPP diff --git a/include/boost/graph/fruchterman_reingold.hpp b/include/boost/graph/fruchterman_reingold.hpp index 65b4a938..0f999d82 100644 --- a/include/boost/graph/fruchterman_reingold.hpp +++ b/include/boost/graph/fruchterman_reingold.hpp @@ -457,4 +457,8 @@ fruchterman_reingold_force_directed_layout } // end namespace boost +#ifdef BOOST_GRAPH_USE_MPI +# include +#endif + #endif // BOOST_GRAPH_FRUCHTERMAN_REINGOLD_FORCE_DIRECTED_LAYOUT_HPP diff --git a/include/boost/graph/graphviz.hpp b/include/boost/graph/graphviz.hpp index 43387883..5809923c 100644 --- a/include/boost/graph/graphviz.hpp +++ b/include/boost/graph/graphviz.hpp @@ -794,4 +794,8 @@ bool read_graphviz(std::istream& in, MutableGraph& graph, # include #endif // BOOST_GRAPH_READ_GRAPHVIZ_ITERATORS +#ifdef BOOST_GRAPH_USE_MPI +# include +#endif + #endif // BOOST_GRAPHVIZ_HPP diff --git a/include/boost/graph/page_rank.hpp b/include/boost/graph/page_rank.hpp index f7c38985..9532260f 100644 --- a/include/boost/graph/page_rank.hpp +++ b/include/boost/graph/page_rank.hpp @@ -154,4 +154,8 @@ remove_dangling_links(MutableGraph& g } } // end namespace boost::graph +#ifdef BOOST_GRAPH_USE_MPI +# include +#endif + #endif // BOOST_GRAPH_PAGE_RANK_HPP diff --git a/include/boost/graph/rmat_graph_generator.hpp b/include/boost/graph/rmat_graph_generator.hpp index ed399c33..96b34879 100644 --- a/include/boost/graph/rmat_graph_generator.hpp +++ b/include/boost/graph/rmat_graph_generator.hpp @@ -581,4 +581,8 @@ namespace boost { } // end namespace boost +#ifdef BOOST_GRAPH_USE_MPI +#include +#endif // BOOST_GRAPH_USE_MPI + #endif // BOOST_GRAPH_RMAT_GENERATOR_HPP diff --git a/include/boost/graph/strong_components.hpp b/include/boost/graph/strong_components.hpp index 1931d86f..9469010a 100644 --- a/include/boost/graph/strong_components.hpp +++ b/include/boost/graph/strong_components.hpp @@ -334,4 +334,8 @@ namespace boost { } // namespace boost +#ifdef BOOST_GRAPH_USE_MPI +# include +#endif + #endif // BOOST_GRAPH_STRONG_COMPONENTS_HPP diff --git a/include/boost/graph/topology.hpp b/include/boost/graph/topology.hpp index 79847137..23ae92ab 100644 --- a/include/boost/graph/topology.hpp +++ b/include/boost/graph/topology.hpp @@ -246,6 +246,13 @@ class hypercube_topology : public convex_topology return dist; } + point_type center() const { + point_type result; + for (std::size_t i = 0; i < Dims; ++i) + result[i] = 0; + return result; + } + private: shared_ptr gen_ptr; shared_ptr rand; @@ -319,6 +326,13 @@ class rectangle_topology : public convex_topology<2> return dist; } + point_type center() const { + point_type result; + result[0] = (left + right) / 2.; + result[1] = (top + bottom) / 2.; + return result; + } + private: shared_ptr gen_ptr; shared_ptr rand; @@ -392,6 +406,13 @@ class ball_topology : public convex_topology return radius - r; } + point_type center() const { + point_type result; + for (std::size_t i = 0; i < Dims; ++i) + result[i] = 0; + return result; + } + private: shared_ptr gen_ptr; shared_ptr rand; diff --git a/include/boost/graph/two_bit_color_map.hpp b/include/boost/graph/two_bit_color_map.hpp index 1b2c7705..3dbcdcef 100644 --- a/include/boost/graph/two_bit_color_map.hpp +++ b/include/boost/graph/two_bit_color_map.hpp @@ -91,3 +91,7 @@ make_two_bit_color_map(std::size_t n, const IndexMap& index_map) } // end namespace boost #endif // BOOST_TWO_BIT_COLOR_MAP_HPP + +#ifdef BOOST_GRAPH_USE_MPI +# include +#endif diff --git a/include/boost/graph/use_mpi.hpp b/include/boost/graph/use_mpi.hpp new file mode 100644 index 00000000..b77f9c0b --- /dev/null +++ b/include/boost/graph/use_mpi.hpp @@ -0,0 +1,15 @@ +// Copyright (C) 2004-2009 The Trustees of Indiana University. + +// 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) + +// Authors: Nick Edmonds +// Andrew Lumsdaine + +#ifndef BOOST_GRAPH_USE_MPI_HPP +#define BOOST_GRAPH_USE_MPI_HPP + +#define BOOST_GRAPH_USE_MPI + +#endif // BOOST_GRAPH_USE_MPI_HPP diff --git a/src/mpi_process_group.cpp b/src/mpi_process_group.cpp new file mode 100644 index 00000000..62ff7ada --- /dev/null +++ b/src/mpi_process_group.cpp @@ -0,0 +1,1108 @@ +// Copyright (C) 2004-2006 The Trustees of Indiana University. +// Copyright (C) 2007 Douglas Gregor +// Copyright (C) 2007 Matthias Troyer + +// 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) + +// Authors: Douglas Gregor +// Andrew Lumsdaine +// Matthias Troyer +#include +#include +#include +#include +#include +#include + +//#define DEBUG 1 + + +//#define MAX_BATCHES 1500 +#define PREALLOCATE_BATCHES 250 +// 500 is a better setting for PREALLOCATE_BATCHES if you're not using process +// subgroups and are building 64-bit binaries. 250 allows all the CTest +// tests to pass in both 32 and 64-bit modes. If you create multiple process +// groups with PREALLOCATE_BATCHES at a reasonable level in 32-bit mode you +// _will_ run out of memory and get "malloc failed" errors + +//#define NO_ISEND_BATCHES +//#define NO_IMMEDIATE_PROCESSING +//#define NO_SPLIT_BATCHES +#define IRECV_BATCH + +// we cannot keep track of how many we received if we do not process them +#ifdef NO_IMMEDIATE_PROCESSING +#undef IRECV_BATCH +#endif + +#ifdef DEBUG +# include +#endif // DEBUG + +namespace boost { namespace graph { namespace distributed { + +struct mpi_process_group::deallocate_block +{ + explicit deallocate_block(blocks_type* blocks) : blocks(blocks) { } + + void operator()(int* block_num) + { + block_type* block = (*blocks)[*block_num]; + + // Mark this block as inactive + (*blocks)[*block_num] = 0; + +#ifdef DEBUG + fprintf(stderr, "Processor %i deallocated block #%i\n", + boost::mpi::communicator().rank(), *block_num); +#endif + + // Delete the block and its block number + delete block_num; + delete block; + } + +private: + blocks_type* blocks; +}; + +mpi_process_group::impl::incoming_messages::incoming_messages() +{ + next_header.push_back(headers.begin()); +} + +mpi_process_group::impl::impl(std::size_t num_headers, std::size_t buffer_sz, + communicator_type parent_comm) + : comm(parent_comm, boost::mpi::comm_duplicate), + oob_reply_comm(parent_comm, boost::mpi::comm_duplicate), + allocated_tags(boost::mpi::environment::max_tag()) +{ + max_sent=0; + max_received=0; + int n = comm.size(); + outgoing.resize(n); + incoming.resize(n); + + // no synchronization stage means -1 + // to keep the convention + synchronizing_stage.resize(n,-1); + number_sent_batches.resize(n); + number_received_batches.resize(n); + trigger_context = trc_none; + processing_batches = 0; + + // Allocator a placeholder block "0" + blocks.push_back(new block_type); + + synchronizing = false; + + set_batch_size(num_headers,buffer_sz); + + for (int i = 0; i < n; ++i) { + incoming[i].next_header.front() = incoming[i].headers.end(); + outgoing[i].buffer.reserve(batch_message_size); + } + +#ifdef PREALLOCATE_BATCHES + batch_pool.resize(PREALLOCATE_BATCHES); + for (std::size_t i = 0 ; i < batch_pool.size(); ++i) { + batch_pool[i].buffer.reserve(batch_message_size); + batch_pool[i].request=MPI_REQUEST_NULL; + free_batches.push(i); + } +#endif +} + +void mpi_process_group::impl::set_batch_size(std::size_t header_num, std::size_t buffer_sz) +{ + batch_header_number = header_num; + batch_buffer_size = buffer_sz; + + // determine batch message size by serializing the largest possible batch + outgoing_messages msg; + msg.headers.resize(batch_header_number); + msg.buffer.resize(batch_buffer_size); + boost::mpi::packed_oarchive oa(comm); + oa << const_cast(msg); + batch_message_size = oa.size(); +} + + +mpi_process_group::impl::~impl() +{ + // Delete the placeholder "0" block + delete blocks.front(); + if (!boost::mpi::environment::finalized()) + for (std::vector::iterator it=requests.begin(); + it != requests.end();++it) + MPI_Cancel(&(*it)); +} + +namespace detail { +// global batch handlers +void handle_batch (mpi_process_group const& self, int source, int, + mpi_process_group::outgoing_messages& batch,bool out_of_band) +{ +#ifdef DEBUG + std::cerr << "Processing batch trigger\n"; + std::cerr << "BATCH: " << process_id(self) << " <- " << source << " (" + << batch.headers.size() << " headers, " + << batch.buffer.size() << " bytes)" + << std::endl; +#endif + // If we are not synchronizing, then this must be an early receive + trigger_receive_context old_context = self.impl_->trigger_context; + if (self.impl_->trigger_context != trc_in_synchronization) + self.impl_->trigger_context = trc_early_receive; + + // Receive the batched messages + self.receive_batch(source,batch); + + // Restore the previous context + self.impl_->trigger_context = old_context; +} + +// synchronization handler +void handle_sync (mpi_process_group const& self, int source, int tag, int val, + bool) +{ + // increment the stage for the source + std::size_t stage = static_cast( + ++self.impl_->synchronizing_stage[source]); + + assert(source != process_id(self)); + +#ifdef DEBUG + std::ostringstream out; + out << process_id(self) << ": handle_sync from " << source + << " (stage = " << self.impl_->synchronizing_stage[source] << ")\n"; + std::cerr << out.str(); +#endif + + // record how many still have messages to be sent + if (self.impl_->synchronizing_unfinished.size()<=stage) { + assert(self.impl_->synchronizing_unfinished.size() == stage); + self.impl_->synchronizing_unfinished.push_back(val >= 0 ? 1 : 0); + } + else + self.impl_->synchronizing_unfinished[stage]+=(val >= 0 ? 1 : 0); + + // record how many are in that stage + if (self.impl_->processors_synchronizing_stage.size()<=stage) { + assert(self.impl_->processors_synchronizing_stage.size() == stage); + self.impl_->processors_synchronizing_stage.push_back(1); + } + else + ++self.impl_->processors_synchronizing_stage[stage]; + + // subtract how many batches we were supposed to receive + if (val>0) + self.impl_->number_received_batches[source] -= val; +} + + +} + +mpi_process_group::mpi_process_group(communicator_type parent_comm) +{ + // 64K messages and 1MB buffer turned out to be a reasonable choice + impl_.reset(new impl(64*1024,1024*1024,parent_comm)); +#ifndef IRECV_BATCH + global_trigger(msg_batch,&detail::handle_batch); +#else // use irecv version by providing a maximum buffer size + global_trigger(msg_batch,&detail::handle_batch, + impl_->batch_message_size); +#endif + global_trigger(msg_large_batch,&detail::handle_batch); + global_trigger(msg_synchronizing,&detail::handle_sync); + rank = impl_->comm.rank(); + size = impl_->comm.size(); + +#ifdef SEND_OOB_BSEND + // let us try with a default bufferr size of 16 MB + if (!message_buffer_size()) + set_message_buffer_size(16*1024*1024); +#endif +} + +mpi_process_group::mpi_process_group(std::size_t h, std::size_t sz, + communicator_type parent_comm) +{ + impl_.reset(new impl(h,sz,parent_comm)); +#ifndef IRECV_BATCH + global_trigger(msg_batch,&detail::handle_batch); +#else // use irecv version by providing a maximum buffer size + global_trigger(msg_batch,&detail::handle_batch, + impl_->batch_message_size); +#endif + global_trigger(msg_large_batch,&detail::handle_batch); + global_trigger(msg_synchronizing,&detail::handle_sync); + rank = impl_->comm.rank(); + size = impl_->comm.size(); +#ifdef SEND_OOB_BSEND + // let us try with a default bufferr size of 16 MB + if (!message_buffer_size()) + set_message_buffer_size(16*1024*1024); +#endif +} + +mpi_process_group::mpi_process_group(const mpi_process_group& other, + const receiver_type& handler, bool) + : impl_(other.impl_) +{ + rank = impl_->comm.rank(); + size = impl_->comm.size(); + replace_handler(handler); +} + +mpi_process_group::mpi_process_group(const mpi_process_group& other, + attach_distributed_object, bool) + : impl_(other.impl_) +{ + rank = impl_->comm.rank(); + size = impl_->comm.size(); + allocate_block(); + + for (std::size_t i = 0; i < impl_->incoming.size(); ++i) { + if (my_block_number() >= (int)impl_->incoming[i].next_header.size()) { + impl_->incoming[i].next_header + .push_back(impl_->incoming[i].headers.begin()); + } else { + impl_->incoming[i].next_header[my_block_number()] = + impl_->incoming[i].headers.begin(); + } + +#ifdef DEBUG + if (process_id(*this) == 0) { + std::cerr << "Allocated tag block " << my_block_number() << std::endl; + } +#endif + } +} + +mpi_process_group::~mpi_process_group() { + /* + std::string msg = boost::lexical_cast(process_id(*this)) + " " + + boost::lexical_cast(impl_->max_received) + " " + + boost::lexical_cast(impl_->max_sent) + "\n"; + std::cerr << msg << "\n"; + */ +} + + +mpi_process_group::communicator_type communicator(const mpi_process_group& pg) +{ return pg.impl_->comm; } + +void +mpi_process_group::replace_handler(const receiver_type& handler, + bool out_of_band_receive) +{ + make_distributed_object(); + + // Attach the receive handler + impl_->blocks[my_block_number()]->on_receive = handler; +} + +void +mpi_process_group::make_distributed_object() +{ + if (my_block_number() == 0) { + allocate_block(); + + for (std::size_t i = 0; i < impl_->incoming.size(); ++i) { + if (my_block_number() >= (int)impl_->incoming[i].next_header.size()) { + impl_->incoming[i].next_header + .push_back(impl_->incoming[i].headers.begin()); + } else { + impl_->incoming[i].next_header[my_block_number()] = + impl_->incoming[i].headers.begin(); + } + +#ifdef DEBUG + if (process_id(*this) == 0) { + std::cerr << "Allocated tag block " << my_block_number() << std::endl; + } +#endif + } + } else { + // Clear out the existing triggers + std::vector >() + .swap(impl_->blocks[my_block_number()]->triggers); + } + + // Clear out the receive handler + impl_->blocks[my_block_number()]->on_receive = 0; +} + +void +mpi_process_group:: +replace_on_synchronize_handler(const on_synchronize_event_type& handler) +{ + if (my_block_number() > 0) + impl_->blocks[my_block_number()]->on_synchronize = handler; +} + +int mpi_process_group::allocate_block(bool out_of_band_receive) +{ + assert(!block_num); + block_iterator i = impl_->blocks.begin(); + while (i != impl_->blocks.end() && *i) ++i; + + if (i == impl_->blocks.end()) { + impl_->blocks.push_back(new block_type()); + i = impl_->blocks.end() - 1; + } else { + *i = new block_type(); + } + + block_num.reset(new int(i - impl_->blocks.begin()), + deallocate_block(&impl_->blocks)); + +#ifdef DEBUG + fprintf(stderr, + "Processor %i allocated block #%i\n", process_id(*this), *block_num); +#endif + + return *block_num; +} + +bool mpi_process_group::maybe_emit_receive(int process, int encoded_tag) const +{ + std::pair decoded = decode_tag(encoded_tag); + + assert (decoded.first < static_cast(impl_->blocks.size())); + + block_type* block = impl_->blocks[decoded.first]; + if (!block) { + std::cerr << "Received message from process " << process << " with tag " + << decoded.second << " for non-active block " + << decoded.first << std::endl; + std::cerr << "Active blocks are: "; + for (std::size_t i = 0; i < impl_->blocks.size(); ++i) + if (impl_->blocks[i]) + std::cerr << i << ' '; + std::cerr << std::endl; + assert(block); + } + + if (decoded.second < static_cast(block->triggers.size()) + && block->triggers[decoded.second]) { + // We have a trigger for this message; use it + trigger_receive_context old_context = impl_->trigger_context; + impl_->trigger_context = trc_out_of_band; + block->triggers[decoded.second]->receive(*this, process, decoded.second, + impl_->trigger_context, + decoded.first); + impl_->trigger_context = old_context; + } + else + return false; + // We receives the message above + return true; +} + +bool mpi_process_group::emit_receive(int process, int encoded_tag) const +{ + std::pair decoded = decode_tag(encoded_tag); + + if (decoded.first >= static_cast(impl_->blocks.size())) + // This must be an out-of-band message destined for + // send_oob_with_reply; ignore it. + return false; + + // Find the block that will receive this message + block_type* block = impl_->blocks[decoded.first]; + assert(block); + if (decoded.second < static_cast(block->triggers.size()) + && block->triggers[decoded.second]) + // We have a trigger for this message; use it + block->triggers[decoded.second]->receive(*this,process, decoded.second, + impl_->trigger_context); + else if (block->on_receive) + // Fall back to the normal message handler + block->on_receive(process, decoded.second); + else + // There was no handler for this message + return false; + + // The message was handled above + return true; +} + +void mpi_process_group::emit_on_synchronize() const +{ + for (block_iterator i = impl_->blocks.begin(); i != impl_->blocks.end(); ++i) + if (*i && (*i)->on_synchronize) (*i)->on_synchronize(); +} + + +optional > +mpi_process_group::probe() const +{ +#ifdef DEBUG + std::cerr << "PROBE: " << process_id(*this) << ", tag block = " + << my_block_number() << std::endl; +#endif + + typedef std::pair result_type; + + int tag_block = my_block_number(); + + for (std::size_t source = 0; source < impl_->incoming.size(); ++source) { + impl::incoming_messages& incoming = impl_->incoming[source]; + std::vector::iterator& i = + incoming.next_header[tag_block]; + std::vector::iterator end = incoming.headers.end(); + + while (i != end) { + if (i->tag != -1 && decode_tag(i->tag).first == my_block_number()) { +#ifdef DEBUG + std::cerr << "PROBE: " << process_id(*this) << " <- " << source + << ", block = " << my_block_number() << ", tag = " + << decode_tag(i->tag).second << ", bytes = " << i->bytes + << std::endl; +#endif + return result_type(source, decode_tag(i->tag).second); + } + ++i; + } + } + return optional(); +} + +void +mpi_process_group::maybe_send_batch(process_id_type dest) const +{ +#ifndef NO_SPLIT_BATCHES + impl::outgoing_messages& outgoing = impl_->outgoing[dest]; + if (outgoing.buffer.size() >= impl_->batch_buffer_size || + outgoing.headers.size() >= impl_->batch_header_number) { + // we are full and need to send + outgoing_messages batch; + batch.buffer.reserve(impl_->batch_buffer_size); + batch.swap(outgoing); + if (batch.buffer.size() >= impl_->batch_buffer_size + && batch.headers.size()>1 ) { + // we are too large, keep the last message in the outgoing buffer + std::copy(batch.buffer.begin()+batch.headers.back().offset, + batch.buffer.end(),std::back_inserter(outgoing.buffer)); + batch.buffer.resize(batch.headers.back().offset); + outgoing.headers.push_back(batch.headers.back()); + batch.headers.pop_back(); + outgoing.headers.front().offset=0; + } + send_batch(dest,batch); + } +#endif +} + +void +mpi_process_group::send_batch(process_id_type dest) const +{ + impl::outgoing_messages& outgoing = impl_->outgoing[dest]; + if (outgoing.headers.size()) { + // need to copy to avoid race conditions + outgoing_messages batch; + batch.buffer.reserve(impl_->batch_buffer_size); + batch.swap(outgoing); + send_batch(dest,batch); + } +} + + +void +mpi_process_group::send_batch(process_id_type dest, + outgoing_messages& outgoing) const +{ + impl_->free_sent_batches(); + process_id_type id = process_id(*this); + + // clear the batch +#ifdef DEBUG + std::cerr << "Sending batch: " << id << " -> " << dest << std::endl; +#endif + // we increment the number of batches sent + ++impl_->number_sent_batches[dest]; + // and send the batch + assert(outgoing.headers.size() <= impl_->batch_header_number); + if (id != dest) { +#ifdef NO_ISEND_BATCHES + impl::batch_request req; +#else +#ifdef PREALLOCATE_BATCHES + while (impl_->free_batches.empty()) { + impl_->free_sent_batches(); + poll(); + } + impl::batch_request& req = impl_->batch_pool[impl_->free_batches.top()]; + impl_->free_batches.pop(); +#else + impl_->sent_batches.push_back(impl::batch_request()); + impl::batch_request& req = impl_->sent_batches.back(); +#endif +#endif + boost::mpi::packed_oarchive oa(impl_->comm,req.buffer); + oa << outgoing; + + int tag = msg_batch; + +#ifdef IRECV_BATCH + if (oa.size() > impl_->batch_message_size) + tag = msg_large_batch; +#endif + + int result = MPI_Isend(const_cast(oa.address()), oa.size(), + MPI_PACKED, dest, tag, impl_->comm, + &req.request); + assert(result == MPI_SUCCESS); + impl_->max_sent = (std::max)(impl_->max_sent,impl_->sent_batches.size()); +#ifdef NO_ISEND_BATCHES + int done=0; + do { + poll(); + MPI_Test(&req.request,&done,MPI_STATUS_IGNORE); + } while (!done); +#else +#ifdef MAX_BATCHES + while (impl_->sent_batches.size() >= MAX_BATCHES-1) { + impl_->free_sent_batches(); + poll(); + } +#endif +#endif + } + else + receive_batch(id,outgoing); +} + +void mpi_process_group::process_batch(int source) const +{ + bool processing_from_queue = !impl_->new_batches.empty(); + impl_->processing_batches++; + typedef std::vector::iterator iterator; + + impl::incoming_messages& incoming = impl_->incoming[source]; + + // Set up the iterators pointing to the next header in each block + for (std::size_t i = 0; i < incoming.next_header.size(); ++i) + incoming.next_header[i] = incoming.headers.begin(); + + buffer_type remaining_buffer; + std::vector remaining_headers; + + iterator end = incoming.headers.end(); + + for (iterator i = incoming.headers.begin(); i != end; ++i) { + // This this message has already been received, skip it + if (i->tag == -1) + continue; + +#ifdef BATCH_DEBUG + std::cerr << process_id(*this) << ": emit_receive(" << source << ", " + << decode_tag(i->tag).first << ":" << decode_tag(i->tag).second + << ")\n"; +#endif + + if (!emit_receive(source, i->tag)) { +#ifdef BATCH_DEBUG + std::cerr << process_id(*this) << ": keeping message # " + << remaining_headers.size() << " from " << source << " (" + << decode_tag(i->tag).first << ":" + << decode_tag(i->tag).second << ", " + << i->bytes << " bytes)\n"; +#endif + // Hold on to this message until the next stage + remaining_headers.push_back(*i); + remaining_headers.back().offset = remaining_buffer.size(); + remaining_buffer.insert(remaining_buffer.end(), + &incoming.buffer[i->offset], + &incoming.buffer[i->offset] + i->bytes); + } + } + + // Swap the remaining messages into the "incoming" set. + incoming.headers.swap(remaining_headers); + incoming.buffer.swap(remaining_buffer); + + // Set up the iterators pointing to the next header in each block + for (std::size_t i = 0; i < incoming.next_header.size(); ++i) + incoming.next_header[i] = incoming.headers.begin(); + impl_->processing_batches--; + + if (!processing_from_queue) + while (!impl_->new_batches.empty()) { + receive_batch(impl_->new_batches.front().first, + impl_->new_batches.front().second); + impl_->new_batches.pop(); + } +} + + +void mpi_process_group::receive_batch(process_id_type source, + outgoing_messages& new_messages) const +{ + impl_->free_sent_batches(); + if(!impl_->processing_batches) { + // increase the number of received batches + ++impl_->number_received_batches[source]; + // and receive the batch + impl::incoming_messages& incoming = impl_->incoming[source]; + typedef std::vector::iterator iterator; + iterator end = new_messages.headers.end(); + for (iterator i = new_messages.headers.begin(); i != end; ++i) { + incoming.headers.push_back(*i); + incoming.headers.back().offset = incoming.buffer.size(); + incoming.buffer.insert(incoming.buffer.end(), + &new_messages.buffer[i->offset], + &new_messages.buffer[i->offset] + i->bytes); + } + // Set up the iterators pointing to the next header in each block + for (std::size_t i = 0; i < incoming.next_header.size(); ++i) + incoming.next_header[i] = incoming.headers.begin(); +#ifndef NO_IMMEDIATE_PROCESSING + process_batch(source); +#endif + } + else { + #ifdef DEBUG + std::cerr << "Pushing incoming message batch onto queue since we are already processing a batch.\n"; + #endif + // use swap to avoid copying + impl_->new_batches.push(std::make_pair(int(source),outgoing_messages())); + impl_->new_batches.back().second.swap(new_messages); + impl_->max_received = (std::max)(impl_->max_received,impl_->new_batches.size()); + } +} + + +void mpi_process_group::pack_headers() const +{ + for (process_id_type other = 0; other < num_processes(*this); ++other) { + typedef std::vector::iterator iterator; + + impl::incoming_messages& incoming = impl_->incoming[other]; + + buffer_type remaining_buffer; + std::vector remaining_headers; + + iterator end = incoming.headers.end(); + for (iterator i = incoming.headers.begin(); i != end; ++i) { + if (i->tag == -1) + continue; + + // Hold on to this message until the next stage + remaining_headers.push_back(*i); + remaining_headers.back().offset = remaining_buffer.size(); + remaining_buffer.insert(remaining_buffer.end(), + &incoming.buffer[i->offset], + &incoming.buffer[i->offset] + i->bytes); + } + + // Swap the remaining messages into the "incoming" set. + incoming.headers.swap(remaining_headers); + incoming.buffer.swap(remaining_buffer); + + // Set up the iterators pointing to the next header in each block + for (std::size_t i = 0; i < incoming.next_header.size(); ++i) + incoming.next_header[i] = incoming.headers.begin(); + } +} + +void mpi_process_group::receive_batch(boost::mpi::status& status) const +{ + //std::cerr << "Handling batch\n"; + outgoing_messages batch; + //impl_->comm.recv(status.source(),status.tag(),batch); + + //receive_oob(*this,status.source(),msg_batch,batch); + + // Determine how big the receive buffer should be +#if BOOST_VERSION >= 103600 + int size = status.count().get(); +#else + int size; + MPI_Status mpi_status(status); + MPI_Get_count(&mpi_status, MPI_PACKED, &size); +#endif + + // Allocate the receive buffer + boost::mpi::packed_iarchive in(impl_->comm,size); + + // Receive the message data + MPI_Recv(in.address(), size, MPI_PACKED, + status.source(), status.tag(), + impl_->comm, MPI_STATUS_IGNORE); + + // Unpack the message data + in >> batch; + receive_batch(status.source(),batch); +} + +std::pair +mpi_process_group::actual_communicator_and_tag(int tag, int block) const +{ + if (tag >= max_tags * static_cast(impl_->blocks.size())) + // Use the out-of-band reply communicator + return std::make_pair(impl_->oob_reply_comm, tag); + else + // Use the normal communicator and translate the tag + return std::make_pair(impl_->comm, + encode_tag(block == -1? my_block_number() : block, + tag)); +} + + +void mpi_process_group::synchronize() const +{ + // Don't synchronize if we've already finished + if (boost::mpi::environment::finalized()) + return; + +#ifdef DEBUG + std::cerr << "SYNC: " << process_id(*this) << std::endl; +#endif + + emit_on_synchronize(); + + process_id_type id = process_id(*this); // Our rank + process_size_type p = num_processes(*this); // The number of processes + + // Pack the remaining incoming messages into the beginning of the + // buffers, so that we can receive new messages in this + // synchronization step without losing those messages that have not + // yet been received. + pack_headers(); + + impl_->synchronizing_stage[id] = -1; + int stage=-1; + bool no_new_messages = false; + while (true) { + ++stage; +#ifdef DEBUG + std::cerr << "SYNC: " << id << " starting stage " << (stage+1) << ".\n"; +#endif + + // Tell everyone that we are synchronizing. Note: we use MPI_Isend since + // we absolutely cannot have any of these operations blocking. + + // increment the stage for the source + ++impl_->synchronizing_stage[id]; + if (impl_->synchronizing_stage[id] != stage) + std::cerr << "Expected stage " << stage << ", got " << impl_->synchronizing_stage[id] << std::endl; + assert(impl_->synchronizing_stage[id]==stage); + // record how many still have messages to be sent + if (static_cast(impl_->synchronizing_unfinished.size())<=stage) { + assert(static_cast(impl_->synchronizing_unfinished.size()) == stage); + impl_->synchronizing_unfinished.push_back(no_new_messages ? 0 : 1); + } + else + impl_->synchronizing_unfinished[stage]+=(no_new_messages ? 0 : 1); + + // record how many are in that stage + if (static_cast(impl_->processors_synchronizing_stage.size())<=stage) { + assert(static_cast(impl_->processors_synchronizing_stage.size()) == stage); + impl_->processors_synchronizing_stage.push_back(1); + } + else + ++impl_->processors_synchronizing_stage[stage]; + + impl_->synchronizing = true; + + for (int dest = 0; dest < p; ++dest) { + int sync_message = no_new_messages ? -1 : impl_->number_sent_batches[dest]; + if (dest != id) { + impl_->number_sent_batches[dest]=0; + MPI_Request request; + MPI_Isend(&sync_message, 1, MPI_INT, dest, msg_synchronizing, impl_->comm,&request); + int done=0; + do { + poll(); + MPI_Test(&request,&done,MPI_STATUS_IGNORE); + } while (!done); + } + else { // need to subtract how many messages I should have received + impl_->number_received_batches[id] -=impl_->number_sent_batches[id]; + impl_->number_sent_batches[id]=0; + } + } + + // Keep handling out-of-band messages until everyone has gotten + // to this point. + while (impl_->processors_synchronizing_stage[stage] synchronizing_stage[source] >= stage); + + // receive any batches sent in the meantime + // all have to be available already + while (true) { + bool done=true; + for (int source=0; source

    number_received_batches[source] < 0) + done = false; + if (done) + break; + poll(false,-1,true); + } + +#ifndef NO_IMMEDIATE_PROCESSING + for (int source=0; source

    number_received_batches[source] >= 0); +#endif + + impl_->synchronizing = false; + + // Flush out remaining messages + if (impl_->synchronizing_unfinished[stage]==0) + break; +#ifdef NO_IMMEDIATE_PROCESSING + for (process_id_type dest = 0; dest < p; ++dest) + process_batch(dest); +#endif + + no_new_messages = true; + for (process_id_type dest = 0; dest < p; ++dest) { + if (impl_->outgoing[dest].headers.size() || + impl_->number_sent_batches[dest]>0) + no_new_messages = false; + send_batch(dest); + } + } + + impl_->comm.barrier/*nomacro*/(); +#if 0 + // set up for next synchronize call + for (int source=0; sourcesynchronizing_stage[source] != stage) { + std::cerr << id << ": expecting stage " << stage << " from source " + << source << ", got " << impl_->synchronizing_stage[source] + << std::endl; + } + assert(impl_->synchronizing_stage[source]==stage); + } +#endif + std::fill(impl_->synchronizing_stage.begin(), + impl_->synchronizing_stage.end(), -1); + + // get rid of the information regarding recorded numbers of processors + // for the stages we just finished + impl_->processors_synchronizing_stage.clear(); + impl_->synchronizing_unfinished.clear(); + + for (process_id_type dest = 0; dest < p; ++dest) + assert (impl_->outgoing[dest].headers.empty()); +#ifndef NO_IMMEDIATE_PROCESSING + for (int source=0; source

    number_received_batches[source] == 0); +#endif + + impl_->free_sent_batches(); +#ifdef DEBUG + std::cerr << "SYNC: " << process_id(*this) << " completed." << std::endl; +#endif +} + +optional > +probe(const mpi_process_group& pg) +{ return pg.probe(); } + +void mpi_process_group::poll_requests(int block) const +{ + int size = impl_->requests.size(); + if (size==0) + return; + std::vector statuses(size); + std::vector indices(size); + + while (true) { + MPI_Testsome(impl_->requests.size(),&impl_->requests[0], + &size,&indices[0],&statuses[0]); + if (size==0) + return; // no message waiting + + // remove handled requests before we get the chance to be recursively called + if (size) { + std::vector active_requests; + std::size_t i=0; + int j=0; + for (;i< impl_->requests.size() && j< size; ++i) { + if (int(i)==indices[j]) + // release the dealt-with request + ++j; + else // copy and keep the request + active_requests.push_back(impl_->requests[i]); + } + while (i < impl_->requests.size()) + active_requests.push_back(impl_->requests[i++]); + impl_->requests.swap(active_requests); + } + + optional > result; + for (int i=0;i < size; ++i) { + std::pair decoded = decode_tag(statuses[i].MPI_TAG); + block_type* block = impl_->blocks[decoded.first]; + + assert (decoded.second < static_cast(block->triggers.size()) && block->triggers[decoded.second]); + // We have a trigger for this message; use it + trigger_receive_context old_context = impl_->trigger_context; + impl_->trigger_context = trc_irecv_out_of_band; + block->triggers[decoded.second]->receive(*this, statuses[i].MPI_SOURCE, + decoded.second, impl_->trigger_context, decoded.first); + impl_->trigger_context = old_context; + } + } +} + + +optional > +mpi_process_group:: +poll(bool wait, int block, bool synchronizing) const +{ + // Set the new trigger context for these receive operations + trigger_receive_context old_context = impl_->trigger_context; + if (synchronizing) + impl_->trigger_context = trc_in_synchronization; + else + impl_->trigger_context = trc_out_of_band; + + //wait = false; + optional status; + bool finished=false; + optional > result; + do { + poll_requests(block); + // Check for any messages not yet received. +#ifdef PBGL_PROCESS_GROUP_NO_IRECV + if (wait) + status = impl_->comm.probe(); + else +#endif + status = impl_->comm.iprobe(); + + if (status) { // we have a message + // Decode the message + std::pair decoded = decode_tag(status.get().tag()); + if (maybe_emit_receive(status.get().source(), status.get().tag())) + // We received the message out-of-band; poll again + finished = false; + else if (decoded.first == (block == -1 ? my_block_number() : block)) { + // This message is for us, but not through a trigger. Return + // the decoded message. + result = std::make_pair(status.get().source(), decoded.second); + // otherwise we didn't match any message we know how to deal with, so + // pretend no message exists. + finished = true; + } + } + else + // We don't have a message to process; we're done. + finished=!wait; + } while (!finished); + + // Restore the prior trigger context + impl_->trigger_context = old_context; + poll_requests(block); + return result; +} + +void synchronize(const mpi_process_group& pg) { pg.synchronize(); } + +mpi_process_group mpi_process_group::base() const +{ + mpi_process_group copy(*this); + copy.block_num.reset(); + return copy; +} + + +void mpi_process_group::impl::free_sent_batches() +{ + typedef std::list::iterator iterator; + iterator it = sent_batches.begin(); + int flag; + int result; + while(it != sent_batches.end()) { + result = MPI_Test(&it->request,&flag,MPI_STATUS_IGNORE); + assert(result == MPI_SUCCESS); + iterator next=it; + ++next; + if (flag) + sent_batches.erase(it); + it=next; + } +#ifdef PREALLOCATE_BATCHES + for (std::size_t i=0; i< batch_pool.size();++i) { + if(batch_pool[i].request != MPI_REQUEST_NULL) { + result = MPI_Test(&batch_pool[i].request,&flag,MPI_STATUS_IGNORE); + assert(result == MPI_SUCCESS); + if (flag) { + free_batches.push(i); + batch_pool[i].request = MPI_REQUEST_NULL; + batch_pool[i].buffer.resize(0); + } + } + } +#endif +} + +void +mpi_process_group::install_trigger(int tag, int block, + shared_ptr const& launcher) +{ + block_type* my_block = impl_->blocks[block]; + assert(my_block); + + // Make sure we have enough space in the structure for this trigger. + if (launcher->tag() >= static_cast(my_block->triggers.size())) + my_block->triggers.resize(launcher->tag() + 1); + + // If someone already put a trigger in this spot, we have a big + // problem. + if (my_block->triggers[launcher->tag()]) { + std::cerr << "Block " << my_block_number() + << " already has a trigger for tag " << launcher->tag() + << std::endl; + } + assert(!my_block->triggers[launcher->tag()]); + + // Attach a new trigger launcher + my_block->triggers[launcher->tag()] = launcher; +} + +std::size_t mpi_process_group::message_buffer_size() +{ + return message_buffer.size(); +} + + +void mpi_process_group::set_message_buffer_size(std::size_t s) +{ + int sz; + void* ptr; + if (!message_buffer.empty()) { + MPI_Buffer_detach(&ptr,&sz); + assert(ptr == &message_buffer.front()); + assert(static_cast(sz) == message_buffer.size()); + } + else if (old_buffer != 0) + MPI_Buffer_detach(&old_buffer,&old_buffer_size); + message_buffer.resize(s); + if (s) + MPI_Buffer_attach(&message_buffer.front(), message_buffer.size()); + else if (old_buffer_size) + MPI_Buffer_attach(old_buffer, old_buffer_size); +} + + +std::vector mpi_process_group::message_buffer; +int mpi_process_group::old_buffer_size=0; +void* mpi_process_group::old_buffer=0; + +} } } // end namespace boost::graph::distributed diff --git a/src/tag_allocator.cpp b/src/tag_allocator.cpp new file mode 100644 index 00000000..a89a2a2d --- /dev/null +++ b/src/tag_allocator.cpp @@ -0,0 +1,45 @@ +// Copyright (C) 2007 Douglas Gregor + +// 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 + +namespace boost { namespace graph { namespace distributed { namespace detail { + +tag_allocator::token tag_allocator::get_tag() +{ + int tag; + + if (!freed.empty()) { + // Grab the tag at the top of the stack. + tag = freed.back(); + freed.pop_back(); + } else + // Grab the bottom tag and move the bottom down + tag = bottom--; + + return token(this, tag); +} + +tag_allocator::token::token(const token& other) + : allocator(other.allocator), tag_(other.tag_) +{ + // other no longer owns this tag + other.tag_ = -1; +} + +tag_allocator::token::~token() +{ + if (tag_ != -1) { + if (tag_ == allocator->bottom + 1) + // This is the bottommost tag: just bump up the bottom + ++allocator->bottom; + else + // This tag isn't the bottom, so push it only the freed stack + allocator->freed.push_back(tag_); + } +} + +} } } } // end namespace boost::graph::distributed::detail From a8365520021a811b0d1147ce29a10b20ca36bf82 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Fri, 10 Apr 2009 18:51:48 +0000 Subject: [PATCH 133/224] Trying to fix CSR constructor [SVN r52302] --- include/boost/graph/compressed_sparse_row_graph.hpp | 4 ++-- include/boost/graph/detail/indexed_properties.hpp | 12 ++++++++++++ 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/include/boost/graph/compressed_sparse_row_graph.hpp b/include/boost/graph/compressed_sparse_row_graph.hpp index f3bfb8f1..24899948 100644 --- a/include/boost/graph/compressed_sparse_row_graph.hpp +++ b/include/boost/graph/compressed_sparse_row_graph.hpp @@ -239,12 +239,12 @@ class compressed_sparse_row_graph // location to insert out edges for vertex v. std::vector current_insert_positions(m_rowstart.begin(), m_rowstart.begin() + numverts); - for (; edge_begin != edge_end; ++edge_begin) { + for (; edge_begin != edge_end; ++edge_begin, ++ep_iter) { vertices_size_type source = edge_begin->first; EdgeIndex insert_pos = current_insert_positions[source]; ++current_insert_positions[source]; m_column[insert_pos] = edge_begin->second; - inherited_edge_properties::operator[](insert_pos) = edge_begin->second; + inherited_edge_properties::write_by_index(insert_pos, *ep_iter); } } diff --git a/include/boost/graph/detail/indexed_properties.hpp b/include/boost/graph/detail/indexed_properties.hpp index 17bbdad1..60156d7f 100644 --- a/include/boost/graph/detail/indexed_properties.hpp +++ b/include/boost/graph/detail/indexed_properties.hpp @@ -68,6 +68,12 @@ public: m_vertex_properties.push_back(prop); } + // Write an element by raw index + void write_by_index(std::size_t idx, const Property& prop) + { + m_edge_properties[idx] = prop; + } + // Access to the derived object Derived& derived() { return *static_cast(this); } @@ -133,6 +139,12 @@ protected: m_edge_properties.reserve(n); } + // Write an element by raw index + void write_by_index(std::size_t idx, const Property& prop) + { + m_edge_properties[idx] = prop; + } + public: // Add a new property value to the back void push_back(const Property& prop) From 44a6ffef17b33afeb31f51e1fcda4519287b1b5d Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Fri, 10 Apr 2009 18:55:45 +0000 Subject: [PATCH 134/224] Trying to fix CSR constructor [SVN r52303] --- include/boost/graph/detail/indexed_properties.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/boost/graph/detail/indexed_properties.hpp b/include/boost/graph/detail/indexed_properties.hpp index 60156d7f..57caea50 100644 --- a/include/boost/graph/detail/indexed_properties.hpp +++ b/include/boost/graph/detail/indexed_properties.hpp @@ -71,7 +71,7 @@ public: // Write an element by raw index void write_by_index(std::size_t idx, const Property& prop) { - m_edge_properties[idx] = prop; + m_vertex_properties[idx] = prop; } // Access to the derived object From 519192a2b838af123d3ca93719a4ed7a6c0ca177 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Sat, 11 Apr 2009 01:33:02 +0000 Subject: [PATCH 135/224] Merged in code and docs from Parallel BGL; CMake-based build system for tests and examples and docs is not working; src and doc can be built with bjam [SVN r52313] --- CMakeLists.txt | 8 +- build/Jamfile.v2 | 23 - module.cmake | 1 + src/CMakeLists.txt | 1 + src/mpi_process_group.cpp | 1108 ------------------------------------- src/tag_allocator.cpp | 45 -- 6 files changed, 3 insertions(+), 1183 deletions(-) delete mode 100644 src/mpi_process_group.cpp delete mode 100644 src/tag_allocator.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 139abdfc..93f55a76 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,16 +1,12 @@ #---------------------------------------------------------------------------- # This file was automatically generated from the original CMakeLists.txt file -# Add a variable to hold the headers for the library -set (lib_headers - graph -) # Add a library target to the build system boost_library_project( graph SRCDIRS src TESTDIRS test - HEADERS ${lib_headers} + HEADERS graph # DOCDIRS DESCRIPTION "The BGL graph interface and graph components are generic, in the same sense as the the Standard Template Library (STL)." MODULARIZED @@ -20,5 +16,3 @@ boost_library_project( "Douglas Gregor " # MAINTAINERS ) - - diff --git a/build/Jamfile.v2 b/build/Jamfile.v2 index a7f70c4d..fa0deba1 100644 --- a/build/Jamfile.v2 +++ b/build/Jamfile.v2 @@ -45,33 +45,10 @@ else } explicit graphml ; -if [ mpi.configured ] -{ - alias pbgl - : mpi_process_group.cpp tag_allocator.cpp - : # requirements - ../../mpi/build//boost_mpi - /mpi//mpi [ mpi.extra-requirements ] - : # default built - : # usage requirements - ../../mpi/build//boost_mpi - /mpi//mpi [ mpi.extra-requirements ] - ; -} -else -{ - message pbgl - : "warning: Graph library does not contain MPI-based parallel components." - : "note: to enable them, add \"using mpi ;\" to your user_config.jam" - ; -} -explicit graphml ; - lib boost_graph : read_graphviz_spirit.cpp graphml - pbgl : BOOST_GRAPH_NO_LIB=1 shared:BOOST_GRAPH_DYN_LINK=1 diff --git a/module.cmake b/module.cmake index 6ffdf592..f0514a08 100644 --- a/module.cmake +++ b/module.cmake @@ -1,3 +1,4 @@ boost_module(graph DEPENDS property_map tuple multi_index any random) +boost_module(graph_mpi DEPENDS mpi graph) # any is there because of the dependency on boost/property_map/dynamic_property_map.hpp diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 786b8173..8bb27ee7 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -24,3 +24,4 @@ boost_add_library( LINK_LIBS ${BOOST_GRAPH_OPTIONAL_LIBRARIES} SHARED_COMPILE_FLAGS "-DBOOST_GRAPH_DYN_LINK=1" ) + diff --git a/src/mpi_process_group.cpp b/src/mpi_process_group.cpp deleted file mode 100644 index 62ff7ada..00000000 --- a/src/mpi_process_group.cpp +++ /dev/null @@ -1,1108 +0,0 @@ -// Copyright (C) 2004-2006 The Trustees of Indiana University. -// Copyright (C) 2007 Douglas Gregor -// Copyright (C) 2007 Matthias Troyer - -// 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) - -// Authors: Douglas Gregor -// Andrew Lumsdaine -// Matthias Troyer -#include -#include -#include -#include -#include -#include - -//#define DEBUG 1 - - -//#define MAX_BATCHES 1500 -#define PREALLOCATE_BATCHES 250 -// 500 is a better setting for PREALLOCATE_BATCHES if you're not using process -// subgroups and are building 64-bit binaries. 250 allows all the CTest -// tests to pass in both 32 and 64-bit modes. If you create multiple process -// groups with PREALLOCATE_BATCHES at a reasonable level in 32-bit mode you -// _will_ run out of memory and get "malloc failed" errors - -//#define NO_ISEND_BATCHES -//#define NO_IMMEDIATE_PROCESSING -//#define NO_SPLIT_BATCHES -#define IRECV_BATCH - -// we cannot keep track of how many we received if we do not process them -#ifdef NO_IMMEDIATE_PROCESSING -#undef IRECV_BATCH -#endif - -#ifdef DEBUG -# include -#endif // DEBUG - -namespace boost { namespace graph { namespace distributed { - -struct mpi_process_group::deallocate_block -{ - explicit deallocate_block(blocks_type* blocks) : blocks(blocks) { } - - void operator()(int* block_num) - { - block_type* block = (*blocks)[*block_num]; - - // Mark this block as inactive - (*blocks)[*block_num] = 0; - -#ifdef DEBUG - fprintf(stderr, "Processor %i deallocated block #%i\n", - boost::mpi::communicator().rank(), *block_num); -#endif - - // Delete the block and its block number - delete block_num; - delete block; - } - -private: - blocks_type* blocks; -}; - -mpi_process_group::impl::incoming_messages::incoming_messages() -{ - next_header.push_back(headers.begin()); -} - -mpi_process_group::impl::impl(std::size_t num_headers, std::size_t buffer_sz, - communicator_type parent_comm) - : comm(parent_comm, boost::mpi::comm_duplicate), - oob_reply_comm(parent_comm, boost::mpi::comm_duplicate), - allocated_tags(boost::mpi::environment::max_tag()) -{ - max_sent=0; - max_received=0; - int n = comm.size(); - outgoing.resize(n); - incoming.resize(n); - - // no synchronization stage means -1 - // to keep the convention - synchronizing_stage.resize(n,-1); - number_sent_batches.resize(n); - number_received_batches.resize(n); - trigger_context = trc_none; - processing_batches = 0; - - // Allocator a placeholder block "0" - blocks.push_back(new block_type); - - synchronizing = false; - - set_batch_size(num_headers,buffer_sz); - - for (int i = 0; i < n; ++i) { - incoming[i].next_header.front() = incoming[i].headers.end(); - outgoing[i].buffer.reserve(batch_message_size); - } - -#ifdef PREALLOCATE_BATCHES - batch_pool.resize(PREALLOCATE_BATCHES); - for (std::size_t i = 0 ; i < batch_pool.size(); ++i) { - batch_pool[i].buffer.reserve(batch_message_size); - batch_pool[i].request=MPI_REQUEST_NULL; - free_batches.push(i); - } -#endif -} - -void mpi_process_group::impl::set_batch_size(std::size_t header_num, std::size_t buffer_sz) -{ - batch_header_number = header_num; - batch_buffer_size = buffer_sz; - - // determine batch message size by serializing the largest possible batch - outgoing_messages msg; - msg.headers.resize(batch_header_number); - msg.buffer.resize(batch_buffer_size); - boost::mpi::packed_oarchive oa(comm); - oa << const_cast(msg); - batch_message_size = oa.size(); -} - - -mpi_process_group::impl::~impl() -{ - // Delete the placeholder "0" block - delete blocks.front(); - if (!boost::mpi::environment::finalized()) - for (std::vector::iterator it=requests.begin(); - it != requests.end();++it) - MPI_Cancel(&(*it)); -} - -namespace detail { -// global batch handlers -void handle_batch (mpi_process_group const& self, int source, int, - mpi_process_group::outgoing_messages& batch,bool out_of_band) -{ -#ifdef DEBUG - std::cerr << "Processing batch trigger\n"; - std::cerr << "BATCH: " << process_id(self) << " <- " << source << " (" - << batch.headers.size() << " headers, " - << batch.buffer.size() << " bytes)" - << std::endl; -#endif - // If we are not synchronizing, then this must be an early receive - trigger_receive_context old_context = self.impl_->trigger_context; - if (self.impl_->trigger_context != trc_in_synchronization) - self.impl_->trigger_context = trc_early_receive; - - // Receive the batched messages - self.receive_batch(source,batch); - - // Restore the previous context - self.impl_->trigger_context = old_context; -} - -// synchronization handler -void handle_sync (mpi_process_group const& self, int source, int tag, int val, - bool) -{ - // increment the stage for the source - std::size_t stage = static_cast( - ++self.impl_->synchronizing_stage[source]); - - assert(source != process_id(self)); - -#ifdef DEBUG - std::ostringstream out; - out << process_id(self) << ": handle_sync from " << source - << " (stage = " << self.impl_->synchronizing_stage[source] << ")\n"; - std::cerr << out.str(); -#endif - - // record how many still have messages to be sent - if (self.impl_->synchronizing_unfinished.size()<=stage) { - assert(self.impl_->synchronizing_unfinished.size() == stage); - self.impl_->synchronizing_unfinished.push_back(val >= 0 ? 1 : 0); - } - else - self.impl_->synchronizing_unfinished[stage]+=(val >= 0 ? 1 : 0); - - // record how many are in that stage - if (self.impl_->processors_synchronizing_stage.size()<=stage) { - assert(self.impl_->processors_synchronizing_stage.size() == stage); - self.impl_->processors_synchronizing_stage.push_back(1); - } - else - ++self.impl_->processors_synchronizing_stage[stage]; - - // subtract how many batches we were supposed to receive - if (val>0) - self.impl_->number_received_batches[source] -= val; -} - - -} - -mpi_process_group::mpi_process_group(communicator_type parent_comm) -{ - // 64K messages and 1MB buffer turned out to be a reasonable choice - impl_.reset(new impl(64*1024,1024*1024,parent_comm)); -#ifndef IRECV_BATCH - global_trigger(msg_batch,&detail::handle_batch); -#else // use irecv version by providing a maximum buffer size - global_trigger(msg_batch,&detail::handle_batch, - impl_->batch_message_size); -#endif - global_trigger(msg_large_batch,&detail::handle_batch); - global_trigger(msg_synchronizing,&detail::handle_sync); - rank = impl_->comm.rank(); - size = impl_->comm.size(); - -#ifdef SEND_OOB_BSEND - // let us try with a default bufferr size of 16 MB - if (!message_buffer_size()) - set_message_buffer_size(16*1024*1024); -#endif -} - -mpi_process_group::mpi_process_group(std::size_t h, std::size_t sz, - communicator_type parent_comm) -{ - impl_.reset(new impl(h,sz,parent_comm)); -#ifndef IRECV_BATCH - global_trigger(msg_batch,&detail::handle_batch); -#else // use irecv version by providing a maximum buffer size - global_trigger(msg_batch,&detail::handle_batch, - impl_->batch_message_size); -#endif - global_trigger(msg_large_batch,&detail::handle_batch); - global_trigger(msg_synchronizing,&detail::handle_sync); - rank = impl_->comm.rank(); - size = impl_->comm.size(); -#ifdef SEND_OOB_BSEND - // let us try with a default bufferr size of 16 MB - if (!message_buffer_size()) - set_message_buffer_size(16*1024*1024); -#endif -} - -mpi_process_group::mpi_process_group(const mpi_process_group& other, - const receiver_type& handler, bool) - : impl_(other.impl_) -{ - rank = impl_->comm.rank(); - size = impl_->comm.size(); - replace_handler(handler); -} - -mpi_process_group::mpi_process_group(const mpi_process_group& other, - attach_distributed_object, bool) - : impl_(other.impl_) -{ - rank = impl_->comm.rank(); - size = impl_->comm.size(); - allocate_block(); - - for (std::size_t i = 0; i < impl_->incoming.size(); ++i) { - if (my_block_number() >= (int)impl_->incoming[i].next_header.size()) { - impl_->incoming[i].next_header - .push_back(impl_->incoming[i].headers.begin()); - } else { - impl_->incoming[i].next_header[my_block_number()] = - impl_->incoming[i].headers.begin(); - } - -#ifdef DEBUG - if (process_id(*this) == 0) { - std::cerr << "Allocated tag block " << my_block_number() << std::endl; - } -#endif - } -} - -mpi_process_group::~mpi_process_group() { - /* - std::string msg = boost::lexical_cast(process_id(*this)) + " " + - boost::lexical_cast(impl_->max_received) + " " + - boost::lexical_cast(impl_->max_sent) + "\n"; - std::cerr << msg << "\n"; - */ -} - - -mpi_process_group::communicator_type communicator(const mpi_process_group& pg) -{ return pg.impl_->comm; } - -void -mpi_process_group::replace_handler(const receiver_type& handler, - bool out_of_band_receive) -{ - make_distributed_object(); - - // Attach the receive handler - impl_->blocks[my_block_number()]->on_receive = handler; -} - -void -mpi_process_group::make_distributed_object() -{ - if (my_block_number() == 0) { - allocate_block(); - - for (std::size_t i = 0; i < impl_->incoming.size(); ++i) { - if (my_block_number() >= (int)impl_->incoming[i].next_header.size()) { - impl_->incoming[i].next_header - .push_back(impl_->incoming[i].headers.begin()); - } else { - impl_->incoming[i].next_header[my_block_number()] = - impl_->incoming[i].headers.begin(); - } - -#ifdef DEBUG - if (process_id(*this) == 0) { - std::cerr << "Allocated tag block " << my_block_number() << std::endl; - } -#endif - } - } else { - // Clear out the existing triggers - std::vector >() - .swap(impl_->blocks[my_block_number()]->triggers); - } - - // Clear out the receive handler - impl_->blocks[my_block_number()]->on_receive = 0; -} - -void -mpi_process_group:: -replace_on_synchronize_handler(const on_synchronize_event_type& handler) -{ - if (my_block_number() > 0) - impl_->blocks[my_block_number()]->on_synchronize = handler; -} - -int mpi_process_group::allocate_block(bool out_of_band_receive) -{ - assert(!block_num); - block_iterator i = impl_->blocks.begin(); - while (i != impl_->blocks.end() && *i) ++i; - - if (i == impl_->blocks.end()) { - impl_->blocks.push_back(new block_type()); - i = impl_->blocks.end() - 1; - } else { - *i = new block_type(); - } - - block_num.reset(new int(i - impl_->blocks.begin()), - deallocate_block(&impl_->blocks)); - -#ifdef DEBUG - fprintf(stderr, - "Processor %i allocated block #%i\n", process_id(*this), *block_num); -#endif - - return *block_num; -} - -bool mpi_process_group::maybe_emit_receive(int process, int encoded_tag) const -{ - std::pair decoded = decode_tag(encoded_tag); - - assert (decoded.first < static_cast(impl_->blocks.size())); - - block_type* block = impl_->blocks[decoded.first]; - if (!block) { - std::cerr << "Received message from process " << process << " with tag " - << decoded.second << " for non-active block " - << decoded.first << std::endl; - std::cerr << "Active blocks are: "; - for (std::size_t i = 0; i < impl_->blocks.size(); ++i) - if (impl_->blocks[i]) - std::cerr << i << ' '; - std::cerr << std::endl; - assert(block); - } - - if (decoded.second < static_cast(block->triggers.size()) - && block->triggers[decoded.second]) { - // We have a trigger for this message; use it - trigger_receive_context old_context = impl_->trigger_context; - impl_->trigger_context = trc_out_of_band; - block->triggers[decoded.second]->receive(*this, process, decoded.second, - impl_->trigger_context, - decoded.first); - impl_->trigger_context = old_context; - } - else - return false; - // We receives the message above - return true; -} - -bool mpi_process_group::emit_receive(int process, int encoded_tag) const -{ - std::pair decoded = decode_tag(encoded_tag); - - if (decoded.first >= static_cast(impl_->blocks.size())) - // This must be an out-of-band message destined for - // send_oob_with_reply; ignore it. - return false; - - // Find the block that will receive this message - block_type* block = impl_->blocks[decoded.first]; - assert(block); - if (decoded.second < static_cast(block->triggers.size()) - && block->triggers[decoded.second]) - // We have a trigger for this message; use it - block->triggers[decoded.second]->receive(*this,process, decoded.second, - impl_->trigger_context); - else if (block->on_receive) - // Fall back to the normal message handler - block->on_receive(process, decoded.second); - else - // There was no handler for this message - return false; - - // The message was handled above - return true; -} - -void mpi_process_group::emit_on_synchronize() const -{ - for (block_iterator i = impl_->blocks.begin(); i != impl_->blocks.end(); ++i) - if (*i && (*i)->on_synchronize) (*i)->on_synchronize(); -} - - -optional > -mpi_process_group::probe() const -{ -#ifdef DEBUG - std::cerr << "PROBE: " << process_id(*this) << ", tag block = " - << my_block_number() << std::endl; -#endif - - typedef std::pair result_type; - - int tag_block = my_block_number(); - - for (std::size_t source = 0; source < impl_->incoming.size(); ++source) { - impl::incoming_messages& incoming = impl_->incoming[source]; - std::vector::iterator& i = - incoming.next_header[tag_block]; - std::vector::iterator end = incoming.headers.end(); - - while (i != end) { - if (i->tag != -1 && decode_tag(i->tag).first == my_block_number()) { -#ifdef DEBUG - std::cerr << "PROBE: " << process_id(*this) << " <- " << source - << ", block = " << my_block_number() << ", tag = " - << decode_tag(i->tag).second << ", bytes = " << i->bytes - << std::endl; -#endif - return result_type(source, decode_tag(i->tag).second); - } - ++i; - } - } - return optional(); -} - -void -mpi_process_group::maybe_send_batch(process_id_type dest) const -{ -#ifndef NO_SPLIT_BATCHES - impl::outgoing_messages& outgoing = impl_->outgoing[dest]; - if (outgoing.buffer.size() >= impl_->batch_buffer_size || - outgoing.headers.size() >= impl_->batch_header_number) { - // we are full and need to send - outgoing_messages batch; - batch.buffer.reserve(impl_->batch_buffer_size); - batch.swap(outgoing); - if (batch.buffer.size() >= impl_->batch_buffer_size - && batch.headers.size()>1 ) { - // we are too large, keep the last message in the outgoing buffer - std::copy(batch.buffer.begin()+batch.headers.back().offset, - batch.buffer.end(),std::back_inserter(outgoing.buffer)); - batch.buffer.resize(batch.headers.back().offset); - outgoing.headers.push_back(batch.headers.back()); - batch.headers.pop_back(); - outgoing.headers.front().offset=0; - } - send_batch(dest,batch); - } -#endif -} - -void -mpi_process_group::send_batch(process_id_type dest) const -{ - impl::outgoing_messages& outgoing = impl_->outgoing[dest]; - if (outgoing.headers.size()) { - // need to copy to avoid race conditions - outgoing_messages batch; - batch.buffer.reserve(impl_->batch_buffer_size); - batch.swap(outgoing); - send_batch(dest,batch); - } -} - - -void -mpi_process_group::send_batch(process_id_type dest, - outgoing_messages& outgoing) const -{ - impl_->free_sent_batches(); - process_id_type id = process_id(*this); - - // clear the batch -#ifdef DEBUG - std::cerr << "Sending batch: " << id << " -> " << dest << std::endl; -#endif - // we increment the number of batches sent - ++impl_->number_sent_batches[dest]; - // and send the batch - assert(outgoing.headers.size() <= impl_->batch_header_number); - if (id != dest) { -#ifdef NO_ISEND_BATCHES - impl::batch_request req; -#else -#ifdef PREALLOCATE_BATCHES - while (impl_->free_batches.empty()) { - impl_->free_sent_batches(); - poll(); - } - impl::batch_request& req = impl_->batch_pool[impl_->free_batches.top()]; - impl_->free_batches.pop(); -#else - impl_->sent_batches.push_back(impl::batch_request()); - impl::batch_request& req = impl_->sent_batches.back(); -#endif -#endif - boost::mpi::packed_oarchive oa(impl_->comm,req.buffer); - oa << outgoing; - - int tag = msg_batch; - -#ifdef IRECV_BATCH - if (oa.size() > impl_->batch_message_size) - tag = msg_large_batch; -#endif - - int result = MPI_Isend(const_cast(oa.address()), oa.size(), - MPI_PACKED, dest, tag, impl_->comm, - &req.request); - assert(result == MPI_SUCCESS); - impl_->max_sent = (std::max)(impl_->max_sent,impl_->sent_batches.size()); -#ifdef NO_ISEND_BATCHES - int done=0; - do { - poll(); - MPI_Test(&req.request,&done,MPI_STATUS_IGNORE); - } while (!done); -#else -#ifdef MAX_BATCHES - while (impl_->sent_batches.size() >= MAX_BATCHES-1) { - impl_->free_sent_batches(); - poll(); - } -#endif -#endif - } - else - receive_batch(id,outgoing); -} - -void mpi_process_group::process_batch(int source) const -{ - bool processing_from_queue = !impl_->new_batches.empty(); - impl_->processing_batches++; - typedef std::vector::iterator iterator; - - impl::incoming_messages& incoming = impl_->incoming[source]; - - // Set up the iterators pointing to the next header in each block - for (std::size_t i = 0; i < incoming.next_header.size(); ++i) - incoming.next_header[i] = incoming.headers.begin(); - - buffer_type remaining_buffer; - std::vector remaining_headers; - - iterator end = incoming.headers.end(); - - for (iterator i = incoming.headers.begin(); i != end; ++i) { - // This this message has already been received, skip it - if (i->tag == -1) - continue; - -#ifdef BATCH_DEBUG - std::cerr << process_id(*this) << ": emit_receive(" << source << ", " - << decode_tag(i->tag).first << ":" << decode_tag(i->tag).second - << ")\n"; -#endif - - if (!emit_receive(source, i->tag)) { -#ifdef BATCH_DEBUG - std::cerr << process_id(*this) << ": keeping message # " - << remaining_headers.size() << " from " << source << " (" - << decode_tag(i->tag).first << ":" - << decode_tag(i->tag).second << ", " - << i->bytes << " bytes)\n"; -#endif - // Hold on to this message until the next stage - remaining_headers.push_back(*i); - remaining_headers.back().offset = remaining_buffer.size(); - remaining_buffer.insert(remaining_buffer.end(), - &incoming.buffer[i->offset], - &incoming.buffer[i->offset] + i->bytes); - } - } - - // Swap the remaining messages into the "incoming" set. - incoming.headers.swap(remaining_headers); - incoming.buffer.swap(remaining_buffer); - - // Set up the iterators pointing to the next header in each block - for (std::size_t i = 0; i < incoming.next_header.size(); ++i) - incoming.next_header[i] = incoming.headers.begin(); - impl_->processing_batches--; - - if (!processing_from_queue) - while (!impl_->new_batches.empty()) { - receive_batch(impl_->new_batches.front().first, - impl_->new_batches.front().second); - impl_->new_batches.pop(); - } -} - - -void mpi_process_group::receive_batch(process_id_type source, - outgoing_messages& new_messages) const -{ - impl_->free_sent_batches(); - if(!impl_->processing_batches) { - // increase the number of received batches - ++impl_->number_received_batches[source]; - // and receive the batch - impl::incoming_messages& incoming = impl_->incoming[source]; - typedef std::vector::iterator iterator; - iterator end = new_messages.headers.end(); - for (iterator i = new_messages.headers.begin(); i != end; ++i) { - incoming.headers.push_back(*i); - incoming.headers.back().offset = incoming.buffer.size(); - incoming.buffer.insert(incoming.buffer.end(), - &new_messages.buffer[i->offset], - &new_messages.buffer[i->offset] + i->bytes); - } - // Set up the iterators pointing to the next header in each block - for (std::size_t i = 0; i < incoming.next_header.size(); ++i) - incoming.next_header[i] = incoming.headers.begin(); -#ifndef NO_IMMEDIATE_PROCESSING - process_batch(source); -#endif - } - else { - #ifdef DEBUG - std::cerr << "Pushing incoming message batch onto queue since we are already processing a batch.\n"; - #endif - // use swap to avoid copying - impl_->new_batches.push(std::make_pair(int(source),outgoing_messages())); - impl_->new_batches.back().second.swap(new_messages); - impl_->max_received = (std::max)(impl_->max_received,impl_->new_batches.size()); - } -} - - -void mpi_process_group::pack_headers() const -{ - for (process_id_type other = 0; other < num_processes(*this); ++other) { - typedef std::vector::iterator iterator; - - impl::incoming_messages& incoming = impl_->incoming[other]; - - buffer_type remaining_buffer; - std::vector remaining_headers; - - iterator end = incoming.headers.end(); - for (iterator i = incoming.headers.begin(); i != end; ++i) { - if (i->tag == -1) - continue; - - // Hold on to this message until the next stage - remaining_headers.push_back(*i); - remaining_headers.back().offset = remaining_buffer.size(); - remaining_buffer.insert(remaining_buffer.end(), - &incoming.buffer[i->offset], - &incoming.buffer[i->offset] + i->bytes); - } - - // Swap the remaining messages into the "incoming" set. - incoming.headers.swap(remaining_headers); - incoming.buffer.swap(remaining_buffer); - - // Set up the iterators pointing to the next header in each block - for (std::size_t i = 0; i < incoming.next_header.size(); ++i) - incoming.next_header[i] = incoming.headers.begin(); - } -} - -void mpi_process_group::receive_batch(boost::mpi::status& status) const -{ - //std::cerr << "Handling batch\n"; - outgoing_messages batch; - //impl_->comm.recv(status.source(),status.tag(),batch); - - //receive_oob(*this,status.source(),msg_batch,batch); - - // Determine how big the receive buffer should be -#if BOOST_VERSION >= 103600 - int size = status.count().get(); -#else - int size; - MPI_Status mpi_status(status); - MPI_Get_count(&mpi_status, MPI_PACKED, &size); -#endif - - // Allocate the receive buffer - boost::mpi::packed_iarchive in(impl_->comm,size); - - // Receive the message data - MPI_Recv(in.address(), size, MPI_PACKED, - status.source(), status.tag(), - impl_->comm, MPI_STATUS_IGNORE); - - // Unpack the message data - in >> batch; - receive_batch(status.source(),batch); -} - -std::pair -mpi_process_group::actual_communicator_and_tag(int tag, int block) const -{ - if (tag >= max_tags * static_cast(impl_->blocks.size())) - // Use the out-of-band reply communicator - return std::make_pair(impl_->oob_reply_comm, tag); - else - // Use the normal communicator and translate the tag - return std::make_pair(impl_->comm, - encode_tag(block == -1? my_block_number() : block, - tag)); -} - - -void mpi_process_group::synchronize() const -{ - // Don't synchronize if we've already finished - if (boost::mpi::environment::finalized()) - return; - -#ifdef DEBUG - std::cerr << "SYNC: " << process_id(*this) << std::endl; -#endif - - emit_on_synchronize(); - - process_id_type id = process_id(*this); // Our rank - process_size_type p = num_processes(*this); // The number of processes - - // Pack the remaining incoming messages into the beginning of the - // buffers, so that we can receive new messages in this - // synchronization step without losing those messages that have not - // yet been received. - pack_headers(); - - impl_->synchronizing_stage[id] = -1; - int stage=-1; - bool no_new_messages = false; - while (true) { - ++stage; -#ifdef DEBUG - std::cerr << "SYNC: " << id << " starting stage " << (stage+1) << ".\n"; -#endif - - // Tell everyone that we are synchronizing. Note: we use MPI_Isend since - // we absolutely cannot have any of these operations blocking. - - // increment the stage for the source - ++impl_->synchronizing_stage[id]; - if (impl_->synchronizing_stage[id] != stage) - std::cerr << "Expected stage " << stage << ", got " << impl_->synchronizing_stage[id] << std::endl; - assert(impl_->synchronizing_stage[id]==stage); - // record how many still have messages to be sent - if (static_cast(impl_->synchronizing_unfinished.size())<=stage) { - assert(static_cast(impl_->synchronizing_unfinished.size()) == stage); - impl_->synchronizing_unfinished.push_back(no_new_messages ? 0 : 1); - } - else - impl_->synchronizing_unfinished[stage]+=(no_new_messages ? 0 : 1); - - // record how many are in that stage - if (static_cast(impl_->processors_synchronizing_stage.size())<=stage) { - assert(static_cast(impl_->processors_synchronizing_stage.size()) == stage); - impl_->processors_synchronizing_stage.push_back(1); - } - else - ++impl_->processors_synchronizing_stage[stage]; - - impl_->synchronizing = true; - - for (int dest = 0; dest < p; ++dest) { - int sync_message = no_new_messages ? -1 : impl_->number_sent_batches[dest]; - if (dest != id) { - impl_->number_sent_batches[dest]=0; - MPI_Request request; - MPI_Isend(&sync_message, 1, MPI_INT, dest, msg_synchronizing, impl_->comm,&request); - int done=0; - do { - poll(); - MPI_Test(&request,&done,MPI_STATUS_IGNORE); - } while (!done); - } - else { // need to subtract how many messages I should have received - impl_->number_received_batches[id] -=impl_->number_sent_batches[id]; - impl_->number_sent_batches[id]=0; - } - } - - // Keep handling out-of-band messages until everyone has gotten - // to this point. - while (impl_->processors_synchronizing_stage[stage] synchronizing_stage[source] >= stage); - - // receive any batches sent in the meantime - // all have to be available already - while (true) { - bool done=true; - for (int source=0; source

    number_received_batches[source] < 0) - done = false; - if (done) - break; - poll(false,-1,true); - } - -#ifndef NO_IMMEDIATE_PROCESSING - for (int source=0; source

    number_received_batches[source] >= 0); -#endif - - impl_->synchronizing = false; - - // Flush out remaining messages - if (impl_->synchronizing_unfinished[stage]==0) - break; -#ifdef NO_IMMEDIATE_PROCESSING - for (process_id_type dest = 0; dest < p; ++dest) - process_batch(dest); -#endif - - no_new_messages = true; - for (process_id_type dest = 0; dest < p; ++dest) { - if (impl_->outgoing[dest].headers.size() || - impl_->number_sent_batches[dest]>0) - no_new_messages = false; - send_batch(dest); - } - } - - impl_->comm.barrier/*nomacro*/(); -#if 0 - // set up for next synchronize call - for (int source=0; sourcesynchronizing_stage[source] != stage) { - std::cerr << id << ": expecting stage " << stage << " from source " - << source << ", got " << impl_->synchronizing_stage[source] - << std::endl; - } - assert(impl_->synchronizing_stage[source]==stage); - } -#endif - std::fill(impl_->synchronizing_stage.begin(), - impl_->synchronizing_stage.end(), -1); - - // get rid of the information regarding recorded numbers of processors - // for the stages we just finished - impl_->processors_synchronizing_stage.clear(); - impl_->synchronizing_unfinished.clear(); - - for (process_id_type dest = 0; dest < p; ++dest) - assert (impl_->outgoing[dest].headers.empty()); -#ifndef NO_IMMEDIATE_PROCESSING - for (int source=0; source

    number_received_batches[source] == 0); -#endif - - impl_->free_sent_batches(); -#ifdef DEBUG - std::cerr << "SYNC: " << process_id(*this) << " completed." << std::endl; -#endif -} - -optional > -probe(const mpi_process_group& pg) -{ return pg.probe(); } - -void mpi_process_group::poll_requests(int block) const -{ - int size = impl_->requests.size(); - if (size==0) - return; - std::vector statuses(size); - std::vector indices(size); - - while (true) { - MPI_Testsome(impl_->requests.size(),&impl_->requests[0], - &size,&indices[0],&statuses[0]); - if (size==0) - return; // no message waiting - - // remove handled requests before we get the chance to be recursively called - if (size) { - std::vector active_requests; - std::size_t i=0; - int j=0; - for (;i< impl_->requests.size() && j< size; ++i) { - if (int(i)==indices[j]) - // release the dealt-with request - ++j; - else // copy and keep the request - active_requests.push_back(impl_->requests[i]); - } - while (i < impl_->requests.size()) - active_requests.push_back(impl_->requests[i++]); - impl_->requests.swap(active_requests); - } - - optional > result; - for (int i=0;i < size; ++i) { - std::pair decoded = decode_tag(statuses[i].MPI_TAG); - block_type* block = impl_->blocks[decoded.first]; - - assert (decoded.second < static_cast(block->triggers.size()) && block->triggers[decoded.second]); - // We have a trigger for this message; use it - trigger_receive_context old_context = impl_->trigger_context; - impl_->trigger_context = trc_irecv_out_of_band; - block->triggers[decoded.second]->receive(*this, statuses[i].MPI_SOURCE, - decoded.second, impl_->trigger_context, decoded.first); - impl_->trigger_context = old_context; - } - } -} - - -optional > -mpi_process_group:: -poll(bool wait, int block, bool synchronizing) const -{ - // Set the new trigger context for these receive operations - trigger_receive_context old_context = impl_->trigger_context; - if (synchronizing) - impl_->trigger_context = trc_in_synchronization; - else - impl_->trigger_context = trc_out_of_band; - - //wait = false; - optional status; - bool finished=false; - optional > result; - do { - poll_requests(block); - // Check for any messages not yet received. -#ifdef PBGL_PROCESS_GROUP_NO_IRECV - if (wait) - status = impl_->comm.probe(); - else -#endif - status = impl_->comm.iprobe(); - - if (status) { // we have a message - // Decode the message - std::pair decoded = decode_tag(status.get().tag()); - if (maybe_emit_receive(status.get().source(), status.get().tag())) - // We received the message out-of-band; poll again - finished = false; - else if (decoded.first == (block == -1 ? my_block_number() : block)) { - // This message is for us, but not through a trigger. Return - // the decoded message. - result = std::make_pair(status.get().source(), decoded.second); - // otherwise we didn't match any message we know how to deal with, so - // pretend no message exists. - finished = true; - } - } - else - // We don't have a message to process; we're done. - finished=!wait; - } while (!finished); - - // Restore the prior trigger context - impl_->trigger_context = old_context; - poll_requests(block); - return result; -} - -void synchronize(const mpi_process_group& pg) { pg.synchronize(); } - -mpi_process_group mpi_process_group::base() const -{ - mpi_process_group copy(*this); - copy.block_num.reset(); - return copy; -} - - -void mpi_process_group::impl::free_sent_batches() -{ - typedef std::list::iterator iterator; - iterator it = sent_batches.begin(); - int flag; - int result; - while(it != sent_batches.end()) { - result = MPI_Test(&it->request,&flag,MPI_STATUS_IGNORE); - assert(result == MPI_SUCCESS); - iterator next=it; - ++next; - if (flag) - sent_batches.erase(it); - it=next; - } -#ifdef PREALLOCATE_BATCHES - for (std::size_t i=0; i< batch_pool.size();++i) { - if(batch_pool[i].request != MPI_REQUEST_NULL) { - result = MPI_Test(&batch_pool[i].request,&flag,MPI_STATUS_IGNORE); - assert(result == MPI_SUCCESS); - if (flag) { - free_batches.push(i); - batch_pool[i].request = MPI_REQUEST_NULL; - batch_pool[i].buffer.resize(0); - } - } - } -#endif -} - -void -mpi_process_group::install_trigger(int tag, int block, - shared_ptr const& launcher) -{ - block_type* my_block = impl_->blocks[block]; - assert(my_block); - - // Make sure we have enough space in the structure for this trigger. - if (launcher->tag() >= static_cast(my_block->triggers.size())) - my_block->triggers.resize(launcher->tag() + 1); - - // If someone already put a trigger in this spot, we have a big - // problem. - if (my_block->triggers[launcher->tag()]) { - std::cerr << "Block " << my_block_number() - << " already has a trigger for tag " << launcher->tag() - << std::endl; - } - assert(!my_block->triggers[launcher->tag()]); - - // Attach a new trigger launcher - my_block->triggers[launcher->tag()] = launcher; -} - -std::size_t mpi_process_group::message_buffer_size() -{ - return message_buffer.size(); -} - - -void mpi_process_group::set_message_buffer_size(std::size_t s) -{ - int sz; - void* ptr; - if (!message_buffer.empty()) { - MPI_Buffer_detach(&ptr,&sz); - assert(ptr == &message_buffer.front()); - assert(static_cast(sz) == message_buffer.size()); - } - else if (old_buffer != 0) - MPI_Buffer_detach(&old_buffer,&old_buffer_size); - message_buffer.resize(s); - if (s) - MPI_Buffer_attach(&message_buffer.front(), message_buffer.size()); - else if (old_buffer_size) - MPI_Buffer_attach(old_buffer, old_buffer_size); -} - - -std::vector mpi_process_group::message_buffer; -int mpi_process_group::old_buffer_size=0; -void* mpi_process_group::old_buffer=0; - -} } } // end namespace boost::graph::distributed diff --git a/src/tag_allocator.cpp b/src/tag_allocator.cpp deleted file mode 100644 index a89a2a2d..00000000 --- a/src/tag_allocator.cpp +++ /dev/null @@ -1,45 +0,0 @@ -// Copyright (C) 2007 Douglas Gregor - -// 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 - -namespace boost { namespace graph { namespace distributed { namespace detail { - -tag_allocator::token tag_allocator::get_tag() -{ - int tag; - - if (!freed.empty()) { - // Grab the tag at the top of the stack. - tag = freed.back(); - freed.pop_back(); - } else - // Grab the bottom tag and move the bottom down - tag = bottom--; - - return token(this, tag); -} - -tag_allocator::token::token(const token& other) - : allocator(other.allocator), tag_(other.tag_) -{ - // other no longer owns this tag - other.tag_ = -1; -} - -tag_allocator::token::~token() -{ - if (tag_ != -1) { - if (tag_ == allocator->bottom + 1) - // This is the bottommost tag: just bump up the bottom - ++allocator->bottom; - else - // This tag isn't the bottom, so push it only the freed stack - allocator->freed.push_back(tag_); - } -} - -} } } } // end namespace boost::graph::distributed::detail From 01b30ee264f4b4711ecd0ecba240f921fea1868d Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Sat, 11 Apr 2009 17:01:34 +0000 Subject: [PATCH 136/224] Fixed inspection problems [SVN r52336] --- include/boost/graph/property_iter_range.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/boost/graph/property_iter_range.hpp b/include/boost/graph/property_iter_range.hpp index 5f166b6c..8485fed3 100644 --- a/include/boost/graph/property_iter_range.hpp +++ b/include/boost/graph/property_iter_range.hpp @@ -1,5 +1,5 @@ -// (C) Copyright François Faure, iMAGIS-GRAVIR / UJF, 2001. +// (C) Copyright Francois Faure, iMAGIS-GRAVIR / UJF, 2001. // // Distributed under the Boost Software License, Version 1.0. (See // accompanying file LICENSE_1_0.txt or copy at From 704e2a08941e6e8ddb7c6c67f02da1d1a4742b97 Mon Sep 17 00:00:00 2001 From: Andrew Sutton Date: Wed, 15 Apr 2009 12:24:21 +0000 Subject: [PATCH 137/224] Added missing copyright info for test files. [SVN r52403] --- test/adj_list_invalidation.cpp | 5 +++++ test/adj_list_loops.cpp | 5 +++++ test/core_numbers_test.cpp | 5 +++++ test/dimacs.cpp | 5 +++++ test/test_graphs.cpp | 12 ++++++++---- 5 files changed, 28 insertions(+), 4 deletions(-) diff --git a/test/adj_list_invalidation.cpp b/test/adj_list_invalidation.cpp index e217c92f..3afdfb5b 100644 --- a/test/adj_list_invalidation.cpp +++ b/test/adj_list_invalidation.cpp @@ -1,3 +1,8 @@ +// (C) Copyright Andrew Sutton 2009 +// +// 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 #include diff --git a/test/adj_list_loops.cpp b/test/adj_list_loops.cpp index 6fc8be54..52ecd2e2 100644 --- a/test/adj_list_loops.cpp +++ b/test/adj_list_loops.cpp @@ -1,3 +1,8 @@ +// (C) Copyright Andrew Sutton 2009 +// +// 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) #if __GNUC__ == 4 && __GNUC_MINOR__ >= 3 # define BOOST_NO_HASH diff --git a/test/core_numbers_test.cpp b/test/core_numbers_test.cpp index 0349d8e6..a4fbf58c 100644 --- a/test/core_numbers_test.cpp +++ b/test/core_numbers_test.cpp @@ -1,3 +1,8 @@ +// (C) Copyright David Gleich 2007 +// +// 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 #include diff --git a/test/dimacs.cpp b/test/dimacs.cpp index f0edea89..7cad5ec0 100644 --- a/test/dimacs.cpp +++ b/test/dimacs.cpp @@ -1,3 +1,8 @@ +// (C) Copyright Andrew Sutton 2009 +// +// 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 #include diff --git a/test/test_graphs.cpp b/test/test_graphs.cpp index 5197d762..1198306f 100644 --- a/test/test_graphs.cpp +++ b/test/test_graphs.cpp @@ -1,9 +1,17 @@ +// (C) Copyright 2007-2009 Andrew Sutton +// +// 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 #include #include +// TODO: Finish implementing this test module. In theory, this will become a +// generic testing facility for any kind of graph declaration. + using namespace std; using namespace boost; @@ -28,16 +36,12 @@ struct arc int n; }; -// TODO: Finish implementing this test. Actually, generalize the test so that -// it works for lots of different graph types. - template void test() { typedef typename Graph::vertex_descriptor Vertex; Graph g; BOOST_ASSERT(num_vertices(g) == 0); - } int main() From 9b25481ac81e36a14e0372106607c3b4d1921117 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Fri, 17 Apr 2009 15:40:34 +0000 Subject: [PATCH 138/224] Trying to fix VC++ issue with overloading [SVN r52443] --- include/boost/graph/betweenness_centrality.hpp | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/include/boost/graph/betweenness_centrality.hpp b/include/boost/graph/betweenness_centrality.hpp index 15cfe741..06b7be06 100644 --- a/include/boost/graph/betweenness_centrality.hpp +++ b/include/boost/graph/betweenness_centrality.hpp @@ -512,6 +512,16 @@ namespace detail { namespace graph { } }; + template + struct is_bgl_named_params { + BOOST_STATIC_CONSTANT(bool, value = false); + }; + + template + struct is_bgl_named_params > { + BOOST_STATIC_CONSTANT(bool, value = true); + }; + } } // end namespace detail::graph template @@ -533,8 +543,11 @@ brandes_betweenness_centrality(const Graph& g, get_param(params, edge_weight)); } +// disable_if is required to work around problem with MSVC 7.1 (it seems to not +// get partial ordering getween this overload and the previous one correct) template -void +typename disable_if, + void>::type brandes_betweenness_centrality(const Graph& g, CentralityMap centrality BOOST_GRAPH_ENABLE_IF_MODELS_PARM(Graph,vertex_list_graph_tag)) { From 7895ca9e8f0a6a9fbc490a7024d5bc3f13e02d54 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Sat, 18 Apr 2009 16:17:36 +0000 Subject: [PATCH 139/224] Relicensed files/added copyright info based on permissions from file authors [SVN r52470] --- CMakeLists.txt | 6 ++++++ doc/lengauer_tarjan_dominator.htm | 14 +++++--------- src/CMakeLists.txt | 6 ++++++ test/CMakeLists.txt | 6 ++++++ 4 files changed, 23 insertions(+), 9 deletions(-) mode change 100755 => 100644 doc/lengauer_tarjan_dominator.htm diff --git a/CMakeLists.txt b/CMakeLists.txt index 93f55a76..ac5d96bb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,3 +1,9 @@ +# Copyright (C) 2008 Mike Jackson +# +# 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) + #---------------------------------------------------------------------------- # This file was automatically generated from the original CMakeLists.txt file diff --git a/doc/lengauer_tarjan_dominator.htm b/doc/lengauer_tarjan_dominator.htm old mode 100755 new mode 100644 index beee2317..e6e70ff6 --- a/doc/lengauer_tarjan_dominator.htm +++ b/doc/lengauer_tarjan_dominator.htm @@ -1,14 +1,10 @@ Boost Graph Library: Lengauer-Tarjan Dominator Tree Algorithm diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 8bb27ee7..2a957166 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,3 +1,9 @@ +# Copyright (C) 2008 Mike Jackson +# +# 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) + add_definitions(-DBOOST_GRAPH_NO_LIB=1) if (MSVC) diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index fd459b3f..27292309 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -1,3 +1,9 @@ +# Copyright (C) 2008 Mike Jackson +# +# 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) + boost_additional_test_dependencies(graph BOOST_DEPENDS test assign) boost_test_run(transitive_closure_test) From 2b2061df1d2626a82a7025c0a2287a609a70b30e Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Sat, 18 Apr 2009 17:53:12 +0000 Subject: [PATCH 140/224] Renamed file to avoid problems with inspect tool [SVN r52471] --- test/Jamfile.v2 | 2 +- test/{metric_tsp_approx.txt => metric_tsp_approx.graph} | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename test/{metric_tsp_approx.txt => metric_tsp_approx.graph} (100%) diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index c1562ee2..b88c4727 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -100,7 +100,7 @@ test-suite graph_test : : $(PLANAR_INPUT_FILES) ] [ run r_c_shortest_paths_test.cpp ] [ run is_straight_line_draw_test.cpp ] - [ run metric_tsp_approx.cpp : metric_tsp_approx.txt ] + [ run metric_tsp_approx.cpp : metric_tsp_approx.graph ] [ compile dimacs.cpp ] [ run bron_kerbosch_all_cliques.cpp ] [ run tiernan_all_cycles.cpp ] diff --git a/test/metric_tsp_approx.txt b/test/metric_tsp_approx.graph similarity index 100% rename from test/metric_tsp_approx.txt rename to test/metric_tsp_approx.graph From b4b0ec400b4ed71bc5b2cc4131a4fda87f41540f Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Sat, 18 Apr 2009 23:59:45 +0000 Subject: [PATCH 141/224] "Mike Jackson" -> "Michael Jackson" in copyright messages [SVN r52475] --- CMakeLists.txt | 2 +- src/CMakeLists.txt | 2 +- test/CMakeLists.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index ac5d96bb..4745fb22 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright (C) 2008 Mike Jackson +# Copyright (C) 2008 Michael Jackson # # Use, modification and distribution is subject to the Boost Software # License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 2a957166..df2395aa 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright (C) 2008 Mike Jackson +# Copyright (C) 2008 Michael Jackson # # Use, modification and distribution is subject to the Boost Software # License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 27292309..c0490018 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright (C) 2008 Mike Jackson +# Copyright (C) 2008 Michael Jackson # # Use, modification and distribution is subject to the Boost Software # License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at From 5e86165addf49782165fe3667fc76388343639e8 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Sun, 19 Apr 2009 01:56:03 +0000 Subject: [PATCH 142/224] Fixed tab [SVN r52476] --- include/boost/pending/fibonacci_heap.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/boost/pending/fibonacci_heap.hpp b/include/boost/pending/fibonacci_heap.hpp index 5fc04187..a386e285 100644 --- a/include/boost/pending/fibonacci_heap.hpp +++ b/include/boost/pending/fibonacci_heap.hpp @@ -193,7 +193,7 @@ public: } if (_mark[p] == false) { _mark[p] = true; - --_degree[p]; + --_degree[p]; break; } else --_degree[p]; From d0aeb0072c5fdd4abd4ece713fce2a622b8401d3 Mon Sep 17 00:00:00 2001 From: Andrew Sutton Date: Mon, 20 Apr 2009 13:43:43 +0000 Subject: [PATCH 143/224] Applied performance patch from Jongsoo Park. [SVN r52506] --- include/boost/graph/dominator_tree.hpp | 73 ++++++++++++++------------ 1 file changed, 38 insertions(+), 35 deletions(-) diff --git a/include/boost/graph/dominator_tree.hpp b/include/boost/graph/dominator_tree.hpp index bb34bbe9..81fa4d1c 100644 --- a/include/boost/graph/dominator_tree.hpp +++ b/include/boost/graph/dominator_tree.hpp @@ -1,19 +1,21 @@ //======================================================================= -// Copyright (C) 2005 Jong Soo Park +// Copyright (C) 2005-2009 Jongsoo Park // // 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) //======================================================================= -// Dominator tree computation + #ifndef BOOST_GRAPH_DOMINATOR_HPP #define BOOST_GRAPH_DOMINATOR_HPP -#include #include #include +#include #include +// Dominator tree computation + namespace boost { namespace detail { /** @@ -26,13 +28,13 @@ namespace boost { { public : typedef Tag event_filter; - time_stamper_with_vertex_vector(TimeMap timeMap, VertexVector& v, + time_stamper_with_vertex_vector(TimeMap timeMap, VertexVector& v, TimeT& t) : timeStamper_(timeMap, t), v_(v) { } template - void - operator()(const typename property_traits::key_type& v, + void + operator()(const typename property_traits::key_type& v, const Graph& g) { timeStamper_(v, g); @@ -52,7 +54,7 @@ namespace boost { stamp_times_with_vertex_vector(TimeMap timeMap, VertexVector& v, TimeT& t, Tag) { - return time_stamper_with_vertex_vector(timeMap, v, t); } @@ -76,29 +78,29 @@ namespace boost { ancestor_(num_vertices(g), graph_traits::null_vertex()), samedom_(ancestor_), best_(semi_), - semiMap_(make_iterator_property_map(semi_.begin(), + semiMap_(make_iterator_property_map(semi_.begin(), get(vertex_index, g))), - ancestorMap_(make_iterator_property_map(ancestor_.begin(), + ancestorMap_(make_iterator_property_map(ancestor_.begin(), get(vertex_index, g))), - bestMap_(make_iterator_property_map(best_.begin(), + bestMap_(make_iterator_property_map(best_.begin(), get(vertex_index, g))), buckets_(num_vertices(g)), - bucketMap_(make_iterator_property_map(buckets_.begin(), + bucketMap_(make_iterator_property_map(buckets_.begin(), get(vertex_index, g))), entry_(entry), domTreePredMap_(domTreePredMap), - samedomMap(make_iterator_property_map(samedom_.begin(), + numOfVertices_(num_vertices(g)), + samedomMap(make_iterator_property_map(samedom_.begin(), get(vertex_index, g))) { } - - void - operator()(const Vertex& n, const TimeMap& dfnumMap, + + void + operator()(const Vertex& n, const TimeMap& dfnumMap, const PredMap& parentMap, const Graph& g) { if (n == entry_) return; - const VerticesSizeType numOfVertices = num_vertices(g); const Vertex p(get(parentMap, n)); Vertex s(p); @@ -113,14 +115,14 @@ namespace boost { // Let semi(u) be a candidate for semi(n) // of all these candidates, the one with lowest dfnum is // the semidominator of n. - + // For each predecessor of n typename graph_traits::in_edge_iterator inItr, inEnd; for (tie(inItr, inEnd) = in_edges(n, g); inItr != inEnd; ++inItr) { const Vertex v = source(*inItr, g); // To deal with unreachable nodes - if (get(dfnumMap, v) < 0 || get(dfnumMap, v) >= numOfVertices) + if (get(dfnumMap, v) < 0 || get(dfnumMap, v) >= numOfVertices_) continue; Vertex s2; @@ -147,7 +149,7 @@ namespace boost { // * Dominator thm. : On the spanning-tree path below semi(n) and // above or including n, let y be the node // with the smallest-numbered semidominator. Then, - // + // // idom(n) = semi(n) if semi(y)=semi(n) or // idom(y) if semi(y) != semi(n) typename std::deque::iterator buckItr; @@ -171,7 +173,7 @@ namespace boost { /** * Evaluate function in Tarjan's path compression */ - const Vertex + const Vertex ancestor_with_lowest_semi_(const Vertex& v, const TimeMap& dfnumMap) { const Vertex a(get(ancestorMap_, v)); @@ -199,9 +201,10 @@ namespace boost { const Vertex& entry_; DomTreePredMap domTreePredMap_; + const VerticesSizeType numOfVertices_; public : - + PredMap samedomMap; }; @@ -219,7 +222,7 @@ namespace boost { * graph_traits::null_vertex in parentMap. * @pre Unreachable nodes must be masked as * (std::numeric_limits::max)() in dfnumMap. - * + * * @param domTreePredMap [out] : immediate dominator map (parent map * in dom. tree) * @@ -227,7 +230,7 @@ namespace boost { * * @todo : Optimization in Finding Dominators in Practice, Loukas Georgiadis */ - template void lengauer_tarjan_dominator_tree_without_dfs @@ -274,7 +277,7 @@ namespace boost { } } } - + /** * Unlike lengauer_tarjan_dominator_tree_without_dfs, * dfs is run in this function and @@ -283,7 +286,7 @@ namespace boost { * If the result of dfs required after this algorithm, * this function can eliminate the need of rerunning dfs. */ - template void lengauer_tarjan_dominator_tree @@ -304,7 +307,7 @@ namespace boost { VerticesSizeType time = (std::numeric_limits::max)(); - std::vector + std::vector colors(numOfVertices, color_traits::white()); depth_first_visit (g, entry, @@ -315,8 +318,8 @@ namespace boost { make_iterator_property_map(colors.begin(), indexMap)); // 2. Run main algorithm. - lengauer_tarjan_dominator_tree_without_dfs(g, entry, indexMap, dfnumMap, - parentMap, verticesByDFNum, + lengauer_tarjan_dominator_tree_without_dfs(g, entry, indexMap, dfnumMap, + parentMap, verticesByDFNum, domTreePredMap); } @@ -353,7 +356,7 @@ namespace boost { std::vector dfnum(numOfVertices, 0); TimeMap dfnumMap(make_iterator_property_map(dfnum.begin(), indexMap)); - std::vector parent(numOfVertices, + std::vector parent(numOfVertices, graph_traits::null_vertex()); PredMap parentMap(make_iterator_property_map(parent.begin(), indexMap)); @@ -361,7 +364,7 @@ namespace boost { // Run main algorithm lengauer_tarjan_dominator_tree(g, entry, - indexMap, dfnumMap, parentMap, + indexMap, dfnumMap, parentMap, verticesByDFNum, domTreePredMap); } @@ -397,7 +400,7 @@ namespace boost { const std::set N(vi, viend); bool change = true; - + std::vector< std::set > dom(numOfVertices, N); vertexSetMap domMap(make_iterator_property_map(dom.begin(), indexMap)); get(domMap, entry).clear(); @@ -411,15 +414,15 @@ namespace boost { if (*vi == entry) continue; std::set T(N); - + typename graph_traits::in_edge_iterator inItr, inEnd; for (tie(inItr, inEnd) = in_edges(*vi, g); inItr != inEnd; ++inItr) { const Vertex p = source(*inItr, g); std::set tempSet; - std::set_intersection(T.begin(), T.end(), - get(domMap, p).begin(), + std::set_intersection(T.begin(), T.end(), + get(domMap, p).begin(), get(domMap, p).end(), std::inserter(tempSet, tempSet.begin())); T.swap(tempSet); @@ -480,7 +483,7 @@ namespace boost { { typename property_map::const_type indexMap = get(vertex_index, g); - + iterative_bit_vector_dominator_tree(g, entry, indexMap, domTreePredMap); } } // namespace boost From 6995f7fb7ec50be036fff616de128cfa3316372d Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Mon, 20 Apr 2009 13:45:08 +0000 Subject: [PATCH 144/224] Added license and copyright information [SVN r52507] --- doc/read_graphml.html | 10 ++++++++++ doc/read_graphml.rst | 10 +++++++++- doc/write_graphml.html | 9 +++++++++ doc/write_graphml.rst | 10 +++++++++- test/graphml_test.xml | 9 +++++++++ 5 files changed, 46 insertions(+), 2 deletions(-) diff --git a/doc/read_graphml.html b/doc/read_graphml.html index c28c584d..188f3266 100644 --- a/doc/read_graphml.html +++ b/doc/read_graphml.html @@ -1,5 +1,15 @@ + + diff --git a/doc/read_graphml.rst b/doc/read_graphml.rst index 90c3de2a..29fcdc94 100644 --- a/doc/read_graphml.rst +++ b/doc/read_graphml.rst @@ -2,6 +2,14 @@ |(logo)|__ ``read_graphml`` ============================ +.. Copyright (C) 2006 Tiago de Paula Peixoto + + 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: Tiago de Paula Peixoto + .. |(logo)| image:: ../../../boost.png :align: middle :alt: Boost @@ -155,4 +163,4 @@ Future Work .. _`Multi-Pass Iterator`: ../../iterator/index.html .. _dynamic_properties: ../../property_map/doc/dynamic_property_map.html .. _write_graphml: write_graphml.html -.. _Boost Jam Build Instructions: ../../../more/getting_started.html#Build_Install \ No newline at end of file +.. _Boost Jam Build Instructions: ../../../more/getting_started.html#Build_Install diff --git a/doc/write_graphml.html b/doc/write_graphml.html index 332254e4..1dbd1863 100644 --- a/doc/write_graphml.html +++ b/doc/write_graphml.html @@ -1,5 +1,14 @@ + diff --git a/doc/write_graphml.rst b/doc/write_graphml.rst index 82919170..e01c79f7 100644 --- a/doc/write_graphml.rst +++ b/doc/write_graphml.rst @@ -2,6 +2,14 @@ |(logo)|__ ``write_graphml`` ============================ +.. Copyright (C) 2006 Tiago de Paula Peixoto + + 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: Tiago de Paula Peixoto + .. |(logo)| image:: ../../../boost.png :align: middle :alt: Boost @@ -253,4 +261,4 @@ Notes .. _dynamic_properties: ../../property_map/doc/dynamic_property_map.html .. _read_graphml: read_graphml.html -.. _VertexListGraph: VertexListGraph.html \ No newline at end of file +.. _VertexListGraph: VertexListGraph.html diff --git a/test/graphml_test.xml b/test/graphml_test.xml index 25d56b47..40b43a12 100644 --- a/test/graphml_test.xml +++ b/test/graphml_test.xml @@ -1,4 +1,13 @@ + 42 From a18ee8efa527db0614ffca735fdda9b1ca4356d6 Mon Sep 17 00:00:00 2001 From: Andrew Sutton Date: Mon, 20 Apr 2009 13:50:25 +0000 Subject: [PATCH 145/224] Adding copyright information. [SVN r52508] --- examples/Jamfile.v2 | 4 ++++ quickbook/images/eq/Makefile | 4 ++++ quickbook/images/reference/Makefile | 4 ++++ 3 files changed, 12 insertions(+) diff --git a/examples/Jamfile.v2 b/examples/Jamfile.v2 index 92d1addf..45697227 100644 --- a/examples/Jamfile.v2 +++ b/examples/Jamfile.v2 @@ -1,3 +1,7 @@ +# Copyright (C) 2007-2009 Andrew Sutton +# +# 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) project : requirements diff --git a/quickbook/images/eq/Makefile b/quickbook/images/eq/Makefile index 1c4d7eff..ad9862da 100644 --- a/quickbook/images/eq/Makefile +++ b/quickbook/images/eq/Makefile @@ -1,3 +1,7 @@ +# Copyright (C) 2007-2009 Andrew Sutton +# +# 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) src = \ mean_geodesic.tex \ diff --git a/quickbook/images/reference/Makefile b/quickbook/images/reference/Makefile index fb2e7fc5..9dc80fd6 100644 --- a/quickbook/images/reference/Makefile +++ b/quickbook/images/reference/Makefile @@ -1,3 +1,7 @@ +# Copyright (C) 2007-2009 Andrew Sutton +# +# 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) GVFLAGS = -Tpng From c57722a10f4dc7caf8a35e8e6790f138a1e5e844 Mon Sep 17 00:00:00 2001 From: Andrew Sutton Date: Mon, 20 Apr 2009 14:34:59 +0000 Subject: [PATCH 146/224] Migrating all examples into example directory [SVN r52509] --- {examples => example}/Jamfile.v2 | 0 .../bron_kerbosch_clique_number.cpp | 0 .../bron_kerbosch_print_cliques.cpp | 0 .../closeness_centrality.cpp | 0 .../clustering_coefficient.cpp | 0 {examples => example}/comm_network.graph | 0 {examples => example}/degree_centrality.cpp | 0 {examples => example}/eccentricity.cpp | 0 {examples => example}/helper.hpp | 0 .../inclusive_mean_geodesic.cpp | 0 {examples => example}/influence_prestige.cpp | 0 {examples => example}/info_network.graph | 0 {examples => example}/mean_geodesic.cpp | 0 {examples => example}/prism_3_2.graph | 0 {examples => example}/prob_network.graph | 0 example/quick-tour.cpp | 4 +- example/quick_tour.cpp | 33 ++- .../scaled_closeness_centrality.cpp | 0 {examples => example}/social_network.graph | 0 .../tiernan_girth_circumference.cpp | 0 .../tiernan_print_cycles.cpp | 0 quickbook/Jamfile.v2 | 7 +- quickbook/boost_reference.qbk | 78 +++--- quickbook/graph.qbk | 2 +- quickbook/history.qbk | 28 +- quickbook/introduction.qbk | 262 ++++++++++-------- .../reference/betweenness_centrality.qbk | 4 +- .../reference/bron_kerbosch_all_cliques.qbk | 4 +- quickbook/reference/closeness_centrality.qbk | 4 +- .../reference/clustering_coefficient.qbk | 4 +- quickbook/reference/eccentricity.qbk | 2 +- quickbook/reference/mean_geodesic.qbk | 2 +- quickbook/reference/tiernan_all_cycles.qbk | 4 +- quickbook/tour.qbk | 160 ++++++----- 34 files changed, 333 insertions(+), 265 deletions(-) rename {examples => example}/Jamfile.v2 (100%) rename {examples => example}/bron_kerbosch_clique_number.cpp (100%) rename {examples => example}/bron_kerbosch_print_cliques.cpp (100%) rename {examples => example}/closeness_centrality.cpp (100%) rename {examples => example}/clustering_coefficient.cpp (100%) rename {examples => example}/comm_network.graph (100%) rename {examples => example}/degree_centrality.cpp (100%) rename {examples => example}/eccentricity.cpp (100%) rename {examples => example}/helper.hpp (100%) rename {examples => example}/inclusive_mean_geodesic.cpp (100%) rename {examples => example}/influence_prestige.cpp (100%) rename {examples => example}/info_network.graph (100%) rename {examples => example}/mean_geodesic.cpp (100%) rename {examples => example}/prism_3_2.graph (100%) rename {examples => example}/prob_network.graph (100%) rename {examples => example}/scaled_closeness_centrality.cpp (100%) rename {examples => example}/social_network.graph (100%) rename {examples => example}/tiernan_girth_circumference.cpp (100%) rename {examples => example}/tiernan_print_cycles.cpp (100%) diff --git a/examples/Jamfile.v2 b/example/Jamfile.v2 similarity index 100% rename from examples/Jamfile.v2 rename to example/Jamfile.v2 diff --git a/examples/bron_kerbosch_clique_number.cpp b/example/bron_kerbosch_clique_number.cpp similarity index 100% rename from examples/bron_kerbosch_clique_number.cpp rename to example/bron_kerbosch_clique_number.cpp diff --git a/examples/bron_kerbosch_print_cliques.cpp b/example/bron_kerbosch_print_cliques.cpp similarity index 100% rename from examples/bron_kerbosch_print_cliques.cpp rename to example/bron_kerbosch_print_cliques.cpp diff --git a/examples/closeness_centrality.cpp b/example/closeness_centrality.cpp similarity index 100% rename from examples/closeness_centrality.cpp rename to example/closeness_centrality.cpp diff --git a/examples/clustering_coefficient.cpp b/example/clustering_coefficient.cpp similarity index 100% rename from examples/clustering_coefficient.cpp rename to example/clustering_coefficient.cpp diff --git a/examples/comm_network.graph b/example/comm_network.graph similarity index 100% rename from examples/comm_network.graph rename to example/comm_network.graph diff --git a/examples/degree_centrality.cpp b/example/degree_centrality.cpp similarity index 100% rename from examples/degree_centrality.cpp rename to example/degree_centrality.cpp diff --git a/examples/eccentricity.cpp b/example/eccentricity.cpp similarity index 100% rename from examples/eccentricity.cpp rename to example/eccentricity.cpp diff --git a/examples/helper.hpp b/example/helper.hpp similarity index 100% rename from examples/helper.hpp rename to example/helper.hpp diff --git a/examples/inclusive_mean_geodesic.cpp b/example/inclusive_mean_geodesic.cpp similarity index 100% rename from examples/inclusive_mean_geodesic.cpp rename to example/inclusive_mean_geodesic.cpp diff --git a/examples/influence_prestige.cpp b/example/influence_prestige.cpp similarity index 100% rename from examples/influence_prestige.cpp rename to example/influence_prestige.cpp diff --git a/examples/info_network.graph b/example/info_network.graph similarity index 100% rename from examples/info_network.graph rename to example/info_network.graph diff --git a/examples/mean_geodesic.cpp b/example/mean_geodesic.cpp similarity index 100% rename from examples/mean_geodesic.cpp rename to example/mean_geodesic.cpp diff --git a/examples/prism_3_2.graph b/example/prism_3_2.graph similarity index 100% rename from examples/prism_3_2.graph rename to example/prism_3_2.graph diff --git a/examples/prob_network.graph b/example/prob_network.graph similarity index 100% rename from examples/prob_network.graph rename to example/prob_network.graph diff --git a/example/quick-tour.cpp b/example/quick-tour.cpp index d790e594..2db005f6 100644 --- a/example/quick-tour.cpp +++ b/example/quick-tour.cpp @@ -1,14 +1,16 @@ //======================================================================= -// Copyright 2001 Jeremy G. Siek, Andrew Lumsdaine, Lie-Quan Lee, +// Copyright 2001 Jeremy G. Siek, Andrew Lumsdaine, Lie-Quan Lee, // // 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 boost; template < typename VertexDescriptor, typename VertexNameMap > void diff --git a/example/quick_tour.cpp b/example/quick_tour.cpp index 78128c9b..ecabb4c9 100644 --- a/example/quick_tour.cpp +++ b/example/quick_tour.cpp @@ -8,11 +8,10 @@ //======================================================================= #include -#include // for std::cout -#include // for std::pair -#include // for std::for_each -#include // for boost::tie -#include // for boost::graph_traits +#include // for std::cout +#include // for std::pair +#include // for std::for_each +#include // for boost::tie #include #include @@ -24,7 +23,7 @@ template struct exercise_vertex { void operator()(const Vertex& v) const { using namespace boost; - typename property_map::type + typename property_map::type vertex_id = get(vertex_index, g); std::cout << "vertex: " << get(vertex_id, v) << std::endl; @@ -32,7 +31,7 @@ template struct exercise_vertex { std::cout << "\tout-edges: "; typename graph_traits::out_edge_iterator out_i, out_end; typename graph_traits::edge_descriptor e; - for (tie(out_i, out_end) = out_edges(v, g); + for (tie(out_i, out_end) = out_edges(v, g); out_i != out_end; ++out_i) { e = *out_i; @@ -42,7 +41,7 @@ template struct exercise_vertex { } std::cout << std::endl; - // Write out the incoming edges + // Write out the incoming edges std::cout << "\tin-edges: "; typename graph_traits::in_edge_iterator in_i, in_end; for (tie(in_i, in_end) = in_edges(v, g); in_i != in_end; ++in_i) @@ -54,7 +53,7 @@ template struct exercise_vertex { } std::cout << std::endl; - // Write out all adjacent vertices + // Write out all adjacent vertices std::cout << "\tadjacent vertices: "; typename graph_traits::adjacency_iterator ai, ai_end; for (tie(ai,ai_end) = adjacent_vertices(v, g); ai != ai_end; ++ai) @@ -78,7 +77,7 @@ int main(int,char*[]) // writing out the edges in the graph typedef std::pair Edge; - Edge edge_array[] = + Edge edge_array[] = { Edge(A,B), Edge(A,D), Edge(C,A), Edge(D,C), Edge(C,E), Edge(B,D), Edge(D,E), }; const int num_edges = sizeof(edge_array)/sizeof(edge_array[0]); @@ -101,7 +100,7 @@ int main(int,char*[]) transmission_delay, num_vertices); #endif - boost::property_map::type + boost::property_map::type vertex_id = get(vertex_index, g); boost::property_map::type trans_delay = get(edge_weight, g); @@ -112,29 +111,29 @@ int main(int,char*[]) for (vp = vertices(g); vp.first != vp.second; ++vp.first) std::cout << name[get(vertex_id, *vp.first)] << " "; std::cout << std::endl; - + std::cout << "edges(g) = "; graph_traits::edge_iterator ei, ei_end; for (tie(ei,ei_end) = edges(g); ei != ei_end; ++ei) std::cout << "(" << name[get(vertex_id, source(*ei, g))] << "," << name[get(vertex_id, target(*ei, g))] << ") "; std::cout << std::endl; - + std::for_each(vertices(g).first, vertices(g).second, exercise_vertex(g)); - + std::map graph_attr, vertex_attr, edge_attr; graph_attr["size"] = "3,3"; graph_attr["rankdir"] = "LR"; graph_attr["ratio"] = "fill"; vertex_attr["shape"] = "circle"; - boost::write_graphviz(std::cout, g, + boost::write_graphviz(std::cout, g, make_label_writer(name), make_label_writer(trans_delay), - make_graph_attributes_writer(graph_attr, vertex_attr, + make_graph_attributes_writer(graph_attr, vertex_attr, edge_attr)); - + return 0; } diff --git a/examples/scaled_closeness_centrality.cpp b/example/scaled_closeness_centrality.cpp similarity index 100% rename from examples/scaled_closeness_centrality.cpp rename to example/scaled_closeness_centrality.cpp diff --git a/examples/social_network.graph b/example/social_network.graph similarity index 100% rename from examples/social_network.graph rename to example/social_network.graph diff --git a/examples/tiernan_girth_circumference.cpp b/example/tiernan_girth_circumference.cpp similarity index 100% rename from examples/tiernan_girth_circumference.cpp rename to example/tiernan_girth_circumference.cpp diff --git a/examples/tiernan_print_cycles.cpp b/example/tiernan_print_cycles.cpp similarity index 100% rename from examples/tiernan_print_cycles.cpp rename to example/tiernan_print_cycles.cpp diff --git a/quickbook/Jamfile.v2 b/quickbook/Jamfile.v2 index d821b3e4..43bd0212 100644 --- a/quickbook/Jamfile.v2 +++ b/quickbook/Jamfile.v2 @@ -1,9 +1,8 @@ - -# Copyright John Maddock 2005. Use, modification, and distribution are -# subject to the Boost Software License, Version 1.0. (See accompanying +# Copyright (C) 2007-2009 Andrew Sutton +# +# 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) - xml graph : graph.qbk ; boostbook standalone diff --git a/quickbook/boost_reference.qbk b/quickbook/boost_reference.qbk index 500acecf..54ca888a 100644 --- a/quickbook/boost_reference.qbk +++ b/quickbook/boost_reference.qbk @@ -25,32 +25,42 @@ [template time_stamper[] [link boost_graph.reference.event_visitors.time_stamper [^time_stamper]]] [template property_writer[] [link boost_graph.reference.event_visitors.property_writer [^property_writer]]] +[/ Attribute BGL interface function back to concept definitions /] +[template add_vertex[] [link + boost_graph.concepts.graph_concepts.mutable_graph [^add_vertex]]] +[template remove_vertex[] [link + boost_graph.concepts.graph_concepts.mutable_graph [^remove_vertex]]] +[template add_edge[] [link + boost_graph.concepts.graph_concepts.mutable_graph [^add_edge]]] +[template remove_edge[] [link + boost_graph.concepts.graph_concepts.mutable_graph [^remove_edge]]] + [/ Fundamental /] [template breadth_first_search[] [link boost_graph.reference.algorithms.fundamental.breadth_first_search - [^breadth_first_search()]]] + [^breadth_first_search]]] [template depth_first_search[] [link boost_graph.reference.algorithms.fundamental.depth_first_search - [^depth_first_search()]]] + [^depth_first_search]]] [/ Shortest Path /] [template dijkstra_shortest_paths[] [link boost_graph.reference.algorithms.shortest_paths.dijkstra_shortest_paths - [^dijkstra_shortest_paths()]]] + [^dijkstra_shortest_paths]]] [template bellman_ford_shortest_paths[] [link boost_graph.reference.algorithms.shortest_paths.bellman_ford_shortest_paths - [^bellman_ford_shortest_paths()]]] + [^bellman_ford_shortest_paths]]] [template floyd_warshall_all_pairs_shortest_paths[] [link boost_graph.reference.algorithms.shortest_paths.floyd_warshall_all_pairs_shortest_paths - [^floyd_warshall_all_pairs_shortest_paths()]]] + [^floyd_warshall_all_pairs_shortest_paths]]] [template johnson_all_pairs_shortest_paths[] [link boost_graph.reference.algorithms.shortest_paths.johnson_all_pairs_shortest_paths - [^johnson_all_pairs_shortest_paths()]]] + [^johnson_all_pairs_shortest_paths]]] [/ Connectivity /] [template connected_components[] [link boost_graph.reference.algorithms.connectivity.connected_components - [^connected_components()]]] + [^connected_components]]] [template strong_connected_components[] [link boost_graph.reference.algorithms.connectivity.strongly_connected_components [^strongly_connected_components]]] @@ -58,80 +68,86 @@ [/ Subgraph/ ] [template bron_kerbosch_visit_cliques[] [link boost_graph.reference.algorithms.subgraph.bron_kerbosch_all_cliques - [^bron_kerbosch_all_cliques()]]] + [^bron_kerbosch_all_cliques]]] [template tiernan_all_cycles[] [link boost_graph.reference.algorithms.subgraph.tiernan_all_cycles.__tiernan_all_cycles___ - [^tiernan_all_cycles()]]] + [^tiernan_all_cycles]]] [template tiernan_girth[] [link boost_graph.reference.algorithms.subgraph.tiernan_all_cycles.__tiernan_girth___ - [^tiernan_girth()]]] + [^tiernan_girth]]] [template tiernan_circumference[] [link boost_graph.reference.algorithms.subgraph.tiernan_all_cycles.__tiernan_circumference___ - [^tiernan_circumference()]]] + [^tiernan_circumference]]] [template tiernan_girth_and_circumference[] [link boost_graph.reference.algorithms.subgraph.tiernan_all_cycles.__tiernan_girth_and_circumference___ - [^tiernan_girth_and_circumference()]]] + [^tiernan_girth_and_circumference]]] [template bron_kerbosch_all_cliques[] [link boost_graph.reference.algorithms.subgraph.bron_kerbosch_all_cliques.__bron_kerbosch_all_cliques___ - [^bron_kerbosch_all_cliques()]]] + [^bron_kerbosch_all_cliques]]] [template bron_kerbosch_clique_number[] [link boost_graph.reference.algorithms.subgraph.bron_kerbosch_all_cliques.__bron_kerbosch_clique_number___ - [^bron_kerbosch_clique_number()]]] + [^bron_kerbosch_clique_number]]] [/ Measures /] [template degree_centrality[] [link boost_graph.reference.algorithms.measures.degree_centrality.__degree_centrality___ - [^degree_centrality()]]] + [^degree_centrality]]] [template all_degree_centralities[] [link boost_graph.reference.algorithms.measures.degree_centrality.__all_degree_centralities___ - [^all_degree_centralities()]]] + [^all_degree_centralities]]] [template closeness_centrality[] [link boost_graph.reference.algorithms.measures.closeness_centrality.__closeness_centrality___ - [^closeness_centrality()]]] + [^closeness_centrality]]] [template all_closeness_centralities[] [link boost_graph.reference.algorithms.measures.closeness_centrality.__all_closeness_centralities___ - [^all_closeness_centralities()]]] + [^all_closeness_centralities]]] [template mean_geodesic[] [link boost_graph.reference.algorithms.measures.mean_geodesic.__mean_geodesic___ - [^mean_geodesic()]]] + [^mean_geodesic]]] [template all_mean_geodesics[] [link boost_graph.reference.algorithms.measures.mean_geodesic.__all_mean_geodesics___ - [^all_mean_geodesics()]]] + [^all_mean_geodesics]]] [template small_world_distance[] [link boost_graph.reference.algorithms.measures.mean_geodesic.__small_world_distance___ - [^small_world_distance()]]] + [^small_world_distance]]] [template eccentricity[] [link boost_graph.reference.algorithms.measures.eccentricity.__eccentricity___ - [^eccentricity()]]] + [^eccentricity]]] [template eccentricities[] [link boost_graph.reference.algorithms.measures.eccentricity.__eccentricities___ - [^eccentricities()]]] + [^eccentricities]]] [template radius[] [link boost_graph.reference.algorithms.measures.eccentricity.__radius___ - [^radius()]]] + [^radius]]] [template diameter[] [link boost_graph.reference.algorithms.measures.eccentricity.__diameter___ - [^diameter()]]] + [^diameter]]] [template radius_and_diameter[] [link boost_graph.reference.algorithms.measures.eccentricity.__radius_and_diameter___ - [^radius_and_diameter()]]] + [^radius_and_diameter]]] [template clustering_coefficient[] [link boost_graph.reference.algorithms.measures.clustering_coefficient.__clustering_coefficient___ - [^clustering_coefficient()]]] + [^clustering_coefficient]]] [template all_clustering_coefficients[] [link boost_graph.reference.algorithms.measures.clustering_coefficient.__all_clustering_coefficients___ - [^all_clustering_coefficients()]]] + [^all_clustering_coefficients]]] [template num_paths_through_vertex[] [link boost_graph.reference.algorithms.measures.clustering_coefficient.__num_paths_through_vertex___ - [^num_paths_through_vertex()]]] + [^num_paths_through_vertex]]] [template num_triangles_on_vertex[] [link boost_graph.reference.algorithms.measures.clustering_coefficient.__num_triangles_on_vertex___ - [^num_triangles_on_vertex()]]] + [^num_triangles_on_vertex]]] +[/ Tours /] +[template metric_tsp_approxp[] [link + boost.graph.reference.algorithms.tours.metrc_tsp_approx.__metric_tsp_approx__ + [^metric_tsp_approx]]] + +[/ Misc /] [template exterior_vertex_property[] [link graph [^exterior_vertex_property]]] @@ -139,7 +155,7 @@ graph [^exterior_edge_property]]] -[/ Import lots of examples to build code templates] +[/ Import a number of examples to build code templates /] [import ../examples/degree_centrality.cpp] [import ../examples/influence_prestige.cpp] [import ../examples/closeness_centrality.cpp] diff --git a/quickbook/graph.qbk b/quickbook/graph.qbk index a5c4aa59..1f7680fa 100644 --- a/quickbook/graph.qbk +++ b/quickbook/graph.qbk @@ -23,7 +23,7 @@ ] [/ Templates /] -[template super[x]''''''[x]''''''] +[template sup[x]''''''[x]''''''] [template sub[x]''''''[x]''''''] [template delta[]'''δ'''] [/ d Greek small letter delta] diff --git a/quickbook/history.qbk b/quickbook/history.qbk index 28321ad5..deca466a 100644 --- a/quickbook/history.qbk +++ b/quickbook/history.qbk @@ -10,7 +10,7 @@ The Boost Graph Library began its life as the Generic Graph Component Library (GGCL), a software project at the Lab for Scientific Computing (LSC) at the University of Notre Dame, under the direction of Professor Andrew Lumsdaine. The Lab's research directions include numerical linear -algebra, parallel computing, and software engineering (including generic programming). +algebra, parallel computing, and software engineering (including generic programming). Soon after the Standard Template Library was released, work began at the LSC to apply generic programming to scientific computing. The Matrix Template Library (Jeremy Siek's masters thesis) @@ -23,11 +23,11 @@ were written using the generic programming style of the STL, and hence did not f and high-performance requirements of the LSC. Others were also expressing interest in a generic C++ graph library. During a meeting with Bjarne Stroustrup we were introduced to several people at AT&T who needed such a library. There had also been earlier work in the area of generic graph algorithms, -including some codes written by Alexander Stepanov, and Dietmar Kuhl's masters thesis. +including some codes written by Alexander Stepanov, and Dietmar Kuhl's masters thesis. With this in mind, and motivated by homework assignments in his algorithms class, Jeremy began prototyping an interface and some graph classes in the spring on 1998. Lie-Quan Lee then developed -the first version of GGCL, which became his masters thesis project. +the first version of GGCL, which became his masters thesis project. The following year, Jeremy went to work for SGI with Alexander Stepanov and Matt Austern. During this time Alex's disjoint-sets based connected components algorithm was added to GGCL, and Jeremy @@ -37,15 +37,25 @@ While working at SGI, Jeremy heard about Boost and was excited to find a group o in creating high-quality C++ libraries. At Boost there were several people interested in generic graph algorithms, most notably Dietmar Kuhl. Some discussions about generic interfaces for graph structures resulted in the a revision of GGCL which closely resembles the current Boost Graph Library -interface. +interface. On September 4, 2000 GGCL passed the Boost formal review and became the Boost Graph Library (BGL). The first release of BGL was September 27, 2000. [h2 Changes by Revision] +* Version 1.38.0 + * New algorithms + * Travelling Salesman Problem approximation by Matyas Egyhazy ([metric_tsp_approx]). + * Support for named vertices in `adjacency_list`. + * Bug Fixes + * Fixed spelling of `edmonds_karp` algorithm name. + * Correctly remove loop edges from undirected [adjacency_list]. + * Correctly handle infinite edge weights in [floyd_warshall_all_pairs_shortest_paths]. + * Edge counts are no longer modified if [remove_edge] fails. + * Version 1.35.0 - * New algorithms and components + * New algorithms and components * kolmogorov_max_flow, from Stephan Diederich as part of the 2006 Google Summer of Code. * read_dimacs_max_flow and write_dimacs_max_flow for max-flow problems, from Stephan Diederich. * read_graphml and write_graphml for GraphML input/output, from Tiago de Paula Peixoto. @@ -53,7 +63,7 @@ The first release of BGL was September 27, 2000. * LEDA Adaptor improvements, from Jens Muller. * Version 1.34.0 - * New algorithms and components + * New algorithms and components * edmonds_maximum_cardinality_matching, from Aaron Windsor. * lengauer_tarjan_dominator_tree, from JongSoo Park. * compressed_sparse_row_graph, from Jeremiah Willcock and Douglas Gregor of Indiana University. @@ -69,15 +79,15 @@ The first release of BGL was September 27, 2000. * Bundled properties now work with adjacency list I/O. * floyd_warshall_all_pairs_shortest_paths now properly uses its compare, inf, and zero parameters. * johnson_all_pairs_shortest_paths now supports compare, combine, inf, and zero. - * Fixed a bug in smallest_last_vertex_ordering.hpp which could cause a vertex to be moved to the wrong bucket during an BucketSorter update. + * Fixed a bug in smallest_last_vertex_ordering.hpp which could cause a vertex to be moved to the wrong bucket during an BucketSorter update. * Version 1.33.1 - * Bug Fixes + * Bug Fixes * fruchterman_reingold_force_directed_layout: Fixed enumeration of grid-force pairs, which caused some odd graph formations along grid lines. * king_ordering and cuthill_mckee_ordering: Fixed bug that caused failures with the multi-component version of these algorithms. * Version 1.33.0 - * New algorithms and components + * New algorithms and components * Experimental Python bindings, from Doug Gregor and Indiana University. * floyd_warshall_all_pairs_shortest_paths, from Lauren Foutz and Scott Hill. * astar_search, from Kristopher Beevers and Jufeng Peng. diff --git a/quickbook/introduction.qbk b/quickbook/introduction.qbk index 356ae253..df881bdc 100644 --- a/quickbook/introduction.qbk +++ b/quickbook/introduction.qbk @@ -1,129 +1,148 @@ [/ - / Copyright (c) 2007 Andrew Sutton + / Copyright (c) 2007-2009 Andrew Sutton / / 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) /] [section Introduction] +Graphs are mathematical abstractions that are useful for solving many types of +problems in computer science. Consequently, these abstractions must also be +represented in computer programs. A standardized generic interface for +traversing graphs is of utmost importance to encourage reuse of graph algorithms +and data structures. Part of the Boost Graph Library is a generic interface that +allows access to a graph's structure, but hides the details of the implementation. +This is an "open" interface in the sense that any graph library that implements +this interface will be interoperable with the BGL generic algorithms and with +other algorithms that also use this interface. The BGL provides some general +purpose graph classes that conform to this interface, but they are not meant to +be the /only/ graph classes; there certainly will be other graph classes that +are better for certain situations. We believe that the main contribution of the +The BGL is the formulation of this interface. -Graphs are mathematical abstractions that are useful for solving many types of problems in -computer science. Consequently, these abstractions must also be represented in computer -programs. A standardized generic interface for traversing graphs is of utmost importance to -encourage reuse of graph algorithms and data structures. Part of the Boost Graph Library is -a generic interface that allows access to a graph's structure, but hides the details of the -implementation. This is an "open" interface in the sense that any graph library that implements -this interface will be interoperable with the BGL generic algorithms and with other algorithms -that also use this interface. The BGL provides some general purpose graph classes that conform -to this interface, but they are not meant to be the ``only'' graph classes; there certainly will -be other graph classes that are better for certain situations. We believe that the main -contribution of the The BGL is the formulation of this interface. +The BGL graph interface and graph components are generic, in the same sense as +the the Standard Template Library (STL). In the following sections, we review +the role that generic programming plays in the STL and compare that to how we +applied generic programming in the context of graphs. -The BGL graph interface and graph components are generic, in the same sense as the the Standard -Template Library (STL). In the following sections, we review the role that generic programming -plays in the STL and compare that to how we applied generic programming in the context of graphs. +Of course, if you are already are familiar with generic programming, please dive +right in! Here's the Table of Contents. -Of course, if you are already are familiar with generic programming, please dive right in! Here's -the Table of Contents. - -The source for the BGL is available as part of the Boost distribution, which you can download -from here. +The source for the BGL is available as part of the Boost distribution, which you +can download from here. [h2 How to Build Boost.Graph] -[*DON'T!] The Boost Graph Library is a header-only library and does not need to be built to be used. -The only exception is the GraphViz input parser. +[*DON'T!] The Boost Graph Library is a header-only library and does not need to +be built to be used. The only exception is the GraphViz input parser. -When compiling programs that use the BGL, be sure to compile with optimization. For instance, -select "Release" mode with Microsoft Visual C++ or supply the flag -O2 or -O3 to GCC. +When compiling programs that use the BGL, be sure to compile with optimization. +For instance, select "Release" mode with Microsoft Visual C++ or supply the flag +`-O2` or `-O3` to GCC. Compiling in "Debug" mode can sometimes result in +algorithms that execute slower by an order magnitude! [h2 Genericity in the STL] There are three ways in which the STL is generic. [h3 Algorithm/Data Structure Interoperability in the STL] -First, each algorithm is written in a data-structure neutral way, allowing a single template -function to operate on many different classes of containers. The concept of an iterator is the -key ingredient in this decoupling of algorithms and data-structures. The impact of this technique -is a reduction in the STL's code size from O(M*N) to O(M+N), where M is the number of algorithms -and N is the number of containers. Considering a situation of 20 algorithms and 5 data-structures, -this would be the difference between writing 100 functions versus only 25 functions! And the -differences continues to grow faster and faster as the number of algorithms and data-structures -increase. +First, each algorithm is written in a data-structure neutral way, allowing a +single template function to operate on many different classes of containers. The +concept of an iterator is the key ingredient in this decoupling of algorithms +and data-structures. The impact of this technique is a reduction in the STL's +code size from O(M*N) to O(M+N), where M is the number of algorithms and N is +the number of containers. Considering a situation of 20 algorithms and 5 +data-structures, this would be the difference between writing 100 functions +versus only 25 functions! And the differences continues to grow faster and +faster as the number of algorithms and data-structures increase. [h3 Extension Through Function Objects] -The second way that STL is generic is that its algorithms and containers are extensible. The user -can adapt and customize the STL through the use of function objects. This flexibility is what makes -STL such a great tool for solving real-world problems. Each programming problem brings its own set -of entities and interactions that must be modeled. Function objects provide a mechanism for extending -the STL to handle the specifics of each problem domain +The second way that STL is generic is that its algorithms and containers are +extensible. The user can adapt and customize the STL through the use of function +objects. This flexibility is what makes STL such a great tool for solving +real-world problems. Each programming problem brings its own set of entities and +interactions that must be modeled. Function objects provide a mechanism for +extending the STL to handle the specifics of each problem domain [h3 Element Type Parameterization] -The third way that STL is generic is that its containers are parameterized on the element type. Though -hugely important, this is perhaps the least "interesting" way in which STL is generic. Generic -programming is often summarized by a brief description of parameterized lists such as `std::list`. -This hardly scratches the surface! +The third way that STL is generic is that its containers are parameterized on +the element type. Though hugely important, this is perhaps the least "interesting" +way in which STL is generic. Generic programming is often summarized by a brief +description of parameterized lists such as `std::list`. This hardly scratches +the surface! [h2 Genericity in Boost.Graph] Like the STL, there are three ways in which the BGL is generic. [h3 Algorithm/Data Structure Interoperability in Boost.Graph] -First, the graph algorithms of the BGL are written to an interface that abstracts away the details -of the particular graph data-structure. Like the STL, the BGL uses iterators to define the interface -for data-structure traversal. There are three distinct graph traversal patterns: traversal of all -vertices in the graph, through all of the edges, and along the adjacency structure of the graph -(from a vertex to each of its neighbors). There are separate iterators for each pattern of traversal. +First, the graph algorithms of the BGL are written to an interface that abstracts +away the details of the particular graph data-structure. Like the STL, the BGL +uses iterators to define the interface for data-structure traversal. There are +three distinct graph traversal patterns: traversal of all vertices in the graph, +through all of the edges, and along the adjacency structure of the graph (from a +vertex to each of its neighbors). There are separate iterators for each pattern +of traversal. -This generic interface allows template functions such as breadth_first_search() to work on a large -variety of graph data-structures, from graphs implemented with pointer-linked nodes to graphs -encoded in arrays. This flexibility is especially important in the domain of graphs. Graph data -structures are often custom-made for a particular application. Traditionally, if programmers want -to reuse an algorithm implementation they must convert/copy their graph data into the graph library's -prescribed graph structure. This is the case with libraries such as LEDA, GTL, Stanford GraphBase; -it is especially true of graph algorithms written in Fortran. This severely limits the reuse of their -graph algorithms. +This generic interface allows template functions such as breadth_first_search() +to work on a large variety of graph data-structures, from graphs implemented +with pointer-linked nodes to graphs encoded in arrays. This flexibility is +especially important in the domain of graphs. Graph data structures are often +custom-made for a particular application. Traditionally, if programmers want to +reuse an algorithm implementation they must convert/copy their graph data into +the graph library's prescribed graph structure. This is the case with libraries +such as LEDA, GTL, Stanford GraphBase; it is especially true of graph algorithms +written in Fortran. This severely limits the reuse of their graph algorithms. -In contrast, custom-made (or even legacy) graph structures can be used as-is with the generic graph -algorithms of the BGL, using external adaptation (see Section How to Convert Existing Graphs to the -BGL). External adaptation wraps a new interface around a data-structure without copying and without -placing the data inside adaptor objects. The BGL interface was carefully designed to make this -adaptation easy. To demonstrate this, we have built interfacing code for using a variety of graph -dstructures (LEDA graphs, Stanford GraphBase graphs, and even Fortran-style arrays) in BGL graph -algorithms. +In contrast, custom-made (or even legacy) graph structures can be used as-is +with the generic graph algorithms of the BGL, using external adaptation (see +Section How to Convert Existing Graphs to the BGL). External adaptation wraps a +new interface around a data-structure without copying and without placing the +data inside adaptor objects. The BGL interface was carefully designed to make +this adaptation easy. To demonstrate this, we have built interfacing code for +using a variety of graph dstructures (LEDA graphs, Stanford GraphBase graphs, +and even Fortran-style arrays) in BGL graph algorithms. [h3 Extension through Visitors] -Second, the graph algorithms of the BGL are extensible. The BGL introduces the notion of a visitor, -which is just a function object with multiple methods. In graph algorithms, there are often several -key /event points/ at which it is useful to insert user-defined operations. The visitor object has -a different method that is invoked at each event point. The particular event points and corresponding -visitor methods depend on the particular algorithm. They often include methods like `start_vertex()`, -`discover_vertex()`, `examine_edge()`, `tree_edge()`, and `finish_vertex()`. +Second, the graph algorithms of the BGL are extensible. The BGL introduces the +notion of a visitor, which is just a function object with multiple methods. In +graph algorithms, there are often several key /event points/ at which it is +useful to insert user-defined operations. The visitor object has a different +method that is invoked at each event point. The particular event points and +corresponding visitor methods depend on the particular algorithm. They often +include methods like `start_vertex`, `discover_vertex`, `examine_edge`, +`tree_edge`, and `finish_vertex`. [h3 Vertex and Edge Property Multi-Parameterization] -The third way that the BGL is generic is analogous to the parameterization of the element-type -in STL containers, though again the story is a bit more complicated for graphs. We need to -associate values (called "properties") with both the vertices and the edges of the graph. In -addition, it will often be necessary to associate multiple properties with each vertex and edge; -this is what we mean by multi-parameterization. The STL `std::list` class has a parameter `T` -for its element type. Similarly, BGL graph classes have template parameters for vertex and edge -"properties". A property specifies the parameterized type of the property and also assigns an -identifying tag to the property. This tag is used to distinguish between the multiple properties -which an edge or vertex may have. A property value that is attached to a particular vertex or edge -can be obtained via a property map. There is a separate property map for each property. +The third way that the BGL is generic is analogous to the parameterization of +the element-type in STL containers, though again the story is a bit more +complicated for graphs. We need to associate values (called "properties") with +both the vertices and the edges of the graph. In addition, it will often be +necessary to associate multiple properties with each vertex and edge; this is +what we mean by multi-parameterization. The STL `std::list` class has a +parameter `T` for its element type. Similarly, BGL graph classes have template +parameters for vertex and edge "properties". A property specifies the +parameterized type of the property and also assigns an identifying tag to the +property. This tag is used to distinguish between the multiple properties which +an edge or vertex may have. A property value that is attached to a particular +vertex or edge can be obtained via a property map. There is a separate property +map for each property. -Traditional graph libraries and graph structures fall down when it comes to the parameterization -of graph properties. This is one of the primary reasons that graph data-structures must be -custom-built for applications. The parameterization of properties in the BGL graph classes makes -them well suited for re-use. +Traditional graph libraries and graph structures frequently fall down when it +comes to the parameterization of graph properties. This is one of the primary +reasons that graph data-structures must be custom-built for applications. The +parameterization of properties in the BGL graph classes makes them well suited +for reuse. [h2 Algorithms] -Boost.Graph algorithms consist of a core set of algorithm patterns (implemented as generic algorithms) -and a larger set of graph algorithms. The core algorithm patterns are: -* Breadth First Search -* Depth First Search +Boost.Graph algorithms consist of a core set of algorithm patterns (implemented +as generic algorithms) and a larger set of graph algorithms. The core algorithm +patterns are: + +* Breadth First Search +* Depth First Search * Uniform Cost Search -By themselves, the algorithm patterns do not compute any meaningful quantities over graphs; they are -merely building blocks for constructing graph algorithms. The graph algorithms in the BGL currently -include: +By themselves, the algorithm patterns do not compute any meaningful quantities +over graphs; they are merely building blocks for constructing graph algorithms. +The graph algorithms in the BGL currently include: * Dijkstra's Shortest Paths * Bellman-Ford Shortest Paths @@ -146,21 +165,23 @@ Boost.Graph currently provides two graph classes and an edge list adaptor: * adjacency_matrix * edge_list -The adjacency_list class is the general purpose "swiss army knife" of graph classes. It is highly -parameterized so that it can be optimized for different situations: the graph is directed or -undirected, allow or disallow parallel edges, efficient access to just the out-edges or also to -the in-edges, fast vertex insertion and removal at the cost of extra space overhead, etc. +The adjacency_list class is the general purpose "swiss army knife" of graph +classes. It is highly parameterized so that it can be optimized for different +situations: the graph is directed or undirected, allow or disallow parallel +edges, efficient access to just the out-edges or also to the in-edges, fast +vertex insertion and removal at the cost of extra space overhead, etc. -The adjacency_matrix class stores edges in a |V| x |V| matrix (where |V| is the number of vertices). -The elements of this matrix represent edges in the graph. Adjacency matrix representations are -especially suitable for very dense graphs, i.e., those where the number of edges approaches |V|2. +The adjacency_matrix class stores edges in a |V| x |V| matrix (where |V| is the +number of vertices). The elements of this matrix represent edges in the graph. +Adjacency matrix representations are especially suitable for very dense +graphs, i.e., those where the number of edges approaches |V|[sup 2]. -The `edge_list` class is an adaptor that takes any kind of edge iterator and implements an -Edge List Graph. +The `edge_list` class is an adaptor that takes any kind of edge iterator and +implements an Edge List Graph. [h2 Projects Using This Library] -This section should probably be merged into the global "Who's using me now page". But, for completeness -here's the list (with links, too): +Here is an abbreviated list of projects that use the BGL or are based on the +graph concepts in the BGL. * [@http://www.cs.rpi.edu/~musser/gsd/ Generic Software Design Course at RPI] * [@http://alps.comp-phys.org/ The ALPS quantum mechanics project] @@ -177,6 +198,8 @@ here's the list (with links, too): * [@http://hyperworx.org Hyperworx Platform Project] [h2 Publications about this Library] +Here is a short list of publications about the BGL. + * Dr. Dobb's Sept. 2000 Article * OOPSLA'99 GGCL Paper * Lie-Quan Lee's Master's Thesis about GGCL(ps) (pdf) @@ -185,30 +208,35 @@ here's the list (with links, too): * C++ Template Workshop 2000, Concept Checking [h2 Acknowledgements] -We owe many debts of thanks to a number of individuals who both inspired and encouraged us in -developing the Boost Graph Library. +We owe many debts of thanks to a number of individuals who both inspired and +encouraged us in developing the Boost Graph Library. -A most profound thanks goes to Alexander Stepanov for his pioneering work in generic programming, -for his encouragement, and for his algorithm contributions to the BGL. We thank Matthew Austern for -his work on documenting the concepts of STL which provided a foundation for creating the concepts in -the BGL. We thank Dietmar Kuhl for his work on generic graph algorithms and design patterns; +A most profound thanks goes to Alexander Stepanov for his pioneering work in +generic programming, for his encouragement, and for his algorithm contributions +to the BGL. We thank Matthew Austern for his work on documenting the concepts +of STL which provided a foundation for creating the concepts in the BGL. We +thank Dietmar Kuhl for his work on generic graph algorithms and design patterns; especially for the property map abstraction. -Dave Abrahams, Jens Maurer, Beman Dawes, Gary Powell, Greg Colvin, Valentin Bonnard, and the rest -of the group at Boost provided valuable input to the BGL interface, numerous suggestions for improvement, -proof reads of the documentation, and help with polishing the code. A special thanks to Dave Abrahams -for managing the formal review. +Dave Abrahams, Jens Maurer, Beman Dawes, Gary Powell, Greg Colvin, Valentin +Bonnard, and the rest of the group at Boost provided valuable input to the BGL +interface, numerous suggestions for improvement, proof reads of the +documentation, and help with polishing the code. A special thanks to Dave +Abrahams for managing the formal review. -We also thank the following BGL users whose questions helped to improve the BGL: Gordon Woodhull, -Dave Longhorn, Joel Phillips, and Edward Luke. +We also thank the following BGL users whose questions helped to improve the +BGL: Gordon Woodhull, Dave Longhorn, Joel Phillips, and Edward Luke. -A special thanks to Jeffrey Squyres for editing and proof reading of the documentation. +A special thanks to Jeffrey Squyres for editing and proof reading of the +documentation. -Our original work on the Boost Graph Library was supported in part by NSF grant ACI-9982205 and by -the Director, Office of Science, Division of Mathematical, Information, and Computational Sciences of -the U.S. Department of Energy under contract number DE-AC03-76SF00098. +Our original work on the Boost Graph Library was supported in part by NSF grant +ACI-9982205 and by the Director, Office of Science, Division of Mathematical, +Information, and Computational Sciences of the U.S. Department of Energy under +contract number DE-AC03-76SF00098. -In our work we also used resources of the National Energy Research Scientific Computing Center, which -is supported by the Office of Science of the U.S. Department of Energy. +In our work we also used resources of the National Energy Research Scientific +Computing Center, which is supported by the Office of Science of the U.S. +Department of Energy. [endsect] \ No newline at end of file diff --git a/quickbook/reference/betweenness_centrality.qbk b/quickbook/reference/betweenness_centrality.qbk index 697cef22..3c65610a 100644 --- a/quickbook/reference/betweenness_centrality.qbk +++ b/quickbook/reference/betweenness_centrality.qbk @@ -141,9 +141,9 @@ The `vertex_closeness_centrality()` function returns the closeness of a vertex. If the source vertex is disconnected from any vertices in the graph, this value is 0. [heading Complexity] -The `closenesss_centrality()` function returns in ['O(n[super 2]*O(M))] where /n/ +The `closenesss_centrality()` function returns in ['O(n[sup 2]*O(M))] where /n/ is the number of vertices in the graph and /M/ is the complexity of the given distance -measure. This is ['O(n[super 2])] by default +measure. This is ['O(n[sup 2])] by default The `vertex_closeness_centrality()` function returns in ['O(n*O(M))]. This is linear by default. diff --git a/quickbook/reference/bron_kerbosch_all_cliques.qbk b/quickbook/reference/bron_kerbosch_all_cliques.qbk index 9048de9f..785954b9 100644 --- a/quickbook/reference/bron_kerbosch_all_cliques.qbk +++ b/quickbook/reference/bron_kerbosch_all_cliques.qbk @@ -97,10 +97,10 @@ on a directed graph will double the performance penalty (which is generally negl ] [heading Complexity] -This problem has a loose upper bound of ['O(2[super n])] if one considers all possible +This problem has a loose upper bound of ['O(2[sup n])] if one considers all possible combinations of subsets of vertices as cliques (i.e., the powerset of vertices). The original publication, however, approximates the runtime of the algorithm as -being proportional to ['O(3.14[super n])]. +being proportional to ['O(3.14[sup n])]. Graphs that do not meet the constant-time requirements of the [AdjacencyMatrix] concept will incur additional runtime costs during execution (usually by a linear diff --git a/quickbook/reference/closeness_centrality.qbk b/quickbook/reference/closeness_centrality.qbk index 3943a931..b81d360a 100644 --- a/quickbook/reference/closeness_centrality.qbk +++ b/quickbook/reference/closeness_centrality.qbk @@ -228,9 +228,9 @@ or as the result of a [breadth_first_search] (if the graph is unweighted). ] [heading Complexity] -The `all_closenesss_centralities()` function returns in ['O(n[super 2]*O(M))] where /n/ +The `all_closenesss_centralities()` function returns in ['O(n[sup 2]*O(M))] where /n/ is the number of vertices in the graph and /O(M)/ is the complexity of the distance -measure. If no distance measure is given, this functions returns in ['O(n[super 2])] +measure. If no distance measure is given, this functions returns in ['O(n[sup 2])] time. [endsect] diff --git a/quickbook/reference/clustering_coefficient.qbk b/quickbook/reference/clustering_coefficient.qbk index 5d5c9623..a892b254 100644 --- a/quickbook/reference/clustering_coefficient.qbk +++ b/quickbook/reference/clustering_coefficient.qbk @@ -117,7 +117,7 @@ The `clustering_coefficient()` function returns the clustering coefficient of th vertex. The return type is either `float` or the type specified by the user. [heading Complexity] -The `clustering_coefficient()` function returns in ['O(d(v)[super 2]] where +The `clustering_coefficient()` function returns in ['O(d(v)[sup 2]] where /d(v)/ is the degree of /v/. [endsect] @@ -159,7 +159,7 @@ coefficient to the caller. ] [heading Complexity] -The `all_clustering_coefficients()` function returns in ['O(nd[super 2])] where +The `all_clustering_coefficients()` function returns in ['O(nd[sup 2])] where /d/ is the mean (average) degree of vertices in the graph. [endsect] diff --git a/quickbook/reference/eccentricity.qbk b/quickbook/reference/eccentricity.qbk index e2764982..fe21706b 100644 --- a/quickbook/reference/eccentricity.qbk +++ b/quickbook/reference/eccentricity.qbk @@ -145,7 +145,7 @@ The `eccentricities()` function returns a pair containing the radius and diamete as the `first` and `second` elements respectively. [heading Complexity] -The `eccentricities()` function returns in ['O(n[super 2])] where /n/ is the number +The `eccentricities()` function returns in ['O(n[sup 2])] where /n/ is the number of vertices in the graph. [endsect] diff --git a/quickbook/reference/mean_geodesic.qbk b/quickbook/reference/mean_geodesic.qbk index 6a7ded54..ca0b5c83 100644 --- a/quickbook/reference/mean_geodesic.qbk +++ b/quickbook/reference/mean_geodesic.qbk @@ -223,7 +223,7 @@ If any vertices have infinite mean geodesic distance, then the small-world dista will also be infinite. [heading Complexity] -The `all_mean_geodesics()` function returns in ['O(n[super 2]*O(M))] where /n/ is the +The `all_mean_geodesics()` function returns in ['O(n[sup 2]*O(M))] where /n/ is the number of vertices in the graph, and /O(M)/ is the complexity of the given measure. If no measure is given, this function returns in quadratic time. [endsect] diff --git a/quickbook/reference/tiernan_all_cycles.qbk b/quickbook/reference/tiernan_all_cycles.qbk index 2d4a8963..f83c04d7 100644 --- a/quickbook/reference/tiernan_all_cycles.qbk +++ b/quickbook/reference/tiernan_all_cycles.qbk @@ -134,7 +134,7 @@ in an undirected graph as a cycle. ] [heading Complexity] -This function has a (loose) upper bound of ['O(2[super n])] where /n/ is the +This function has a (loose) upper bound of ['O(2[sup n])] where /n/ is the number of vertices a graph. This bound is derived from the powerset of vertices in /g/ and does not account for the vertex of origin or directionality of edges connecting vertices in a path. If one considers the paths in a triangle {1, 2, 3} @@ -142,7 +142,7 @@ and {3, 2, 1} to be distinct cycles within a graph, then this bound can potentia be much greater. From a practical standpoint, it is unlikely that real graphs will ever approach a number of paths remotely close to this number. -This function requires ['O(n[super 2])] space where /n/ is the number of vertices +This function requires ['O(n[sup 2])] space where /n/ is the number of vertices in a graph. [endsect] diff --git a/quickbook/tour.qbk b/quickbook/tour.qbk index 0a823ea7..60302021 100644 --- a/quickbook/tour.qbk +++ b/quickbook/tour.qbk @@ -6,43 +6,55 @@ /] [section A Quick tour of Boost.Graph] -The domain of graph data structures and algorithms is in some respects more complicated than -that of containers. The abstract iterator interface used by STL is not sufficiently rich to -encompass the numerous ways that graph algorithms may traverse a graph. Instead, we formulate an -abstract interface that serves the same purpose for graphs that iterators do for basic containers -(though iterators still play a large role). Figure 1 depicts the analogy between the STL and +The domain of graph data structures and algorithms is in some respects more +complicated than that of containers. The abstract iterator interface used by +STL is not sufficiently rich to encompass the numerous ways that graph +algorithms may traverse a graph. Instead, we formulate an abstract interface +that serves the same purpose for graphs that iterators do for basic containers +(though iterators still play a large role). Figure 1 depicts the analogy between +the STL and Boost.Graph. [$../images/tour_analogy.gif] -The graph abstraction consists of a set of vertices (or nodes), and a set of edges (or arcs) that -connect the vertices. Figure 2 depicts a directed graph with five vertices (labeled 0 through 4) -and 11 edges. The edges leaving a vertex are called the out-edges of the vertex. The edges -{(0,1),(0,2),(0,3),(0,4)} are all out-edges of vertex 0. The edges entering a vertex are called -the in-edges of the vertex. The edges {(0,4),(2,4),(3,4)} are all in-edges of vertex 4. +The graph abstraction consists of a set of vertices (or nodes), and a set of +edges (or arcs) that connect the vertices. Figure 2 depicts a directed graph +with five vertices (labeled 0 through 4) and 11 edges. The edges leaving a +vertex are called the out-edges of the vertex. The edges {(0,1),(0,2),(0,3),(0,4)} +are all out-edges of vertex 0. The edges entering a vertex are called the in-edges +of the vertex. The edges {(0,4),(2,4),(3,4)} are all in-edges of vertex 4. [$../images/tour_graph.png] -In the following sections we will use Boost.Graph to construct this example graph and manipulate it in -various ways. The complete source code for this example can be found in examples/quick_tour.cpp. Each -of the following sections discusses a "slice" of this example file. Excerpts from the output of the -example program will also be listed. +In the following sections we will use Boost.Graph to construct this example +graph and manipulate it in various ways. The complete source code for this +example can be found in `examples/quick_tour.cpp`. Each of the following +sections discusses a "slice" of this example file. Excerpts from the output of +the example program will also be listed. [h2 Constructing the Graph] -In this example we will use the `adjacency_list<>` class to demonstrate the main ideas in the -Boost.Graph interface. The `adjacency_list<>` class provides a generalized version of the classic -"adjacency list" data structure. The `adjacency_list<>` is a template class with six template parameters, -though here we only fill in the first three parameters and use the defaults for the remainder. -The first two template arguments (`vecS`, `vecS`) determine the data structure used to represent the -out-edges for each vertex in the graph and the data structure used to represent the graph's vertex set -(see section Choosing the Edgelist and VertexList for information about the tradeoffs of the different -data structures). The third argument, `bidirectionalS`, selects a directed graph that provides access to -both out and in-edges. The other options for the third argument are `directedS` which selects a directed -graph with only out-edges, and `undirectedS` which selects an undirected graph. -Once we have the graph type selected, we can create the graph in Figure 2 by declaring a graph object -and filling in edges using the add_edge() function of the MutableGraph interface (which `adjacency_list<>` -implements). We use the array of pairs edge_array merely as a convenient way to explicitly create the +In this example + +[h2 Constructing the Graph] +In this example we will use the [adjacency_list] class to demonstrate the main +ideas in the Boost.Graph interface. The [adjacency_list] class provides a +generalized version of the classic /adjacency list/ data structure. The +[adjacency_list] class is a template class with six template parameters, though +here we only fill in the first three parameters and use the defaults for the +remainder. The first two template arguments (`vecS`, `vecS`) determine the data +structure used to represent the out-edges for each vertex in the graph and the +data structure used to represent the graph's vertex set (see section Choosing +the Edgelist and VertexList for information about the tradeoffs of the different +data structures). The third argument, `bidirectionalS`, selects a directed graph +that provides access to both out and in-edges. The other options for the third +argument are `directedS` which selects a directed graph with only out-edges, and +`undirectedS` which selects an undirected graph. + +Once we have the graph type selected, we can create the graph in Figure 2 by +declaring a graph object and filling in edges using the add_edge() function of +the MutableGraph interface (which `adjacency_list<>` implements). We use the +array of pairs edge_array merely as a convenient way to explicitly create the edges for this example. #include // for std::cout @@ -83,16 +95,17 @@ edges for this example. return 0; } -Instead of calling the `add_edge()` function for each edge, we could use the edge iterator constructor -of the graph. This is typically more efficient than using `add_edge()`. Pointers to the `edge_array` can -be viewed as iterators, so we can call the iterator constructor by passing pointers to the beginning -and end of the array. +Instead of calling the `add_edge()` function for each edge, we could use the +edge iterator constructor of the graph. This is typically more efficient than +using `add_edge()`. Pointers to the `edge_array` can be viewed as iterators, so +we can call the iterator constructor by passing pointers to the beginning and +end of the array. Graph g(edges, edges + sizeof(edge_array) / sizeof(edge_array[0]), num_vertices); -Instead of creating a graph with a certain number of vertices to begin with, it is also possible to -add and remove vertices with the `add_vertex()` and `remove_vertex()` functions, also of the /MutableGraph/ -interface. +Instead of creating a graph with a certain number of vertices to begin with, it +is also possible to add and remove vertices with the [add_vertex] and +[remove_vertex] functions, also of the [MutableGraph] interface. [h2 Accessing the Vertex Set] Now that we have created a graph, we can use the graph interface to access the graph data in @@ -108,7 +121,7 @@ The following example prints out the index for each of the vertices in the graph edge properties, including index, are accessed via property map objects. The `property_map<>` class is used to obtain the property map type for a specific property (specified by `vertex_index_t`, one of the Boost.Graph predefined properties) and function call `get(vertex_index, g)` returns the actual -property map object. +property map object. // ... @@ -132,7 +145,7 @@ property map object. return 0; } -The output is: +The output is: [pre vertices(g) = 0 1 2 3 4 @@ -147,7 +160,7 @@ functions return the two vertices that are connected by the edge. Instead of exp 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 choice for Boost.Graph. - + // ... int main(int,char*[]) { @@ -173,8 +186,8 @@ In the next few examples we will explore the adjacency structure of the graph fr view of a particular vertex. We will look at the vertices' in-edges, out-edges, and its adjacent vertices. We will encapsulate this in an "exercise vertex" function, and apply it to each vertex in the graph. To demonstrate the STL-interoperability of Boost.Graph, we will use the STL `for_each()` -function to iterate through the vertices and apply the function. - +function to iterate through the vertices and apply the function. + //... int main(int,char*[]) { @@ -187,8 +200,8 @@ We use a functor for exercise_vertex instead of just a function because the grap needed when we access information about each vertex; using a functor gives us a place to keep a reference to the graph object during the execution of the `std::for_each()`. Also we template the functor on the graph type so that it is reusable with different graph classes. Here is the start -of the exercise_vertex functor: - +of the exercise_vertex functor: + template struct exercise_vertex { exercise_vertex(Graph& g_) : g(g_) { } @@ -210,8 +223,8 @@ that can be used to access information about the graph via the `out_edges()`, `i vertex_descriptor type is obtained through the graph_traits class. The typename keyword used below is necessary because the type on the left hand side of the scope :: operator (the `graph_traits` type) is dependent on a template parameter (the `Graph` type). Here is how we define the functor's -apply method: - +apply method: + template struct exercise_vertex { // ... continued from above @@ -234,8 +247,9 @@ iterators). The iterators are called out-edge iterators and dereferencing one of gives an edge descriptor object. An edge descriptor plays the same kind of role as the vertex descriptor object, it is a "black box" provided by the graph type. The following code snippet prints the source-target pairs for each out-edge of vertex, v. - - template struct exercise_vertex { + + template + struct exercise_vertex { //... continued from above void operator()(const Vertex& v) const @@ -260,7 +274,7 @@ the source-target pairs for each out-edge of vertex, v. // ... }; -For vertex 0 the output is: +For vertex 0 the output is: [pre out-edges: (0,1) (0,2) (0,3) (0,4) ] @@ -268,8 +282,8 @@ For vertex 0 the output is: The `in_edges()` function of the BidirectionalGraph interface provides access to all the in-edges of a vertex through in-edge iterators. The in_edges() function is only available for the `adjacency_list<>` if `bidirectionalS` is supplied for the Directed template parameter. There is an -extra cost in space when `bidirectionalS` is specified instead of `directedS`. - +extra cost in space when `bidirectionalS` is specified instead of `directedS`. + template struct exercise_vertex { // ... continued from above @@ -291,7 +305,7 @@ extra cost in space when `bidirectionalS` is specified instead of `directedS`. // ... }; -For vertex 0 the output is: +For vertex 0 the output is: [pr in-edges: (2,0) (3,0) (4,0) ] @@ -302,8 +316,8 @@ vertex. Sometimes an algorithm does not need to look at the edges of the graph a about the vertices. Therefore the graph interface also includes the `adjacent_vertices()` function of the AdjacencyGraph interface which provides direct access to the adjacent vertices. This function returns a pair of adjacency iterators. Dereferencing an adjacency iterator gives a vertex descriptor -for an adjacent vertex. - +for an adjacent vertex. + template struct exercise_vertex { // ... continued from above @@ -322,7 +336,7 @@ for an adjacent vertex. //... }; -For vertex 4 the output is: +For vertex 4 the output is: [pre adjacent vertices: 0 1 ] @@ -337,7 +351,7 @@ the graph object. The first kind of property is called an internally stored prop kind is called an externally stored property. Boost.Graph uses a uniform mechanism to access both kinds of properties inside its graph algorithms called the property map interface, described in Section Property Map Concepts. In addition, the PropertyGraph concept defines the interface for obtaining -a property map object for an internally stored property. +a property map object for an internally stored property. The Boost.Graph adjacency_list class allows users to specify internally stored properties through plug-in template parameters of the graph class. How to do this is discussed in detail in Section Internal @@ -347,11 +361,11 @@ properties is to create an array indexed by vertex or edge index. In the adjacen specified for the VertexList template parameter, vertices are automatically assigned indices, which can be accessed via the property map for the vertex_index_t. Edges are not automatically assigned indices. However the property mechanism can be used to attach indices to the edges which can be -used to index into other externally stored properties. +used to index into other externally stored properties. In the following example, we construct a graph and apply `dijkstra_shortest_paths()`. The complete source code for the example is in examples/dijkstra-example.cpp. Dijkstra's algorithm computes the -shortest distance from the starting vertex to every other vertex in the graph. +shortest distance from the starting vertex to every other vertex in the graph. Dijkstra's algorithm requires that a weight property is associated with each edge and a distance property with each vertex. Here we use an internal property for the weight and an external property @@ -362,9 +376,9 @@ The listS and vecS types are selectors that determine the data structure used in `adjacency_list<>` (see Section Choosing the Edgelist and VertexList). The directedS type specifies that the graph should be directed (versus undirected). The following code shows the specification of the graph type and then the initialization of the graph. The edges and weights are passed to the -graph constructor in the form of iterators (a pointer qualifies as a /RandomAccessIterator/). +graph constructor in the form of iterators (a pointer qualifies as a /RandomAccessIterator/). - typedef adjacency_list // edges have integer edge weight > Graph; @@ -372,9 +386,9 @@ graph constructor in the form of iterators (a pointer qualifies as a /RandomAcce typedef std::pair E; const int num_nodes = 5; - E edges[] = { E(0,2), + E edges[] = { E(0,2), E(1,1), E(1,3), E(1,4), - E(2,1), E(2,3), + E(2,1), E(2,3), E(3,4), E(4,0), E(4,1) }; int weights[] = { 1, 2, 1, 2, 7, 3, 1, 1, 1}; @@ -385,8 +399,8 @@ For the external distance property we will use a std::vector for storage. Boost. random access iterators as property maps, so we can just pass the beginning iterator of the distance vector to Dijkstra's algorithm. Continuing the above example, the following code shows the creation of the distance vector, the call to Dijkstra's algorithm (implicitly using the -internal edge weight property), and then the output of the results. - +internal edge weight property), and then the output of the results. + // vector for storing distance property std::vector d(num_vertices(G)); @@ -399,11 +413,11 @@ internal edge weight property), and then the output of the results. std::cout << "distances from start vertex:" << ; graph_traits::vertex_iterator vi; for(vi = vertices(G).first; vi != vertices(G).second; ++vi) - std::cout << "distance(" << index(*vi) << ") = " + std::cout << "distance(" << index(*vi) << ") = " << d[*vi] << ; std::cout << ; -The output is: +The output is: [pre distances from start vertex: distance(0) = 0 @@ -417,7 +431,7 @@ The output is: Often times an algorithm in a library almost does what you need, but not quite. For example, in the previous section we used Dijkstra's algorithm to calculate the shortest distances to each vertex, but perhaps we also wanted to record the tree of shortest paths. One way to do this is -to record the predecessor (parent) for each node in the shortest-paths tree. +to record the predecessor (parent) for each node in the shortest-paths tree. It would be nice if we could avoid rewriting Dijkstra's algorithm, and just add that little bit extra needed to record the predecessors [1]. In the STL, this kind of extensibility is provided @@ -439,7 +453,7 @@ then only be responsible for what parent to record. To implement this, we create this visitor will only be filling in one of the visitor methods, we will inherit from `dijkstra_visitor` which will provide empty methods for the rest. The constructor of the `predecessor_recorder` will take the property map object and save it away in a data member. - + template class record_predecessors : public dijkstra_visitor<> { @@ -466,8 +480,8 @@ to invoke the `explore()` method. In this case we only want to be notified about shortest-paths tree so we specify `tree_edge_tag`. As a finishing touch, we create a helper function to make it more convenient to create predecessor -visitors. All Boost.Graph visitors have a helper function like this. - +visitors. All Boost.Graph visitors have a helper function like this. + template record_predecessors make_predecessor_recorder(PredecessorMap p) { @@ -477,25 +491,25 @@ visitors. All Boost.Graph visitors have a helper function like this. We are now ready to use the `record_predecessors` in Dijkstra's algorithm. Luckily, Boost.Graph's Dijkstra's algorithm is already equipped to handle visitors, so we just pass in our new visitor. In this example we only need to use one visitor, but Boost.Graph is also equipped to handle the use -of multiple visitors in the same algorithm (see Section Visitor Concepts). - +of multiple visitors in the same algorithm (see Section Visitor Concepts). + using std::vector; using std::cout; using std::endl; vector p(num_vertices(G)); //the predecessor array - dijkstra_shortest_paths(G, s, distance_map(&d[0]). + dijkstra_shortest_paths(G, s, distance_map(&d[0]). visitor(make_predecessor_recorder(&p[0]))); cout << "parents in the tree of shortest paths:" << endl; for(vi = vertices(G).first; vi != vertices(G).second; ++vi) { cout << "parent(" << *vi; if (p[*vi] == Vertex()) - cout << ") = no parent" << endl; - else + cout << ") = no parent" << endl; + else cout << ") = " << p[*vi] << endl; } -The output is: +The output is: [pre parents in the tree of shortest paths: parent(0) = no parent From 549db6db29bbd9e729a64598bf486a86bf6a624c Mon Sep 17 00:00:00 2001 From: Andrew Sutton Date: Mon, 20 Apr 2009 14:49:29 +0000 Subject: [PATCH 147/224] Importing null (no-op) property map from SOC/2007. [SVN r52510] --- .../graph/property_maps/null_property_map.hpp | 38 +++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 include/boost/graph/property_maps/null_property_map.hpp diff --git a/include/boost/graph/property_maps/null_property_map.hpp b/include/boost/graph/property_maps/null_property_map.hpp new file mode 100644 index 00000000..2d30eea8 --- /dev/null +++ b/include/boost/graph/property_maps/null_property_map.hpp @@ -0,0 +1,38 @@ +// (C) Copyright Andrew Sutton 2007 +// +// 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_NULL_PROPERTY_HPP +#define BOOST_GRAPH_NULL_PROPERTY_HPP + +#include + +namespace boost +{ + // A null property is somewhat like the inverse of the constant + // property map except that instead of returning a single value, + // this eats any writes and cannot be read from. + + template + struct null_property_map + { + typedef Key key_type; + typedef Value value_type; + typedef void reference; + typedef boost::writable_property_map_tag category; + }; + + // The null_property_map only has a put() function. + template + void put(null_property_map& pm, const K& key, const V& value) + { } + + // A helper function for intantiating null property maps. + template + inline null_property_map make_null_property() + { return null_property_map(); } +} + +#endif From ee18592d0f6e88361957bb2c29a1b3a5b5632ac5 Mon Sep 17 00:00:00 2001 From: Andrew Sutton Date: Mon, 20 Apr 2009 14:58:50 +0000 Subject: [PATCH 148/224] Reordering headers. [SVN r52512] --- include/boost/graph/dominator_tree.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/boost/graph/dominator_tree.hpp b/include/boost/graph/dominator_tree.hpp index 81fa4d1c..cf0d310e 100644 --- a/include/boost/graph/dominator_tree.hpp +++ b/include/boost/graph/dominator_tree.hpp @@ -9,9 +9,9 @@ #ifndef BOOST_GRAPH_DOMINATOR_HPP #define BOOST_GRAPH_DOMINATOR_HPP +#include #include #include -#include #include // Dominator tree computation From ce04079e628fa5739965edada36f5e6db5e49988 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Tue, 21 Apr 2009 20:15:59 +0000 Subject: [PATCH 149/224] Changed bogus HTML comment syntax [SVN r52530] --- doc/AStarHeuristic.html | 10 +++++----- doc/AStarVisitor.html | 10 +++++----- doc/AddEdgeVisitor.html | 12 ++++++------ doc/AdjacencyGraph.html | 10 +++++----- doc/AdjacencyMatrix.html | 10 +++++----- doc/BFSVisitor.html | 10 +++++----- doc/BasicMatrix.html | 10 +++++----- doc/BellmanFordVisitor.html | 10 +++++----- doc/BidirectionalGraph.html | 10 +++++----- doc/Buffer.html | 10 +++++----- doc/ColorValue.html | 10 +++++----- doc/DFSVisitor.html | 10 +++++----- doc/DijkstraVisitor.html | 10 +++++----- doc/EdgeListGraph.html | 10 +++++----- doc/EdgeMutableGraph.html | 10 +++++----- doc/EventVisitor.html | 10 +++++----- doc/EventVisitorList.html | 10 +++++----- doc/Graph.html | 10 +++++----- doc/IncidenceGraph.html | 10 +++++----- doc/IteratorConstructibleGraph.html | 10 +++++----- doc/Monoid.html | 10 +++++----- doc/MutableGraph.html | 10 +++++----- doc/MutablePropertyGraph.html | 10 +++++----- doc/PlanarEmbedding.html | 10 +++++----- doc/PlanarFaceVisitor.html | 10 +++++----- doc/PropertyGraph.html | 10 +++++----- doc/PropertyTag.html | 10 +++++----- doc/VertexAndEdgeListGraph.html | 10 +++++----- doc/VertexListGraph.html | 10 +++++----- doc/VertexMutableGraph.html | 10 +++++----- doc/acknowledgements.html | 10 +++++----- doc/adjacency_iterator.html | 10 +++++----- doc/adjacency_list.html | 10 +++++----- doc/adjacency_list_traits.html | 10 +++++----- doc/adjacency_matrix.html | 10 +++++----- doc/astar_heuristic.html | 10 +++++----- doc/astar_visitor.html | 10 +++++----- doc/bandwidth.html | 10 +++++----- doc/bc_clustering.html | 10 +++++----- doc/bellman_ford_shortest.html | 10 +++++----- doc/bellman_visitor.html | 10 +++++----- doc/betweenness_centrality.html | 10 +++++----- doc/bfs_visitor.html | 10 +++++----- doc/bgl_named_params.html | 10 +++++----- doc/bibliography.html | 10 +++++----- doc/biconnected_components.html | 18 +++++++++--------- doc/boyer_myrvold.html | 10 +++++----- doc/breadth_first_search.html | 10 +++++----- doc/breadth_first_visit.html | 10 +++++----- doc/bundles.html | 10 +++++----- doc/challenge.html | 10 +++++----- doc/circle_layout.html | 10 +++++----- doc/connected_components.html | 10 +++++----- doc/constructing_algorithms.html | 10 +++++----- doc/copy_graph.html | 10 +++++----- doc/cuthill_mckee_ordering.html | 9 +++++---- doc/dag_shortest_paths.html | 10 +++++----- doc/depth_first_search.html | 10 +++++----- doc/depth_first_visit.html | 10 +++++----- doc/dfs_visitor.html | 10 +++++----- doc/dijkstra_visitor.html | 10 +++++----- doc/distance_recorder.html | 10 +++++----- doc/edge_list.html | 10 +++++----- doc/edmonds_karp_max_flow.html | 10 +++++----- doc/erdos_renyi_generator.html | 18 +++++++++--------- doc/exception.html | 10 +++++----- doc/faq.html | 10 +++++----- doc/file_dependency_example.html | 10 +++++----- doc/filtered_graph.html | 10 +++++----- doc/fruchterman_reingold.html | 10 +++++----- doc/graph_coloring.html | 10 +++++----- doc/graph_concepts.html | 10 +++++----- doc/graph_theory_review.html | 10 +++++----- doc/graph_traits.html | 10 +++++----- doc/gursoy_atun_layout.html | 10 +++++----- doc/history.html | 10 +++++----- doc/howard_cycle_ratio.html | 14 +++++++------- doc/incident.html | 10 +++++----- doc/incremental_components.html | 10 +++++----- doc/index.html | 10 +++++----- doc/inv_adjacency_iterator.html | 10 +++++----- doc/is_kuratowski_subgraph.html | 12 ++++++------ doc/is_straight_line_drawing.html | 10 +++++----- doc/isomorphism.html | 10 +++++----- doc/kamada_kawai_spring_layout.html | 10 +++++----- doc/kevin_bacon.html | 10 +++++----- doc/king_ordering.html | 6 +++--- doc/known_problems.html | 10 +++++----- doc/kruskal_min_spanning_tree.html | 10 +++++----- doc/layout_tolerance.html | 10 +++++----- doc/leda_conversion.html | 10 +++++----- doc/make_biconnected_planar.html | 10 +++++----- doc/make_connected.html | 10 +++++----- doc/make_maximal_planar.html | 10 +++++----- doc/maximum_matching.html | 14 +++++++------- doc/minimum_degree_ordering.html | 10 +++++----- doc/null_visitor.html | 10 +++++----- doc/opposite.html | 10 +++++----- doc/planar_canonical_ordering.html | 12 ++++++------ doc/planar_face_traversal.html | 10 +++++----- doc/planar_graphs.html | 10 +++++----- doc/plod_generator.html | 16 ++++++++-------- doc/predecessor_recorder.html | 10 +++++----- doc/prim_minimum_spanning_tree.html | 10 +++++----- doc/property.html | 10 +++++----- doc/property_map.html | 10 +++++----- doc/property_writer.html | 10 +++++----- doc/publications.html | 10 +++++----- doc/push_relabel_max_flow.html | 10 +++++----- doc/python.html | 10 +++++----- doc/quick_tour.html | 10 +++++----- doc/r_c_shortest_paths.html | 18 +++++++++--------- doc/random.html | 10 +++++----- doc/random_layout.html | 10 +++++----- doc/read_graphviz.html | 10 +++++----- doc/reverse_graph.html | 10 +++++----- doc/sequential_vertex_coloring.html | 10 +++++----- doc/small_world_generator.html | 16 ++++++++-------- doc/sorted_erdos_renyi_gen.html | 18 +++++++++--------- doc/sparse_matrix_ordering.html | 10 +++++----- doc/stanford_graph.html | 6 +++--- doc/straight_line_drawing.html | 10 +++++----- doc/strong_components.html | 10 +++++----- doc/subgraph.html | 10 +++++----- doc/table_of_contents.html | 10 +++++----- doc/time_stamper.html | 10 +++++----- doc/topological_sort.html | 10 +++++----- doc/transitive_closure.html | 10 +++++----- doc/transpose_graph.html | 10 +++++----- doc/trouble_shooting.html | 10 +++++----- doc/undirected_dfs.html | 10 +++++----- doc/users.html | 10 +++++----- doc/using_adjacency_list.html | 10 +++++----- doc/using_property_maps.html | 10 +++++----- doc/visitor_concepts.html | 10 +++++----- doc/write-graphviz.html | 10 +++++----- 136 files changed, 705 insertions(+), 704 deletions(-) mode change 100755 => 100644 doc/maximum_matching.html diff --git a/doc/AStarHeuristic.html b/doc/AStarHeuristic.html index a123dc0b..d57ed61b 100644 --- a/doc/AStarHeuristic.html +++ b/doc/AStarHeuristic.html @@ -1,10 +1,10 @@ Boost Graph Library: AStarHeuristic diff --git a/doc/AStarVisitor.html b/doc/AStarVisitor.html index fe4d3c5c..422ecb7a 100644 --- a/doc/AStarVisitor.html +++ b/doc/AStarVisitor.html @@ -1,10 +1,10 @@ Boost Graph Library: AStarVisitor diff --git a/doc/AddEdgeVisitor.html b/doc/AddEdgeVisitor.html index f263ed92..50ba8967 100644 --- a/doc/AddEdgeVisitor.html +++ b/doc/AddEdgeVisitor.html @@ -1,11 +1,11 @@ AddEdgeVisitor Concept @@ -127,4 +127,4 @@ and update the edge index for the newly created edge. Copyright © 2007 Aaron Windsor ( aaron.windsor@gmail.com) - \ No newline at end of file + diff --git a/doc/AdjacencyGraph.html b/doc/AdjacencyGraph.html index 317b34bb..3278d533 100644 --- a/doc/AdjacencyGraph.html +++ b/doc/AdjacencyGraph.html @@ -1,10 +1,10 @@ AdjacencyGraph diff --git a/doc/AdjacencyMatrix.html b/doc/AdjacencyMatrix.html index cb458547..1ddf78ab 100644 --- a/doc/AdjacencyMatrix.html +++ b/doc/AdjacencyMatrix.html @@ -1,10 +1,10 @@ AdjacencyMatrix diff --git a/doc/BFSVisitor.html b/doc/BFSVisitor.html index 2d6fc3d7..259aaf88 100644 --- a/doc/BFSVisitor.html +++ b/doc/BFSVisitor.html @@ -1,10 +1,10 @@ Boost Graph Library: BFSVisitor diff --git a/doc/BasicMatrix.html b/doc/BasicMatrix.html index 986abaea..d3a7e03d 100644 --- a/doc/BasicMatrix.html +++ b/doc/BasicMatrix.html @@ -1,10 +1,10 @@ BasicMatrix diff --git a/doc/BellmanFordVisitor.html b/doc/BellmanFordVisitor.html index c49992b9..0c74d7cd 100644 --- a/doc/BellmanFordVisitor.html +++ b/doc/BellmanFordVisitor.html @@ -1,10 +1,10 @@ Boost Graph Library: Bellman Ford Visitor diff --git a/doc/BidirectionalGraph.html b/doc/BidirectionalGraph.html index 404b1c72..d4732d1a 100644 --- a/doc/BidirectionalGraph.html +++ b/doc/BidirectionalGraph.html @@ -1,10 +1,10 @@ Bidirectional diff --git a/doc/Buffer.html b/doc/Buffer.html index 3a52b1b1..19aaac3c 100644 --- a/doc/Buffer.html +++ b/doc/Buffer.html @@ -1,10 +1,10 @@ Buffer diff --git a/doc/ColorValue.html b/doc/ColorValue.html index 4e3111b3..ef862934 100644 --- a/doc/ColorValue.html +++ b/doc/ColorValue.html @@ -1,10 +1,10 @@ Boost Graph Library: ColorValue Concept diff --git a/doc/DFSVisitor.html b/doc/DFSVisitor.html index 99784844..c7d3e94e 100644 --- a/doc/DFSVisitor.html +++ b/doc/DFSVisitor.html @@ -1,10 +1,10 @@ DFS Visitor diff --git a/doc/DijkstraVisitor.html b/doc/DijkstraVisitor.html index c504cb71..36b2c7e2 100644 --- a/doc/DijkstraVisitor.html +++ b/doc/DijkstraVisitor.html @@ -1,10 +1,10 @@ Boost Graph Library: Dijkstra Visitor diff --git a/doc/EdgeListGraph.html b/doc/EdgeListGraph.html index f5d086ce..e7838893 100644 --- a/doc/EdgeListGraph.html +++ b/doc/EdgeListGraph.html @@ -1,10 +1,10 @@ EdgeListGraph diff --git a/doc/EdgeMutableGraph.html b/doc/EdgeMutableGraph.html index 07818d49..03e614ed 100644 --- a/doc/EdgeMutableGraph.html +++ b/doc/EdgeMutableGraph.html @@ -1,10 +1,10 @@ Edge Mutable Graph diff --git a/doc/EventVisitor.html b/doc/EventVisitor.html index 10cf6407..6fb03739 100644 --- a/doc/EventVisitor.html +++ b/doc/EventVisitor.html @@ -1,10 +1,10 @@ Boost Graph Library: EventVisitor diff --git a/doc/EventVisitorList.html b/doc/EventVisitorList.html index 070d391f..65546f97 100644 --- a/doc/EventVisitorList.html +++ b/doc/EventVisitorList.html @@ -1,10 +1,10 @@ Boost Graph Library: EventVisitorList diff --git a/doc/Graph.html b/doc/Graph.html index 50812786..4af74631 100644 --- a/doc/Graph.html +++ b/doc/Graph.html @@ -1,10 +1,10 @@ Graph diff --git a/doc/IncidenceGraph.html b/doc/IncidenceGraph.html index 069b9371..4b21e271 100644 --- a/doc/IncidenceGraph.html +++ b/doc/IncidenceGraph.html @@ -1,10 +1,10 @@ IncidenceGraph diff --git a/doc/IteratorConstructibleGraph.html b/doc/IteratorConstructibleGraph.html index 901452eb..a7977bef 100644 --- a/doc/IteratorConstructibleGraph.html +++ b/doc/IteratorConstructibleGraph.html @@ -1,10 +1,10 @@ IteratorConstructibleGraph diff --git a/doc/Monoid.html b/doc/Monoid.html index c0898b70..b9ab7a46 100644 --- a/doc/Monoid.html +++ b/doc/Monoid.html @@ -1,10 +1,10 @@ Monoid diff --git a/doc/MutableGraph.html b/doc/MutableGraph.html index b50890ca..b5cd35da 100644 --- a/doc/MutableGraph.html +++ b/doc/MutableGraph.html @@ -1,10 +1,10 @@ MutableGraph diff --git a/doc/MutablePropertyGraph.html b/doc/MutablePropertyGraph.html index 15f17711..dde8b968 100644 --- a/doc/MutablePropertyGraph.html +++ b/doc/MutablePropertyGraph.html @@ -1,10 +1,10 @@ MutablePropertyGraph diff --git a/doc/PlanarEmbedding.html b/doc/PlanarEmbedding.html index b8234a72..aae9e14b 100644 --- a/doc/PlanarEmbedding.html +++ b/doc/PlanarEmbedding.html @@ -1,9 +1,9 @@ Planar Embedding Concept diff --git a/doc/PlanarFaceVisitor.html b/doc/PlanarFaceVisitor.html index 3fa3ab59..ee140ea4 100644 --- a/doc/PlanarFaceVisitor.html +++ b/doc/PlanarFaceVisitor.html @@ -1,10 +1,10 @@ Planar Face Visitor Concept diff --git a/doc/PropertyGraph.html b/doc/PropertyGraph.html index 2ed567b6..fb6f7598 100644 --- a/doc/PropertyGraph.html +++ b/doc/PropertyGraph.html @@ -1,10 +1,10 @@ PropertyGraph diff --git a/doc/PropertyTag.html b/doc/PropertyTag.html index 6b0c0267..549aa2db 100644 --- a/doc/PropertyTag.html +++ b/doc/PropertyTag.html @@ -1,10 +1,10 @@ Property diff --git a/doc/VertexAndEdgeListGraph.html b/doc/VertexAndEdgeListGraph.html index 50c6a134..bde47f84 100644 --- a/doc/VertexAndEdgeListGraph.html +++ b/doc/VertexAndEdgeListGraph.html @@ -1,10 +1,10 @@ VertexAndEdgeListGraph diff --git a/doc/VertexListGraph.html b/doc/VertexListGraph.html index e49cdfca..f508efb8 100644 --- a/doc/VertexListGraph.html +++ b/doc/VertexListGraph.html @@ -1,10 +1,10 @@ VertexListGraph diff --git a/doc/VertexMutableGraph.html b/doc/VertexMutableGraph.html index cec0a001..5609439d 100644 --- a/doc/VertexMutableGraph.html +++ b/doc/VertexMutableGraph.html @@ -1,10 +1,10 @@ Vertex Mutable Graph diff --git a/doc/acknowledgements.html b/doc/acknowledgements.html index 16f3af7e..670766e7 100644 --- a/doc/acknowledgements.html +++ b/doc/acknowledgements.html @@ -1,10 +1,10 @@ Boost Graph Library: Acknowledgements diff --git a/doc/adjacency_iterator.html b/doc/adjacency_iterator.html index b995da3e..159c8f72 100644 --- a/doc/adjacency_iterator.html +++ b/doc/adjacency_iterator.html @@ -1,10 +1,10 @@ diff --git a/doc/adjacency_list.html b/doc/adjacency_list.html index cb23a0ea..670e49e5 100644 --- a/doc/adjacency_list.html +++ b/doc/adjacency_list.html @@ -1,10 +1,10 @@ Boost Graph Library: Adjacency List diff --git a/doc/adjacency_list_traits.html b/doc/adjacency_list_traits.html index 14f60063..8680084e 100644 --- a/doc/adjacency_list_traits.html +++ b/doc/adjacency_list_traits.html @@ -1,10 +1,10 @@ Boost Graph Library: Graph Traits diff --git a/doc/adjacency_matrix.html b/doc/adjacency_matrix.html index 4f8d5390..e5d5e431 100644 --- a/doc/adjacency_matrix.html +++ b/doc/adjacency_matrix.html @@ -1,10 +1,10 @@ Boost Graph Library: Adjacency Matrix diff --git a/doc/astar_heuristic.html b/doc/astar_heuristic.html index 163066bb..ea648842 100644 --- a/doc/astar_heuristic.html +++ b/doc/astar_heuristic.html @@ -1,10 +1,10 @@ Boost Graph Library: astar_heuristic diff --git a/doc/astar_visitor.html b/doc/astar_visitor.html index 3df6a3ae..bfcb350d 100644 --- a/doc/astar_visitor.html +++ b/doc/astar_visitor.html @@ -1,10 +1,10 @@ Boost Graph Library: astar_visitor diff --git a/doc/bandwidth.html b/doc/bandwidth.html index 53877877..1d88befa 100644 --- a/doc/bandwidth.html +++ b/doc/bandwidth.html @@ -1,10 +1,10 @@ Boost Graph Library: Bandwidth diff --git a/doc/bc_clustering.html b/doc/bc_clustering.html index 9fa60e50..fc677b3c 100644 --- a/doc/bc_clustering.html +++ b/doc/bc_clustering.html @@ -1,10 +1,10 @@ diff --git a/doc/bellman_ford_shortest.html b/doc/bellman_ford_shortest.html index eb660b6f..89268b0d 100644 --- a/doc/bellman_ford_shortest.html +++ b/doc/bellman_ford_shortest.html @@ -1,10 +1,10 @@ Bellman Ford Shortest Paths diff --git a/doc/bellman_visitor.html b/doc/bellman_visitor.html index a5dfe9bf..77d439df 100644 --- a/doc/bellman_visitor.html +++ b/doc/bellman_visitor.html @@ -1,10 +1,10 @@ Boost Graph Library: bellman_visitor diff --git a/doc/betweenness_centrality.html b/doc/betweenness_centrality.html index cc3741e0..7e332ef6 100644 --- a/doc/betweenness_centrality.html +++ b/doc/betweenness_centrality.html @@ -1,11 +1,11 @@ Boost Graph Library: Brandes' Betweenness Centrality diff --git a/doc/bfs_visitor.html b/doc/bfs_visitor.html index d38f9a1a..aa6e2f30 100644 --- a/doc/bfs_visitor.html +++ b/doc/bfs_visitor.html @@ -1,10 +1,10 @@ Boost Graph Library: bfs_visitor diff --git a/doc/bgl_named_params.html b/doc/bgl_named_params.html index 282e0c82..98449486 100644 --- a/doc/bgl_named_params.html +++ b/doc/bgl_named_params.html @@ -1,10 +1,10 @@ Boost Graph Library: Named Parameters diff --git a/doc/bibliography.html b/doc/bibliography.html index 19799338..437540df 100644 --- a/doc/bibliography.html +++ b/doc/bibliography.html @@ -1,10 +1,10 @@ Boost Graph Library: Bibliography diff --git a/doc/biconnected_components.html b/doc/biconnected_components.html index 3b1afa95..74b34c3b 100644 --- a/doc/biconnected_components.html +++ b/doc/biconnected_components.html @@ -1,14 +1,14 @@ Boost Graph Library: Biconnected Components and Articulation Points diff --git a/doc/boyer_myrvold.html b/doc/boyer_myrvold.html index 69569e98..fdefdb41 100644 --- a/doc/boyer_myrvold.html +++ b/doc/boyer_myrvold.html @@ -1,10 +1,10 @@ Boost Graph Library: Boyer-Myrvold Planarity Testing/Embedding diff --git a/doc/breadth_first_search.html b/doc/breadth_first_search.html index 169fc103..5560285e 100644 --- a/doc/breadth_first_search.html +++ b/doc/breadth_first_search.html @@ -1,10 +1,10 @@ Boost Graph Library: Breadth-First Search diff --git a/doc/breadth_first_visit.html b/doc/breadth_first_visit.html index c5aa5c1c..a7309f02 100644 --- a/doc/breadth_first_visit.html +++ b/doc/breadth_first_visit.html @@ -1,10 +1,10 @@ Boost Graph Library: Breadth-First Visit diff --git a/doc/bundles.html b/doc/bundles.html index bafbbdd5..f73ba623 100644 --- a/doc/bundles.html +++ b/doc/bundles.html @@ -1,12 +1,12 @@ Bundled Properties diff --git a/doc/challenge.html b/doc/challenge.html index 2fa7740a..b17b1bc4 100644 --- a/doc/challenge.html +++ b/doc/challenge.html @@ -1,10 +1,10 @@ Challenge diff --git a/doc/circle_layout.html b/doc/circle_layout.html index eceffa91..31e5d470 100644 --- a/doc/circle_layout.html +++ b/doc/circle_layout.html @@ -1,9 +1,9 @@ Function template circle_graph_layout
    boost.png (6897 bytes)HomeLibrariesPeopleFAQMore


    (Python)Function template circle_graph_layout

    boost::circle_graph_layout — Layout the graph with the vertices at the points of a regular n-polygon.

    Synopsis

     template<typename VertexListGraph, typename PositionMap, typename Radius> 
    diff --git a/doc/connected_components.html b/doc/connected_components.html
    index dcfbe8e2..776cfc0e 100644
    --- a/doc/connected_components.html
    +++ b/doc/connected_components.html
    @@ -1,10 +1,10 @@
     
     
     
     Boost Graph Library: Connected Components
    diff --git a/doc/constructing_algorithms.html b/doc/constructing_algorithms.html
    index 968df19c..79322828 100644
    --- a/doc/constructing_algorithms.html
    +++ b/doc/constructing_algorithms.html
    @@ -1,10 +1,10 @@
     
     
     
     Boost Graph Library: Constructing Graph Algorithms
    diff --git a/doc/copy_graph.html b/doc/copy_graph.html
    index ab31940f..72912d6b 100644
    --- a/doc/copy_graph.html
    +++ b/doc/copy_graph.html
    @@ -1,10 +1,10 @@
     
     
     
     Boost Graph Library: Copy Graph
    diff --git a/doc/cuthill_mckee_ordering.html b/doc/cuthill_mckee_ordering.html
    index f5d7c110..f51771ad 100644
    --- a/doc/cuthill_mckee_ordering.html
    +++ b/doc/cuthill_mckee_ordering.html
    @@ -1,10 +1,11 @@
     
     
    -
    +
     
      
     Boost Graph Library: Cuthill-Mckee Ordering
    diff --git a/doc/dag_shortest_paths.html b/doc/dag_shortest_paths.html
    index 4768dc0c..b3844e3f 100644
    --- a/doc/dag_shortest_paths.html
    +++ b/doc/dag_shortest_paths.html
    @@ -1,10 +1,10 @@
     
     
     
     Boost Graph Library: Directed Acyclic Graph Shortest Paths
    diff --git a/doc/depth_first_search.html b/doc/depth_first_search.html
    index 51d4d0fc..d60e78c8 100644
    --- a/doc/depth_first_search.html
    +++ b/doc/depth_first_search.html
    @@ -1,10 +1,10 @@
     
     
     
     Boost Graph Library: Depth-First Search
    diff --git a/doc/depth_first_visit.html b/doc/depth_first_visit.html
    index 7f1b704e..e192cc18 100644
    --- a/doc/depth_first_visit.html
    +++ b/doc/depth_first_visit.html
    @@ -1,10 +1,10 @@
     
     
     
     Boost Graph Library: Depth-First Visit
    diff --git a/doc/dfs_visitor.html b/doc/dfs_visitor.html
    index 9c87ce34..f2d0dc34 100644
    --- a/doc/dfs_visitor.html
    +++ b/doc/dfs_visitor.html
    @@ -1,10 +1,10 @@
     
     
     
     Boost Graph Library: dfs_visitor
    diff --git a/doc/dijkstra_visitor.html b/doc/dijkstra_visitor.html
    index e6d3e146..a7afd34b 100644
    --- a/doc/dijkstra_visitor.html
    +++ b/doc/dijkstra_visitor.html
    @@ -1,10 +1,10 @@
     
     
     
     Boost Graph Library: dijkstra_visitor
    diff --git a/doc/distance_recorder.html b/doc/distance_recorder.html
    index deaf0b4e..2555c324 100644
    --- a/doc/distance_recorder.html
    +++ b/doc/distance_recorder.html
    @@ -1,10 +1,10 @@
     
     
     
     Boost Graph Library: distance_recorder
    diff --git a/doc/edge_list.html b/doc/edge_list.html
    index c1e0f202..94b85e65 100644
    --- a/doc/edge_list.html
    +++ b/doc/edge_list.html
    @@ -1,10 +1,10 @@
     
     
     
     Boost Graph Library: Edge List Class
    diff --git a/doc/edmonds_karp_max_flow.html b/doc/edmonds_karp_max_flow.html
    index 59d889b4..69389534 100644
    --- a/doc/edmonds_karp_max_flow.html
    +++ b/doc/edmonds_karp_max_flow.html
    @@ -1,10 +1,10 @@
     
     
     
     Boost Graph Library: Edmonds-Karp Maximum Flow
    diff --git a/doc/erdos_renyi_generator.html b/doc/erdos_renyi_generator.html
    index 6c17bc92..9c842deb 100644
    --- a/doc/erdos_renyi_generator.html
    +++ b/doc/erdos_renyi_generator.html
    @@ -1,14 +1,14 @@
     
     
     
       Boost Graph Library: Erdös-Renyi Generator
    diff --git a/doc/exception.html b/doc/exception.html
    index f5cbdf28..def19cef 100644
    --- a/doc/exception.html
    +++ b/doc/exception.html
    @@ -1,10 +1,10 @@
     
     
     
     Boost Graph Library: Exceptions
    diff --git a/doc/faq.html b/doc/faq.html
    index eeef22e4..6f491484 100644
    --- a/doc/faq.html
    +++ b/doc/faq.html
    @@ -1,10 +1,10 @@
     
     
     
     Boost Graph Library: FAQ
    diff --git a/doc/file_dependency_example.html b/doc/file_dependency_example.html
    index 1b7ff931..39b1a8e8 100644
    --- a/doc/file_dependency_example.html
    +++ b/doc/file_dependency_example.html
    @@ -1,10 +1,10 @@
     
     
     
     File Dependency Example
    diff --git a/doc/filtered_graph.html b/doc/filtered_graph.html
    index 296171f7..a72e531b 100644
    --- a/doc/filtered_graph.html
    +++ b/doc/filtered_graph.html
    @@ -1,10 +1,10 @@
     
     
     
     Boost Graph Library: Filtered Graph
    diff --git a/doc/fruchterman_reingold.html b/doc/fruchterman_reingold.html
    index 89b58e62..4b890dc2 100644
    --- a/doc/fruchterman_reingold.html
    +++ b/doc/fruchterman_reingold.html
    @@ -1,10 +1,10 @@
     
     
     
     
    diff --git a/doc/graph_coloring.html b/doc/graph_coloring.html
    index 26d52ecf..cc632590 100644
    --- a/doc/graph_coloring.html
    +++ b/doc/graph_coloring.html
    @@ -1,10 +1,10 @@
     
     
     
     Graph Coloring Example
    diff --git a/doc/graph_concepts.html b/doc/graph_concepts.html
    index 1291c10b..d2b949bc 100644
    --- a/doc/graph_concepts.html
    +++ b/doc/graph_concepts.html
    @@ -1,10 +1,10 @@
     
     
     
     Boost Graph Concepts
    diff --git a/doc/graph_theory_review.html b/doc/graph_theory_review.html
    index 4d5f64ea..ae80c8b3 100644
    --- a/doc/graph_theory_review.html
    +++ b/doc/graph_theory_review.html
    @@ -1,10 +1,10 @@
     
     
     
     Boost Graph Library: Graph Theory Review
    diff --git a/doc/graph_traits.html b/doc/graph_traits.html
    index e0916b0b..f31652e0 100644
    --- a/doc/graph_traits.html
    +++ b/doc/graph_traits.html
    @@ -1,10 +1,10 @@
     
     
     
     Boost Graph Library: Graph Traits
    diff --git a/doc/gursoy_atun_layout.html b/doc/gursoy_atun_layout.html
    index e90fa196..c927fd1b 100644
    --- a/doc/gursoy_atun_layout.html
    +++ b/doc/gursoy_atun_layout.html
    @@ -1,10 +1,10 @@
     
     
     
     Boost Graph Library: Gürsoy-Atun Layout
    diff --git a/doc/history.html b/doc/history.html
    index 0b7bd2d3..2d014b5a 100644
    --- a/doc/history.html
    +++ b/doc/history.html
    @@ -1,10 +1,10 @@
     
     
     
     Boost Graph Library: History
    diff --git a/doc/howard_cycle_ratio.html b/doc/howard_cycle_ratio.html
    index 76a64983..1deb6317 100644
    --- a/doc/howard_cycle_ratio.html
    +++ b/doc/howard_cycle_ratio.html
    @@ -9,13 +9,13 @@
     
     
     	
     	
     
     
     
    -

    Boost read_graphviz

    +

    Boost read_graphviz

    + +
    -template <typename MutableGraph>
    -bool read_graphviz(std::istream& in, MutableGraph& graph,
    -                   dynamic_properties& dp, 
    -                   const std::string& node_id = "node_id");
    +namespace boost {
     
    -// Only available if BOOST_GRAPH_READ_GRAPHVIZ_ITERATORS is defined
    -template <typename MultiPassIterator, typename MutableGraph>
    -bool read_graphviz(MultiPassIterator begin, MultiPassIterator end,
    -                   MutableGraph& graph, dynamic_properties& dp, 
    -                   const std::string& node_id = "node_id");
    +  template <typename MutableGraph>
    +  bool read_graphviz(std::istream& in, MutableGraph& graph,
    +                     dynamic_properties& dp,
    +                     const std::string& node_id = "node_id");
     
    -// Deprecated GraphViz readers
    -void read_graphviz(const std::string& file, GraphvizDigraph& g);
    -void read_graphviz(FILE* file, GraphvizDigraph& g);
    -void read_graphviz(const std::string& file, GraphvizGraph& g);
    -void read_graphviz(FILE* file, GraphvizGraph& g);
    +  template <typename BidirectionalIterator, typename MutableGraph>
    +  bool read_graphviz(BidirectionalIterator begin, BidirectionalIterator end,
    +                     MutableGraph& graph, dynamic_properties& dp,
    +                     const std::string& node_id = "node_id");
    +
    +}
     

    The read_graphviz function interprets a graph described using the -GraphViz DOT language and builds a BGL graph that captures that -description. Using this function, you can initialize a graph using -data stored as text. To use the iterator version of read_graphviz, -you will need to define the macro BOOST_GRAPH_READ_GRAPHVIZ_ITERATORS -before including the header <boost/graph/graphviz.hpp>. Doing so -may greatly increase the amount of time required to compile the -GraphViz reader.

    +GraphViz DOT language and builds a BGL graph that captures that +description. Using these functions, you can initialize a graph using +data stored as text.

    +

    The BOOST_GRAPH_USE_SPIRIT_PARSER macro may be defined before including +<boost/graph/graphviz.hpp> to include a previous parser implementation, +with the same interface, that uses Spirit for its implementation. The main +advantage of that version is that it supports subgraphs to a limited extent, +while the new parser does not support them at all.

    The DOT language can specify both directed and undirected graphs, and read_graphviz differentiates between the two. One must pass read_graphviz an undirected graph when reading an undirected graph; @@ -50,7 +321,7 @@ the same is true for directed graphs. Furthermore, will throw an exception if it encounters parallel edges and cannot add them to the graph.

    To handle properties expressed in the DOT language, read_graphviz -takes a dynamic_properties object and operates on its collection of +takes a dynamic_properties object and operates on its collection of property maps. The reader passes all the properties encountered to this object, using the GraphViz string keys as the property keys. Furthermore, read_graphviz stores node identifier names under the @@ -58,32 +329,31 @@ vertex property map named node_id.

    Requirements:
    -

    Where Defined

    +

    Where Defined

    <boost/graph/graphviz.hpp>

    -

    Exceptions

    +

    Exceptions

     struct graph_exception : public std::exception {
       virtual ~graph_exception() throw();
    @@ -130,13 +400,13 @@ graph is undirected, as indicated by the 
     
    -

    Example

    +

    Example

    The following example illustrates a relatively simple use of the GraphViz reader to populate an adjacency_list graph

     // Vertex properties
     typedef property < vertex_name_t, std::string,
    -          property < vertex_color_t, float > > vertex_p;  
    +          property < vertex_color_t, float > > vertex_p;
     // Edge properties
     typedef property < edge_weight_t, double > edge_p;
     // Graph properties
    @@ -162,7 +432,7 @@ property_map<graph_t, edge_weight_t>::type weight =
     dp.property("weight",weight);
     
     // Use ref_property_map to turn a graph property into a property map
    -boost::ref_property_map<graph_t*,std::string> 
    +boost::ref_property_map<graph_t*,std::string>
       gname(get_property(graph,graph_name));
     dp.property("name",gname);
     
    @@ -174,20 +444,13 @@ bool status = read_graphviz(gvgraph,graph,dp,"node_id");
     
    -

    Building the GraphViz Readers

    +

    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.

    -
    -
    -

    Deprecated Readers

    -

    The deprecated readers do not provide exceptions on error (they -abort), they require the use of one of the predefined graph types -(GraphvizDigraph or GraphvizGraph), and they do not support -arbitrary properties. They will be removed in a future Boost version.

    +the "boost_regex" library. The library can be built by following the +Boost Jam Build Instructions for the subdirectory libs/regex/build.

    -

    Notes

    +

    Notes

    • The read_graphviz function does not use any code from the @@ -196,15 +459,6 @@ implementation was based on documentation found on the GraphViz web site, as well as experiments run using the dot application. The resulting interpretation may be subtly different from dot for some corner cases that are not well specified.
    • -
    • read_graphviz treats subgraphs as syntactic sugar. It does not -reflect subgraphs as actual entities in the BGL. Rather, they are -used to shorten some edge definitions as well as to give a subset -of all nodes or edges certain properties. For example, the -DOT graphs digraph { a -> subgraph {b -> c} -> e } and -digraph { a -> b -> e ; a -> c -> e ; b -> c} are equivalent.
    • -
    • Subgraph IDs refer to subgraphs defined earlier in the graph -description. Undefined subgraphs behave as empty subgraphs -({}).
    • On successful reading of a graph, every vertex and edge will have an associated value for every respective edge and vertex property encountered while interpreting the graph. These values will be set @@ -217,21 +471,33 @@ given the default constructed value of the value type. Be sure that property map value types are default constructible.
    + +
    -

    Future Work

    +

    Future Work

      -
    • The parser currently does not handle continuation lines as defined -in the DOT Language. Some more sophisticated parsing of -identifier(so-called "ID" in the source) is required to support this.
    • -
    • Support for optional recognition of subgraphs as distinct entities.
    • +
    • Support for subgraphs (currently parsed but ignored).
    • +
    • Support for HTML strings.
    • +
    • Passing port information to BGL.
    • +
    • Expanding escape codes in the same way GraphViz does.
    • +
    • Enforcement of the strict keyword (ignoring self-loops and parallel +edges).
    +
    diff --git a/doc/read_graphviz.rst b/doc/read_graphviz.rst index 2d0aadbb..b528bb7b 100644 --- a/doc/read_graphviz.rst +++ b/doc/read_graphviz.rst @@ -14,32 +14,31 @@ __ ../../../index.htm :: - template - bool read_graphviz(std::istream& in, MutableGraph& graph, - dynamic_properties& dp, - const std::string& node_id = "node_id"); - - // Only available if BOOST_GRAPH_READ_GRAPHVIZ_ITERATORS is defined - template - bool read_graphviz(MultiPassIterator begin, MultiPassIterator end, - MutableGraph& graph, dynamic_properties& dp, - const std::string& node_id = "node_id"); - - // Deprecated GraphViz readers - void read_graphviz(const std::string& file, GraphvizDigraph& g); - void read_graphviz(FILE* file, GraphvizDigraph& g); - void read_graphviz(const std::string& file, GraphvizGraph& g); - void read_graphviz(FILE* file, GraphvizGraph& g); + namespace boost { + + template + bool read_graphviz(std::istream& in, MutableGraph& graph, + dynamic_properties& dp, + const std::string& node_id = "node_id"); + + template + bool read_graphviz(BidirectionalIterator begin, BidirectionalIterator end, + MutableGraph& graph, dynamic_properties& dp, + const std::string& node_id = "node_id"); + + } The ``read_graphviz`` function interprets a graph described using the GraphViz_ DOT language and builds a BGL graph that captures that -description. Using this function, you can initialize a graph using -data stored as text. To use the iterator version of ``read_graphviz``, -you will need to define the macro BOOST_GRAPH_READ_GRAPHVIZ_ITERATORS -before including the header ````. Doing so -may greatly increase the amount of time required to compile the -GraphViz reader. +description. Using these functions, you can initialize a graph using +data stored as text. + +The ``BOOST_GRAPH_USE_SPIRIT_PARSER`` macro may be defined before including +```` to include a previous parser implementation, +with the same interface, that uses Spirit for its implementation. The main +advantage of that version is that it supports subgraphs to a limited extent, +while the new parser does not support them at all. The DOT language can specify both directed and undirected graphs, and ``read_graphviz`` differentiates between the two. One must pass @@ -57,7 +56,7 @@ vertex property map named node_id. Requirements: - The type of the graph must model the `Mutable Graph`_ concept. - - The type of the iterator must model the `Multi-Pass Iterator`_ + - The type of the iterator must model the `Bidirectional Iterator`_ concept. - The property map value types must be default-constructible. @@ -172,15 +171,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``. - -Deprecated Readers ------------------- -The deprecated readers do not provide exceptions on error (they -abort), they require the use of one of the predefined graph types -(``GraphvizDigraph`` or ``GraphvizGraph``), and they do not support -arbitrary properties. They will be removed in a future Boost version. +the "boost_regex" library. The library can be built by following the +`Boost Jam Build Instructions`_ for the subdirectory ``libs/regex/build``. Notes @@ -193,17 +185,6 @@ Notes resulting interpretation may be subtly different from dot for some corner cases that are not well specified. - - ``read_graphviz`` treats subgraphs as syntactic sugar. It does not - reflect subgraphs as actual entities in the BGL. Rather, they are - used to shorten some edge definitions as well as to give a subset - of all nodes or edges certain properties. For example, the - DOT graphs ``digraph { a -> subgraph {b -> c} -> e }`` and - ``digraph { a -> b -> e ; a -> c -> e ; b -> c}`` are equivalent. - - - Subgraph IDs refer to subgraphs defined earlier in the graph - description. Undefined subgraphs behave as empty subgraphs - (``{}``). - - On successful reading of a graph, every vertex and edge will have an associated value for every respective edge and vertex property encountered while interpreting the graph. These values will be set @@ -215,6 +196,19 @@ Notes given the default constructed value of the value type. **Be sure that property map value types are default constructible.** +.. + - ``read_graphviz`` treats subgraphs as syntactic sugar. It does not + reflect subgraphs as actual entities in the BGL. Rather, they are + used to shorten some edge definitions as well as to give a subset + of all nodes or edges certain properties. For example, the + DOT graphs ``digraph { a -> subgraph {b -> c} -> e }`` and + ``digraph { a -> b -> e ; a -> c -> e ; b -> c}`` are equivalent. + +.. + - Subgraph IDs refer to subgraphs defined earlier in the graph + description. Undefined subgraphs behave as empty subgraphs + (``{}``). + See Also -------- @@ -224,16 +218,24 @@ write_graphviz_ Future Work ----------- - - The parser currently does not handle continuation lines as defined - in the DOT Language. Some more sophisticated parsing of - identifier(so-called "ID" in the source) is required to support this. + - Support for subgraphs (currently parsed but ignored). - - Support for optional recognition of subgraphs as distinct entities. + - Support for HTML strings. + + - Passing port information to BGL. + + - Expanding escape codes in the same way GraphViz does. + + - Enforcement of the ``strict`` keyword (ignoring self-loops and parallel + edges). +.. + - Support for optional recognition of subgraphs as distinct entities. + .. _GraphViz: http://graphviz.org/ .. _`Mutable Graph`: MutableGraph.html -.. _`Multi-Pass Iterator`: ../../iterator/index.html +.. _`Bidirectional Iterator`: http://www.sgi.com/tech/stl/BidirectionalIterator.html .. _dynamic_properties: ../../property_map/doc/dynamic_property_map.html .. _write_graphviz: write-graphviz.html .. _Boost Jam Build Instructions: ../../../more/getting_started.html#Build_Install diff --git a/include/boost/graph/detail/read_graphviz_new.hpp b/include/boost/graph/detail/read_graphviz_new.hpp new file mode 100644 index 00000000..7df4acec --- /dev/null +++ b/include/boost/graph/detail/read_graphviz_new.hpp @@ -0,0 +1,699 @@ +// Copyright 2004-9 Trustees of Indiana University + +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// +// read_graphviz_new.hpp - +// Initialize a model of the BGL's MutableGraph concept and an associated +// collection of property maps using a graph expressed in the GraphViz +// DOT Language. +// +// Based on the grammar found at: +// http://www.graphviz.org/cvs/doc/info/lang.html +// +// Jeremiah rewrite used grammar found at: +// http://www.graphviz.org/doc/info/lang.html +// and page 34 or http://www.graphviz.org/pdf/dotguide.pdf +// +// See documentation for this code at: +// http://www.boost.org/libs/graph/doc/read-graphviz.html +// + +// Author: Jeremiah Willcock +// Ronald Garcia +// + +#ifndef BOOST_READ_GRAPHVIZ_NEW_HPP +#define BOOST_READ_GRAPHVIZ_NEW_HPP + +#include +#include +#include +#include +#include +#include +#include +#include // for std::exception +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost { + +namespace read_graphviz_detail { + struct token { + enum token_type { + kw_strict, + kw_graph, + kw_digraph, + kw_node, + kw_edge, + kw_subgraph, + left_brace, + right_brace, + semicolon, + equal, + left_bracket, + right_bracket, + comma, + colon, + dash_greater, + dash_dash, + plus, + left_paren, + right_paren, + at, + identifier, + quoted_string, // Only used internally in tokenizer + eof, + invalid + } type; + std::string normalized_value; // May have double-quotes removed and/or some escapes replaced + token(token_type type, const std::string& normalized_value) + : type(type), normalized_value(normalized_value) {} + token(): type(invalid), normalized_value("") {} + friend std::ostream& operator<<(std::ostream& o, const token& t) { + switch (t.type) { + case token::kw_strict: o << ""; break; + case token::kw_graph: o << ""; break; + case token::kw_digraph: o << ""; break; + case token::kw_node: o << ""; break; + case token::kw_edge: o << ""; break; + case token::kw_subgraph: o << ""; break; + case token::left_brace: o << ""; break; + case token::right_brace: o << ""; break; + case token::semicolon: o << ""; break; + case token::equal: o << ""; break; + case token::left_bracket: o << ""; break; + case token::right_bracket: o << ""; break; + case token::comma: o << ""; break; + case token::colon: o << ""; break; + case token::dash_greater: o << ""; break; + case token::dash_dash: o << ""; break; + case token::plus: o << ""; break; + case token::left_paren: o << ""; break; + case token::right_paren: o << ""; break; + case token::at: o << ""; break; + case token::identifier: o << ""; break; + case token::quoted_string: o << ""; break; + case token::eof: o << ""; break; + default: o << ""; break; + } + o << " '" << t.normalized_value << "'"; + return o; + } + }; + + struct lex_error: public std::exception { + std::string errmsg; + char bad_char; + lex_error(const std::string& errmsg, char bad_char): errmsg(errmsg), bad_char(bad_char) { + this->errmsg += std::string(" (char is '") + bad_char + "')"; + } + const char* what() const throw () {return errmsg.c_str();} + ~lex_error() throw () {}; + }; + + struct parse_error: public std::exception { + std::string errmsg; + token bad_token; + parse_error(const std::string& errmsg, const token& bad_token): errmsg(errmsg), bad_token(bad_token) { + this->errmsg += std::string(" (token is \"") + boost::lexical_cast(bad_token) + "\")"; + } + const char* what() const throw () {return errmsg.c_str();} + ~parse_error() throw () {}; + }; + + template + struct tokenizer { + BidirectionalIterator begin, end; + std::vector lookahead; + // Precomputed regexes + boost::regex stuff_to_skip; + boost::regex basic_id_token; + boost::regex punctuation_token; + boost::regex number_token; + boost::regex quoted_string_token; + + tokenizer(BidirectionalIterator begin, BidirectionalIterator end) + : begin(begin), end(end) + { + std::string end_of_token = "(?=(?:\\W))"; + std::string whitespace = "(?:\\s+)"; + std::string slash_slash_comment = "(?://.*$)"; + std::string slash_star_comment = "(?:/\\*.*?\\*/)"; + std::string hash_comment = "(?:^#.*?$)"; + stuff_to_skip = "\\A(?:" + whitespace + "|" + slash_slash_comment + "|" + slash_star_comment + "|" + hash_comment + ")*"; + basic_id_token = "\\A([[:alpha:]_](?:\\w*))"; + punctuation_token = "\\A([][{};=,:+()@]|[-][>-])"; + number_token = "\\A([-]?(?:(?:\\.\\d+)|(?:\\d+(?:\\.\\d*)?)))"; + quoted_string_token = "\\A(\"(?:[^\"\\\\]|(?:[\\\\].))*\")"; + } + + void skip() { + boost::match_results results; + bool found = boost::regex_search(begin, end, results, stuff_to_skip); + assert (found); + boost::sub_match sm1 = results.suffix(); + assert (sm1.second == end); + begin = sm1.first; + } + + token get_token_raw() { + if (!lookahead.empty()) { + token t = lookahead.front(); + lookahead.erase(lookahead.begin()); + return t; + } + skip(); + if (begin == end) return token(token::eof, ""); + // Look for keywords first + bool found; + boost::match_results results; + found = boost::regex_search(begin, end, results, basic_id_token); + if (found) { + std::string str = results[1].str(); + std::string str_lower = boost::algorithm::to_lower_copy(str); + begin = results.suffix().first; + if (str_lower == "strict") { + return token(token::kw_strict, str); + } else if (str_lower == "graph") { + return token(token::kw_graph, str); + } else if (str_lower == "digraph") { + return token(token::kw_digraph, str); + } else if (str_lower == "node") { + return token(token::kw_node, str); + } else if (str_lower == "edge") { + return token(token::kw_edge, str); + } else if (str_lower == "subgraph") { + return token(token::kw_subgraph, str); + } else { + return token(token::identifier, str); + } + } + found = boost::regex_search(begin, end, results, punctuation_token); + if (found) { + std::string str = results[1].str(); + begin = results.suffix().first; + switch (str[0]) { + case '[': return token(token::left_bracket, str); + case ']': return token(token::right_bracket, str); + case '{': return token(token::left_brace, str); + case '}': return token(token::right_brace, str); + case ';': return token(token::semicolon, str); + case '=': return token(token::equal, str); + case ',': return token(token::comma, str); + case ':': return token(token::colon, str); + case '+': return token(token::plus, str); + case '(': return token(token::left_paren, str); + case ')': return token(token::right_paren, str); + case '@': return token(token::at, str); + case '-': { + 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: assert (!"Definition of punctuation_token does not match switch statement"); std::abort(); + } + } + found = boost::regex_search(begin, end, results, number_token); + if (found) { + std::string str = results[1].str(); + begin = results.suffix().first; + return token(token::identifier, str); + } + found = boost::regex_search(begin, end, results, quoted_string_token); + if (found) { + std::string str = results[1].str(); + begin = results.suffix().first; + // Remove the beginning and ending quotes + assert (str.size() >= 2); + str.erase(str.begin()); + str.erase(str.end() - 1); + // Unescape quotes in the middle, but nothing else (see format spec) + for (size_t i = 0; i + 1 < str.size() /* May change */; ++i) { + if (str[i] == '\\' && str[i + 1] == '"') { + str.erase(str.begin() + i); + // Don't need to adjust i + } else if (str[i] == '\\' && str[i + 1] == '\n') { + str.erase(str.begin() + i); + str.erase(str.begin() + i); + --i; // Invert ++ that will be applied + } + } + return token(token::quoted_string, str); + } + if (*begin == '<') { + throw_lex_error("HTML strings not supported"); + return token(); + } else { + throw_lex_error("Invalid character"); + return token(); + } + } + + token peek_token_raw() { + if (lookahead.empty()) { + token t = get_token_raw(); + lookahead.push_back(t); + } + return lookahead.front(); + } + + token get_token() { // Handle string concatenation + token t = get_token_raw(); + if (t.type != token::quoted_string) return t; + std::string str = t.normalized_value; + while (peek_token_raw().type == token::plus) { + get_token_raw(); + token t2 = get_token_raw(); + if (t2.type != token::quoted_string) { + throw_lex_error("Must have quoted string after string concatenation"); + } + str += t2.normalized_value; + } + return token(token::identifier, str); // Note that quoted_string does not get passed to the parser + } + + void throw_lex_error(const std::string& errmsg) { + boost::throw_exception(lex_error(errmsg, *begin)); + } + }; + + typedef std::map properties; + + struct node_id { + std::string name; + std::string angle; // Or empty if no angle + std::vector location; // Up to two identifiers + }; + + // Parser policy object should have the following methods: + // struct parser_policy { + // void do_node(const node_id& n, const properties& default_props, const properties& custom_props); + // void do_edge(const node_id& a, const node_id& b, const properties& props); + // void do_begin_graph(bool is_strict, bool is_directed, const std::string& name); + // void do_end_graph(const properties& props); + // void do_begin_subgraph(const std::string& name); + // void do_end_subgraph(const properties& props); + // }; + + template + struct parser { + tokenizer tokenizer; + std::vector lookahead; + bool graph_is_directed; + properties graph_props; + properties node_props; + properties edge_props; + Policy hooks; + + parser(BidirectionalIterator begin, BidirectionalIterator end, Policy hooks) + : tokenizer(begin, end), lookahead(), hooks(hooks) {} + + token get() { + if (lookahead.empty()) { + token t = tokenizer.get_token(); + return t; + } else { + token t = lookahead.front(); + lookahead.erase(lookahead.begin()); + return t; + } + } + + token peek() { + if (lookahead.empty()) { + lookahead.push_back(tokenizer.get_token()); + } + return lookahead.front(); + } + + void error(const std::string& str) { + boost::throw_exception(parse_error(str, peek())); + } + + void parse_graph(bool want_directed) { + bool is_strict = false; + bool is_directed; + std::string name; + if (peek().type == token::kw_strict) {get(); is_strict = true;} + switch (peek().type) { + case token::kw_graph: is_directed = false; break; + case token::kw_digraph: is_directed = true; break; + default: error("Wanted \"graph\" or \"digraph\""); + } + graph_is_directed = is_directed; // Used to check edges + if (want_directed != graph_is_directed) { + if (want_directed) { + boost::throw_exception(boost::undirected_graph_error()); + } else { + boost::throw_exception(boost::directed_graph_error()); + } + } + hooks.do_begin_graph(is_strict, is_directed, name); + get(); + switch (peek().type) { + case token::identifier: name = peek().normalized_value; get(); break; + case token::left_brace: break; + default: error("Wanted a graph name or left brace"); + } + if (peek().type == token::left_brace) get(); else error("Wanted a left brace to start the graph"); + parse_stmt_list(); + if (peek().type == token::right_brace) get(); else error("Wanted a right brace to end the graph"); + hooks.do_end_graph(graph_props); + if (peek().type == token::eof) {} else error("Wanted end of file"); + } + + void parse_stmt_list() { + while (true) { + if (peek().type == token::right_brace) return; + parse_stmt(); + if (peek().type == token::semicolon) get(); + } + } + + void parse_stmt() { + switch (peek().type) { + case token::kw_node: + case token::kw_edge: + case token::kw_graph: parse_attr_stmt(); break; + case token::kw_subgraph: + case token::left_brace: parse_subgraph(); break; + case token::identifier: { + token id = get(); + switch (peek().type) { + case token::dash_dash: + case token::dash_greater: { + node_id n = parse_node_id_rest(id); + parse_edge_stmt(n); + break; + } + case token::equal: { + get(); + if (peek().type != token::identifier) error("Wanted identifier as right side of ="); + token id2 = get(); + graph_props[id.normalized_value] = id2.normalized_value; + break; + } + default: { + node_id n = parse_node_id_rest(id); + parse_node_stmt(n); + break; + } + } + break; + } + default: error("Invalid start token for statement"); + } + } + + void parse_attr_stmt() { + switch (get().type) { + case token::kw_graph: parse_attr_list(graph_props); break; + case token::kw_node: parse_attr_list(node_props); break; + case token::kw_edge: parse_attr_list(edge_props); break; + default: assert (!"Bad attr_stmt case"); std::abort(); + } + } + + void parse_subgraph() { + std::string name; + if (peek().type == token::kw_subgraph) { + get(); + if (peek().type == token::identifier) { + name = get().normalized_value; + } + } + properties saved_node_props = node_props; + properties saved_edge_props = edge_props; + properties saved_graph_props = graph_props; + if (peek().type != token::left_brace) { + if (name.empty()) error("Subgraph reference needs a name"); + hooks.do_subgraph_reference(name); + return; + } + hooks.do_begin_subgraph(name); + if (peek().type == token::left_brace) get(); else error("Wanted left brace to start subgraph"); + parse_stmt_list(); + if (peek().type == token::right_brace) get(); else error("Wanted right brace to end subgraph"); + hooks.do_end_subgraph(graph_props); + node_props = saved_node_props; + edge_props = saved_edge_props; + graph_props = saved_graph_props; + if (peek().type == token::dash_greater || + peek().type == token::dash_dash) { // FIXME + std::cerr << "FIXME: Subgraphs in edges are not supported" << std::endl; + error("Unsupported subgraph edge case"); + } + } + + node_id parse_node_id_rest(const token& name) { + // A node ID is a node name, followed optionally by a port angle and a + // port location (in either order); a port location is either :id, + // :id:id, or :(id,id); the last two forms are treated as equivalent + // although I am not sure about that. + node_id id; + id.name = name.normalized_value; + parse_more: + switch (peek().type) { + case token::at: { + get(); + if (peek().type != token::identifier) error("Wanted identifier as port angle"); + if (id.angle != "") error("Duplicate port angle"); + id.angle = get().normalized_value; + goto parse_more; + } + case token::colon: { + get(); + if (!id.location.empty()) error("Duplicate port location"); + switch (peek().type) { + case token::identifier: { + id.location.push_back(get().normalized_value); + switch (peek().type) { + case token::colon: { + get(); + if (peek().type != token::identifier) error("Wanted identifier as port location"); + id.location.push_back(get().normalized_value); + goto parse_more; + } + default: goto parse_more; + } + } + case token::left_paren: { + get(); + if (peek().type != token::identifier) error("Wanted identifier as first element of port location"); + id.location.push_back(get().normalized_value); + if (peek().type != token::comma) error("Wanted comma between parts of port location"); + get(); + if (peek().type != token::identifier) error("Wanted identifier as second element of port location"); + id.location.push_back(get().normalized_value); + if (peek().type != token::right_paren) error("Wanted right parenthesis to close port location"); + get(); + goto parse_more; + } + default: error("Wanted identifier or left parenthesis as start of port location"); + } + } + default: break; + } + return id; + } + + node_id parse_node_id() { + if (peek().type != token::identifier) error("Wanted identifier as node name (subgraphs not supported yet)"); + token name = get(); + return parse_node_id_rest(name); + } + + void parse_node_stmt(const node_id& n) { + properties this_node_props; + if (peek().type == token::left_bracket) parse_attr_list(this_node_props); + hooks.do_node(n, node_props, this_node_props); + } + + void parse_edge_stmt(const node_id& lhs) { + std::vector nodes_in_chain(1, lhs); + while (true) { + bool leave_loop = true; + switch (peek().type) { + case token::dash_dash: { + if (graph_is_directed) error("Using -- in directed graph"); + get(); + nodes_in_chain.push_back(parse_node_id()); + leave_loop = false; + break; + } + case token::dash_greater: { + if (!graph_is_directed) error("Using -> in undirected graph"); + get(); + nodes_in_chain.push_back(parse_node_id()); + leave_loop = false; + break; + } + default: leave_loop = true; break; + } + if (leave_loop) break; + } + properties this_edge_props = 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 + for (size_t i = 0; i + 1 < nodes_in_chain.size(); ++i) { + hooks.do_edge(nodes_in_chain[i], nodes_in_chain[i + 1], this_edge_props); + } + } + + void parse_attr_list(properties& props) { + while (true) { + if (peek().type == token::left_bracket) get(); else error("Wanted left bracket to start attribute list"); + while (true) { + switch (peek().type) { + case token::right_bracket: break; + case token::identifier: { + std::string lhs = get().normalized_value; + std::string rhs = "true"; + if (peek().type == token::equal) { + get(); + if (peek().type != token::identifier) error("Wanted identifier as value of attributed"); + rhs = get().normalized_value; + } + props[lhs] = rhs; + break; + } + default: error("Wanted identifier as name of attribute"); + } + if (peek().type == token::comma) {get(); continue;} + break; + } + if (peek().type == token::right_bracket) get(); else error("Wanted right bracket to end attribute list"); + if (peek().type != token::left_bracket) break; + } + } + }; + + struct graph_parser_policy { + ::boost::detail::graph::mutate_graph* mg; + + typedef boost::detail::graph::node_t vertex; + typedef boost::detail::graph::edge_t edge; + + std::map vertex_map; + std::map edge_map; + + graph_parser_policy(::boost::detail::graph::mutate_graph* mg) + : mg(mg), + vertex_map(), + edge_map() + {} + + bool node_exists(const node_id& n) const { + std::map::const_iterator i = vertex_map.find(n.name); + return (i != vertex_map.end()); + } + + vertex get_or_build_node(const node_id& n) { + // FIXME: use ports + std::map::const_iterator i = vertex_map.find(n.name); + if (i == vertex_map.end()) { + vertex v = n.name; + mg->do_add_vertex(v); + vertex_map.insert(std::make_pair(v, v)); + return v; + } else { + return i->second; + } + } + + static std::string node_id_to_string(const node_id& n) { + std::string result = n.name; + for (size_t i = 0; i < n.location.size(); ++i) { + result += ":" + n.location[i]; + } + if (!n.angle.empty()) result += "@" + n.angle; + return result; + } + + static std::string props_to_string(const properties& props) { + std::string result = "["; + for (properties::const_iterator i = props.begin(); i != props.end(); ++i) { + if (i != props.begin()) result += ", "; + result += i->first + "=" + i->second; + } + result += "]"; + return result; + } + + void do_node(const node_id& n, const properties& def_props, const properties& new_props) { + std::cerr << node_id_to_string(n) << " " << props_to_string(def_props) << " " << props_to_string(new_props) << std::endl; + properties props_to_set = new_props; + if (!node_exists(n)) { // Only use defaults if node is new + props_to_set.insert(def_props.begin(), def_props.end()); // This keeps old properties in preference to ones from def_props + } + vertex v = get_or_build_node(n); + for (properties::const_iterator i = props_to_set.begin(); i != props_to_set.end(); ++i) { + mg->set_node_property(i->first, v, i->second); + } + } + + void do_edge(const node_id& a, const node_id& b, const properties& props) { + std::cerr << node_id_to_string(a) << " -> " << node_id_to_string(b) << " " << props_to_string(props) << std::endl; + edge e = edge::new_edge(); + mg->do_add_edge(e, get_or_build_node(a), get_or_build_node(b)); + for (properties::const_iterator i = props.begin(); i != props.end(); ++i) { + mg->set_edge_property(i->first, e, i->second); + } + } + + void do_begin_graph(bool is_strict, bool is_directed, const std::string& name) { + // std::cerr << "starting" << (is_strict ? " strict" : "") << " " << (is_directed ? "directed" : "undirected") << " graph named " << name << std::endl; + } + + void do_end_graph(const properties& props) { + std::cerr << "ending graph " << props_to_string(props) << std::endl; + for (properties::const_iterator i = props.begin(); i != props.end(); ++i) { + mg->set_graph_property(i->first, i->second); + } + } + + void do_subgraph_reference(const std::string& name) { + // std::cerr << "subgraph reference to " << name << std::endl; + } + + void do_begin_subgraph(const std::string& name) { + // std::cerr << "starting subgraph named " << name << std::endl; + } + + void do_end_subgraph(const properties& props) { + // std::cerr << "ending subgraph " << props_to_string(props) << std::endl; + } + }; + +} // namespace read_graphviz_detail + +template +bool read_graphviz(BidirectionalIterator begin, BidirectionalIterator end, + MutableGraph& graph, boost::dynamic_properties& dp, + std::string const& node_id = "node_id") { + boost::detail::graph::mutate_graph_impl mg(graph, dp, node_id); + read_graphviz_detail::graph_parser_policy policy(&mg); + read_graphviz_detail::parser p(begin, end, policy); + p.parse_graph(mg.is_directed()); + return true; +} + +} // namespace boost + +#endif // BOOST_READ_GRAPHVIZ_NEW_HPP diff --git a/include/boost/graph/graphviz.hpp b/include/boost/graph/graphviz.hpp index 5809923c..88dff67d 100644 --- a/include/boost/graph/graphviz.hpp +++ b/include/boost/graph/graphviz.hpp @@ -784,15 +784,24 @@ bool read_graphviz(std::istream& in, MutableGraph& graph, dynamic_properties& dp, std::string const& node_id = "node_id") { - detail::graph::mutate_graph_impl m_graph(graph, dp, node_id); - return detail::graph::read_graphviz(in, m_graph); + std::string data; + in >> std::noskipws; + std::copy(std::istream_iterator(in), + std::istream_iterator(), + std::back_inserter(data)); + return read_graphviz(data.begin(),data.end(),graph,dp,node_id); } } // namespace boost -#ifdef BOOST_GRAPH_READ_GRAPHVIZ_ITERATORS +#ifdef BOOST_GRAPH_USE_SPIRIT_PARSER +# ifndef BOOST_GRAPH_READ_GRAPHVIZ_ITERATORS +# define BOOST_GRAPH_READ_GRAPHVIZ_ITERATORS +# endif # include -#endif // BOOST_GRAPH_READ_GRAPHVIZ_ITERATORS +#else // New default parser +# include +#endif // BOOST_GRAPH_USE_SPIRIT_PARSER #ifdef BOOST_GRAPH_USE_MPI # include diff --git a/src/read_graphviz_spirit.cpp b/src/read_graphviz_spirit.cpp index 77bb718b..7fcdc280 100644 --- a/src/read_graphviz_spirit.cpp +++ b/src/read_graphviz_spirit.cpp @@ -26,38 +26,22 @@ # define BOOST_GRAPH_READ_GRAPHVIZ_ITERATORS #endif #include +#include namespace boost { namespace detail { namespace graph { +#if 0 BOOST_GRAPH_DECL bool read_graphviz(std::istream& in, mutate_graph& graph) { using namespace boost; - using namespace boost::spirit::classic; typedef std::istream_iterator is_t; - typedef multi_pass iterator_t; - iterator_t first(make_multi_pass(is_t(in))); - iterator_t last(make_multi_pass(is_t())); + std::string str((is_t(in)), is_t()); - // Turn off white space skipping on the stream - in.unsetf(std::ios::skipws); - - typedef skip_parser_iteration_policy< boost::detail::graph::dot_skipper> - iter_policy_t; - typedef scanner_policies scanner_policies_t; - typedef scanner scanner_t; - - boost::detail::graph::dot_grammar p(graph); - boost::detail::graph::dot_skipper skip_p; - - iter_policy_t iter_policy(skip_p); - scanner_policies_t policies(iter_policy); - - scanner_t scan(first, last, policies); - - return p.parse(scan); + return read_graphviz(str.begin(), str.end()); } +#endif } } } // end namespace boost::detail::graph diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 908d956c..dc7f52fa 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -58,7 +58,8 @@ test-suite graph_test : [ compile graph_concepts.cpp ] [ run graphviz_test.cpp /boost/test//boost_test_exec_monitor/static - ../build//boost_graph ] + ../build//boost_graph + ../../regex/build//boost_regex ] [ run metis_test.cpp : $(METIS_INPUT_FILE) ] [ run gursoy_atun_layout_test.cpp ] [ run layout_test.cpp : : : always_show_run_output intel:off ] @@ -85,7 +86,7 @@ test-suite graph_test : [ run matching_test.cpp ] [ run max_flow_test.cpp ] [ run kolmogorov_max_flow_test.cpp ] - [ run cycle_ratio_tests.cpp ../build//boost_graph : $(CYCLE_RATIO_INPUT_FILE) ] + [ run cycle_ratio_tests.cpp ../build//boost_graph ../../regex/build//boost_regex : $(CYCLE_RATIO_INPUT_FILE) ] [ run basic_planarity_test.cpp ] [ run make_connected_test.cpp ] [ run make_bicon_planar_test.cpp ] diff --git a/test/graphviz_test.cpp b/test/graphviz_test.cpp index e2dac5f9..83f79f2a 100644 --- a/test/graphviz_test.cpp +++ b/test/graphviz_test.cpp @@ -11,8 +11,8 @@ // Author: Ronald Garcia -//#define BOOST_GRAPH_READ_GRAPHVIZ_ITERATORS #define BOOST_GRAPHVIZ_USE_ISTREAM +#include #include #include #include @@ -31,9 +31,6 @@ using namespace std; using namespace boost; -#ifndef BOOST_GRAPHVIZ_USE_ISTREAM -using namespace boost::spirit; -#endif using namespace boost::assign; typedef std::string node_t; @@ -43,7 +40,8 @@ typedef std::map mass_map_t; typedef std::map weight_map_t; template -bool test_graph(std::istream& dotfile, mass_map_t const& masses, +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()) { @@ -79,11 +77,14 @@ bool test_graph(std::istream& dotfile, mass_map_t const& masses, if(read_graphviz(dotfile,graph,dp,node_id)) { #else std::string data; + dotfile >> std::noskipws; std::copy(std::istream_iterator(dotfile), std::istream_iterator(), std::back_inserter(data)); if(read_graphviz(data.begin(),data.end(),graph,dp,node_id)) { #endif + // check correct vertex count + BOOST_CHECK_EQUAL(num_vertices(graph), correct_num_vertices); // check masses if(!masses.empty()) { // assume that all the masses have been set @@ -139,16 +140,25 @@ int test_main(int, char*[]) { 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,masses,weight_map_t()))); + BOOST_CHECK((test_graph(gs,3,masses,weight_map_t()))); + } + + { + 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()))); } { weight_map_t weights; insert( weights )(make_pair("a","b"),0.0) - (make_pair("c","d"),7.7)(make_pair("e","f"),6.66); - gs_t gs("digraph { a -> b edge [weight = 7.7] " - "c -> d e-> f [weight = 6.66] }"); - BOOST_CHECK((test_graph(gs,mass_map_t(),weights))); + (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]}"); + BOOST_CHECK((test_graph(gs,6,mass_map_t(),weights))); } // undirected graph with alternate node_id property name @@ -156,7 +166,7 @@ int test_main(int, char*[]) { 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,masses,weight_map_t(), + BOOST_CHECK((test_graph(gs,3,masses,weight_map_t(), "nodenames"))); } @@ -165,7 +175,7 @@ int test_main(int, char*[]) { 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,masses,weight_map_t()))); + BOOST_CHECK((test_graph(gs,3,masses,weight_map_t()))); } { @@ -174,7 +184,7 @@ int test_main(int, char*[]) { (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,mass_map_t(),weights))); + BOOST_CHECK((test_graph(gs,6,mass_map_t(),weights))); } // Mismatch directed graph test @@ -183,7 +193,7 @@ int test_main(int, char*[]) { 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,masses,weight_map_t()); + test_graph(gs,3,masses,weight_map_t()); BOOST_ERROR("Failed to throw boost::directed_graph_error."); } catch (boost::undirected_graph_error&) {} } @@ -194,7 +204,7 @@ int test_main(int, char*[]) { 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,masses,weight_map_t()); + test_graph(gs,3,masses,weight_map_t()); BOOST_ERROR("Failed to throw boost::directed_graph_error."); } catch (boost::directed_graph_error&) {} } @@ -205,7 +215,7 @@ int test_main(int, char*[]) { 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,mass_map_t(),weights); + test_graph(gs,2,mass_map_t(),weights); BOOST_ERROR("Failed to throw boost::bad_parallel_edge."); } catch (boost::bad_parallel_edge&) {} } @@ -215,16 +225,16 @@ int test_main(int, char*[]) { 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,mass_map_t(),weights))); + BOOST_CHECK((test_graph(gs,2,mass_map_t(),weights))); } // Graph Property Test 1 { mass_map_t masses; insert ( masses ) ("a",0.0f) ("c",0.0f) ("e", 6.66f); - gs_t gs("digraph { graph [name=\"foo\"] a c e [mass = 6.66] }"); - std::string graph_name("foo"); - BOOST_CHECK((test_graph(gs,masses,weight_map_t(),"", + 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))); } @@ -232,9 +242,9 @@ int test_main(int, char*[]) { { mass_map_t masses; insert ( masses ) ("a",0.0f) ("c",0.0f) ("e", 6.66f); - gs_t gs("digraph { name=\"foo\" a c e [mass = 6.66] }"); + gs_t gs("digraph { name=\"fo\"+ \"\\\no\" a c e [mass = 6.66] }"); std::string graph_name("foo"); - BOOST_CHECK((test_graph(gs,masses,weight_map_t(),"", + BOOST_CHECK((test_graph(gs,3,masses,weight_map_t(),"", graph_name))); } @@ -246,7 +256,7 @@ int test_main(int, char*[]) { "a1 [ label = \"//depot/path/to/file_29#9\" ];" "a0 -> a1 [ color=gray ];" "}"); - BOOST_CHECK((test_graph(gs,mass_map_t(),weight_map_t()))); + BOOST_CHECK((test_graph(gs,2,mass_map_t(),weight_map_t()))); } return 0; } From 92e58bf5ebd587fd887c0d741e4804de91aa0bba Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Mon, 18 May 2009 17:30:27 +0000 Subject: [PATCH 178/224] Changed names of some property maps to match code; fixes #2320 [SVN r53093] --- doc/kolmogorov_max_flow.html | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/doc/kolmogorov_max_flow.html b/doc/kolmogorov_max_flow.html index 87c293be..d5437ac7 100644 --- a/doc/kolmogorov_max_flow.html +++ b/doc/kolmogorov_max_flow.html @@ -227,14 +227,14 @@ must also be in the graph.
    The sink vertex for the flow network graph.

    Named Parameters

    -

    IN: capacity_map(EdgeCapacityMap cap) +

    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: residual_capacity_map(ResidualCapacityEdgeMap res) +

    OUT: edge_residual_capacity(ResidualCapacityEdgeMap res)

    The edge residual capacity property map. The type must be a model of a mutable Lvalue @@ -242,7 +242,7 @@ 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) +

    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 @@ -275,7 +275,7 @@ algorithm. The map must be a model of mutable Date: Wed, 20 May 2009 14:41:03 +0000 Subject: [PATCH 183/224] Added copyright/licence. [SVN r53129] --- example/labeled_graph.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/example/labeled_graph.cpp b/example/labeled_graph.cpp index d03d633b..b1d8c243 100644 --- a/example/labeled_graph.cpp +++ b/example/labeled_graph.cpp @@ -1,4 +1,8 @@ -#include "typestr.hpp" +// (C) Copyright 2009 Andrew Sutton +// +// 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 #include From 72769b9017c2fb0c83bdd0baae74634325db932f Mon Sep 17 00:00:00 2001 From: Andrew Sutton Date: Wed, 20 May 2009 16:05:05 +0000 Subject: [PATCH 184/224] Whitespace and commenting. Added mutability traits to subgraph. [SVN r53133] --- include/boost/graph/graph_mutability_traits.hpp | 2 +- include/boost/graph/labeled_graph.hpp | 4 +++- include/boost/graph/subgraph.hpp | 15 ++++++++++++--- 3 files changed, 16 insertions(+), 5 deletions(-) diff --git a/include/boost/graph/graph_mutability_traits.hpp b/include/boost/graph/graph_mutability_traits.hpp index f167271a..93cfa16e 100644 --- a/include/boost/graph/graph_mutability_traits.hpp +++ b/include/boost/graph/graph_mutability_traits.hpp @@ -240,4 +240,4 @@ struct graph_mutability_traits { } // namespace boost -#endif \ No newline at end of file +#endif diff --git a/include/boost/graph/labeled_graph.hpp b/include/boost/graph/labeled_graph.hpp index 349bb81a..c7f40260 100644 --- a/include/boost/graph/labeled_graph.hpp +++ b/include/boost/graph/labeled_graph.hpp @@ -775,7 +775,9 @@ remove_edge_by_label(typename LABELED_GRAPH::label_type const& u, /** @name Labeled Mutable Graph * The labeled mutable graph hides the add_ and remove_ vertex functions from - * the mutable graph concept. + * the mutable graph concept. Note that the remove_vertex is hidden because + * removing the vertex without its key could leave a dangling reference in + * the map. */ //@{ template diff --git a/include/boost/graph/subgraph.hpp b/include/boost/graph/subgraph.hpp index 8e301108..be28ddab 100644 --- a/include/boost/graph/subgraph.hpp +++ b/include/boost/graph/subgraph.hpp @@ -237,7 +237,7 @@ namespace boost { template typename graph::detail::bundled_result::type& operator[](Descriptor x) - { + { if (m_parent == 0) return m_graph[x]; else return root().m_graph[local_to_global(x)]; } @@ -245,7 +245,7 @@ namespace boost { template typename graph::detail::bundled_result::type const& operator[](Descriptor x) const - { + { if (m_parent == 0) return m_graph[x]; else return root().m_graph[local_to_global(x)]; } @@ -254,7 +254,7 @@ namespace boost { // private: typedef typename property_map::type EdgeIndexMap; typedef typename property_traits::value_type edge_index_type; - BOOST_STATIC_ASSERT((!is_same::value)); Graph m_graph; @@ -885,6 +885,15 @@ namespace boost { return vertex(n, g.m_graph); } + //=========================================================================== + // Mutability Traits + // Just pull the mutability traits form the underlying graph. Note that this + // will probably fail (badly) for labeled graphs. + template + struct graph_mutability_traits< subgraph > { + typedef typename graph_mutability_traits::category category; + }; + } // namespace boost #endif // BOOST_SUBGRAPH_HPP From 6fd494aec257e6fb1860bc6903cbdd45b3f5b94d Mon Sep 17 00:00:00 2001 From: Andrew Sutton Date: Wed, 20 May 2009 16:06:13 +0000 Subject: [PATCH 185/224] Added a test to verify a bug from Dmitry Bufistov. Built in some output to help debug the graph testing framework. [SVN r53134] --- test/Jamfile.v2 | 1 + test/read_propmap.cpp | 30 ++++++++++++++++++++++++++++++ test/test_construction.hpp | 4 ++++ test/test_destruction.hpp | 4 ++++ test/test_direction.hpp | 3 +++ test/test_graph.hpp | 2 ++ test/test_graphs.cpp | 9 +++++++++ test/test_iteration.hpp | 2 ++ test/test_properties.hpp | 2 ++ 9 files changed, 57 insertions(+) create mode 100644 test/read_propmap.cpp diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index dc7f52fa..e87f7a9e 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -112,6 +112,7 @@ test-suite graph_test : [ run eccentricity.cpp ] [ run clustering_coefficient.cpp ] [ run core_numbers_test.cpp ] + [ run read_propmap.cpp ] $(optional_tests) ; diff --git a/test/read_propmap.cpp b/test/read_propmap.cpp new file mode 100644 index 00000000..3c0aa69a --- /dev/null +++ b/test/read_propmap.cpp @@ -0,0 +1,30 @@ +// (C) Copyright 2009 Dmitry Bufistov, Andrew Sutton +// +// 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 +#include + +// Test contributed by Dmitry that validates a read-only property map bug +// for bundled properties. +// TODO: Integrate this into a testing framework. + +using namespace boost; + +struct EdgeProp +{ + double weight; +}; + +typedef adjacency_list graph_t; +int main() +{ + typedef property_map::type WeightMap; + typedef property_map::const_type cWeightMap; + typedef graph_traits::edge_descriptor Edge; + function_requires >(); + function_requires >(); + return 0; +} diff --git a/test/test_construction.hpp b/test/test_construction.hpp index 03276848..312bf49b 100644 --- a/test/test_construction.hpp +++ b/test/test_construction.hpp @@ -24,6 +24,7 @@ void build_graph(Graph& g, Add, Label) // This matches MutableGraph, so just add some vertices. template void build_graph(Graph& g, boost::mpl::true_, boost::mpl::false_) { + std::cout << "...build_normal\n"; for(std::size_t i = 0; i < N; ++i) { boost::add_vertex(g); } @@ -32,6 +33,7 @@ void build_graph(Graph& g, boost::mpl::true_, boost::mpl::false_) { // This will match labeled graphs. template void build_graph(Graph& g, boost::mpl::false_, boost::mpl::true_) { + std::cout << "...build_labeled\n"; // Add each vertex labeled with the number i. for(std::size_t i = 0; i < N; ++i) { boost::add_vertex(i, g); @@ -50,6 +52,7 @@ void build_graph(Graph& g, boost::mpl::false_, boost::mpl::true_) { //@{ template void connect_graph(Graph& g, VertexSet const& verts, boost::mpl::false_) { + std::cout << "...connect_normal\n"; Pair *f, *l; for(boost::tie(f, l) = edge_pairs(); f != l; ++f) { Pair const& e = *f; @@ -63,6 +66,7 @@ void connect_graph(Graph& g, VertexSet const& verts, boost::mpl::false_) { template void connect_graph(Graph& g, VertexSet const& verts, boost::mpl::true_) { + std::cout << "...connect_labeled\n"; // With labeled graphs, we want to operate directly on the edge numbers // rather than looking up the correct vertex index. This is because the // vertices are already mapped to indices. diff --git a/test/test_destruction.hpp b/test/test_destruction.hpp index 9668d979..0d28ab4b 100644 --- a/test/test_destruction.hpp +++ b/test/test_destruction.hpp @@ -21,6 +21,7 @@ void destroy_graph(Graph& g, VertexSet const& verts, Remove, Label) // This matches MutableGraph, so just remove a vertex and then clear. template void destroy_graph(Graph& g, VertexSet const& verts, boost::mpl::true_, boost::mpl::false_) { + std::cout << "...destroy_normal\n"; // Remove the roof vertex boost::remove_vertex(verts[0], g); BOOST_ASSERT(boost::num_vertices(g) == N - 1); @@ -29,6 +30,7 @@ void destroy_graph(Graph& g, VertexSet const& verts, boost::mpl::true_, boost::m // This will match labeled graphs. template void destroy_graph(Graph& g, VertexSet const& verts, boost::mpl::false_, boost::mpl::true_) { + std::cout << "...destroy_labeled\n"; // Remove the roof vertex boost::remove_vertex(0, g); BOOST_ASSERT(boost::num_vertices(g) == N - 1); @@ -48,6 +50,7 @@ void destroy_graph(Graph& g, VertexSet const& verts, boost::mpl::false_, boost:: template void disconnect_graph(Graph& g, VertexSet const& verts, boost::mpl::false_) { + std::cout << "...disconnect_normal\n"; typedef typename boost::graph_traits::edge_descriptor Edge; // Disconnect the "lollipop" from the house. @@ -70,6 +73,7 @@ void disconnect_graph(Graph& g, VertexSet const& verts, boost::mpl::false_) { template void disconnect_graph(Graph& g, VertexSet const& verts, boost::mpl::true_) { + std::cout << "...disconnect_labeled\n"; typedef typename boost::graph_traits::edge_descriptor Edge; // Disconnect the "lollipop" from the house. diff --git a/test/test_direction.hpp b/test/test_direction.hpp index b572fef4..56b1ef11 100644 --- a/test/test_direction.hpp +++ b/test/test_direction.hpp @@ -16,6 +16,7 @@ //@{ template void test_outdirected_graph(Graph const& g, VertexSet const& verts, boost::mpl::true_) { + std::cout << "...test_outdirected_graph\n"; typedef typename boost::graph_traits::out_edge_iterator OutIter; typedef std::pair OutRange; typedef std::vector OutSet; @@ -55,6 +56,7 @@ void test_outdirected_graph(Graph const& g, VertexSet const& verts, boost::mpl:: //@{ template void test_indirected_graph(Graph const& g, VertexSet const& verts, boost::mpl::true_) { + std::cout << "...test_indirected_graph\n"; typedef typename boost::graph_traits::in_edge_iterator InIter; typedef std::pair InRange; typedef std::vector InSet; @@ -89,6 +91,7 @@ void test_indirected_graph(Graph const& g, VertexSet const& verts, boost::mpl::f */ template void test_undirected_graph(Graph const& g, VertexSet const& verts, boost::mpl::true_) { + std::cout << "...test_undirected_graph\n"; typedef typename boost::graph_traits::out_edge_iterator OutIter; typedef std::pair OutRange; typedef std::vector OutSet; diff --git a/test/test_graph.hpp b/test/test_graph.hpp index c35acdb8..1ba9c8ca 100644 --- a/test/test_graph.hpp +++ b/test/test_graph.hpp @@ -87,6 +87,8 @@ struct EdgeBundle { template void test_graph(Graph& g) { + std::cout << typestr(g) << "\n"; + // Define a bunch of tags for the graph. typename boost::graph_has_add_vertex::type can_add_vertex; typename boost::graph_has_remove_vertex::type can_remove_vertex; diff --git a/test/test_graphs.cpp b/test/test_graphs.cpp index 1ee5b65c..96e84afd 100644 --- a/test/test_graphs.cpp +++ b/test/test_graphs.cpp @@ -13,6 +13,7 @@ #include #include #include +#include #include "test_graph.hpp" @@ -148,5 +149,13 @@ int main() Graph g; test_graph(g); } + { + // Make srue that subgraph obeys the basi + typedef property EdgeProp; + typedef adjacency_list BaseGraph; + typedef subgraph Graph; + Graph g; + test_graph(g); + } } diff --git a/test/test_iteration.hpp b/test/test_iteration.hpp index c048ed6f..b005830d 100644 --- a/test/test_iteration.hpp +++ b/test/test_iteration.hpp @@ -16,6 +16,7 @@ //@{ template void test_vertex_list_graph(Graph const& g) { + std::cout << "...test_vertex_list_graph\n"; typedef typename boost::graph_traits::vertex_iterator Iterator; typedef std::pair Range; @@ -33,6 +34,7 @@ void test_vertex_list_graph(Graph const& g) { //@{ template void test_edge_list_graph(Graph const& g) { + std::cout << "...test_edge_list_graph\n"; typedef typename boost::graph_traits::edge_iterator Iterator; typedef std::pair Range; diff --git a/test/test_properties.hpp b/test/test_properties.hpp index 9d289e5f..3da4c654 100644 --- a/test/test_properties.hpp +++ b/test/test_properties.hpp @@ -14,6 +14,7 @@ //@{ template void test_vertex_bundle(Graph& g, VertexSet const& verts, boost::mpl::true_) { + std::cout << "...test_vertex_bundle\n"; typedef typename boost::graph_traits::vertex_descriptor Vertex; // This just has to compile. You can't actually get this map. @@ -44,6 +45,7 @@ void test_vertex_bundle(Graph&, VertexSet const&, boost::mpl::false_) //@{ template void test_edge_bundle(Graph& g, VertexSet const& verts, boost::mpl::true_) { + std::cout << "...test_edge_bundle\n"; // This just has to compile. You can't actually get this map. typedef typename boost::graph_traits::edge_descriptor Edge; typedef typename boost::property_map::type TestMap; From 5080ba19dfa88a5205150d7aeb0499e32bc393d9 Mon Sep 17 00:00:00 2001 From: Andrew Sutton Date: Wed, 20 May 2009 16:54:46 +0000 Subject: [PATCH 186/224] Added concept checks to the interface testing harness. [SVN r53135] --- test/test_construction.hpp | 36 ++++++++++++++++++++++-------- test/test_destruction.hpp | 42 ++++++++++++++++++++++++----------- test/test_direction.hpp | 45 +++++++++++++++++++++++--------------- test/test_graph.hpp | 20 ++++++++++------- test/test_graphs.cpp | 3 +-- test/test_iteration.hpp | 12 +++++++--- test/test_properties.hpp | 31 +++++++++++++++++++------- 7 files changed, 128 insertions(+), 61 deletions(-) diff --git a/test/test_construction.hpp b/test/test_construction.hpp index 312bf49b..07a4d7ab 100644 --- a/test/test_construction.hpp +++ b/test/test_construction.hpp @@ -24,20 +24,30 @@ void build_graph(Graph& g, Add, Label) // This matches MutableGraph, so just add some vertices. template void build_graph(Graph& g, boost::mpl::true_, boost::mpl::false_) { + using namespace boost; + BOOST_CONCEPT_ASSERT((VertexListGraphConcept)); + BOOST_CONCEPT_ASSERT((VertexMutableGraphConcept)); + std::cout << "...build_normal\n"; for(std::size_t i = 0; i < N; ++i) { - boost::add_vertex(g); + add_vertex(g); } + BOOST_ASSERT(num_vertices(g) == N); } // This will match labeled graphs. template void build_graph(Graph& g, boost::mpl::false_, boost::mpl::true_) { + using namespace boost; + BOOST_CONCEPT_ASSERT((VertexListGraphConcept)); + // BOOST_CONCEPT_ASSERT((VertexMutableGraphConcept)); + std::cout << "...build_labeled\n"; // Add each vertex labeled with the number i. for(std::size_t i = 0; i < N; ++i) { - boost::add_vertex(i, g); + add_vertex(i, g); } + BOOST_ASSERT(num_vertices(g) == N); } //@} @@ -52,20 +62,28 @@ void build_graph(Graph& g, boost::mpl::false_, boost::mpl::true_) { //@{ template void connect_graph(Graph& g, VertexSet const& verts, boost::mpl::false_) { + using namespace boost; + BOOST_CONCEPT_ASSERT((AdjacencyMatrixConcept)); + BOOST_CONCEPT_ASSERT((EdgeMutableGraphConcept)); + std::cout << "...connect_normal\n"; Pair *f, *l; - for(boost::tie(f, l) = edge_pairs(); f != l; ++f) { + for(tie(f, l) = edge_pairs(); f != l; ++f) { Pair const& e = *f; - boost::add_edge(verts[e.first], verts[e.second], g); + add_edge(verts[e.first], verts[e.second], g); } // Is the lollipop connected? Is the lollipop not connected to the roof? - BOOST_ASSERT(boost::edge(verts[5], verts[3], g).second == true); - BOOST_ASSERT(boost::edge(verts[5], verts[0], g).second == false); + BOOST_ASSERT(edge(verts[5], verts[3], g).second == true); + BOOST_ASSERT(edge(verts[5], verts[0], g).second == false); } template void connect_graph(Graph& g, VertexSet const& verts, boost::mpl::true_) { + using namespace boost; + BOOST_CONCEPT_ASSERT((AdjacencyMatrixConcept)); + // BOOST_CONCEPT_ASSERT((EdgeMutableGraphConcept)); + std::cout << "...connect_labeled\n"; // With labeled graphs, we want to operate directly on the edge numbers // rather than looking up the correct vertex index. This is because the @@ -73,12 +91,12 @@ void connect_graph(Graph& g, VertexSet const& verts, boost::mpl::true_) { Pair* p = edge_pairs().first; for(std::size_t i = 0; i < M; ++i) { Pair const& e = p[i]; - boost::add_edge_by_label(e.first, e.second, g); + add_edge_by_label(e.first, e.second, g); } // Is the lollipop connected? - BOOST_ASSERT(boost::edge_by_label(5, 3, g).second == true); - BOOST_ASSERT(boost::edge_by_label(5, 0, g).second == false); + BOOST_ASSERT(edge_by_label(5, 3, g).second == true); + BOOST_ASSERT(edge_by_label(5, 0, g).second == false); } //@} diff --git a/test/test_destruction.hpp b/test/test_destruction.hpp index 0d28ab4b..96df5866 100644 --- a/test/test_destruction.hpp +++ b/test/test_destruction.hpp @@ -21,19 +21,27 @@ void destroy_graph(Graph& g, VertexSet const& verts, Remove, Label) // This matches MutableGraph, so just remove a vertex and then clear. template void destroy_graph(Graph& g, VertexSet const& verts, boost::mpl::true_, boost::mpl::false_) { + using namespace boost; + BOOST_CONCEPT_ASSERT((VertexListGraphConcept)); + BOOST_CONCEPT_ASSERT((VertexMutableGraphConcept)); + std::cout << "...destroy_normal\n"; // Remove the roof vertex - boost::remove_vertex(verts[0], g); - BOOST_ASSERT(boost::num_vertices(g) == N - 1); + remove_vertex(verts[0], g); + BOOST_ASSERT(num_vertices(g) == N - 1); } // This will match labeled graphs. template void destroy_graph(Graph& g, VertexSet const& verts, boost::mpl::false_, boost::mpl::true_) { + using namespace boost; + BOOST_CONCEPT_ASSERT((VertexListGraphConcept)); + // function_requires< VeretexMutableGraphConcept >(); + std::cout << "...destroy_labeled\n"; // Remove the roof vertex - boost::remove_vertex(0, g); - BOOST_ASSERT(boost::num_vertices(g) == N - 1); + remove_vertex(0, g); + BOOST_ASSERT(num_vertices(g) == N - 1); } //@} @@ -50,29 +58,37 @@ void destroy_graph(Graph& g, VertexSet const& verts, boost::mpl::false_, boost:: template void disconnect_graph(Graph& g, VertexSet const& verts, boost::mpl::false_) { + using namespace boost; + BOOST_CONCEPT_ASSERT((EdgeListGraphConcept)); + BOOST_CONCEPT_ASSERT((EdgeMutableGraphConcept)); + std::cout << "...disconnect_normal\n"; - typedef typename boost::graph_traits::edge_descriptor Edge; + typedef typename graph_traits::edge_descriptor Edge; // Disconnect the "lollipop" from the house. - Edge e = boost::edge(verts[5], verts[3], g).first; - boost::remove_edge(e, g); - BOOST_ASSERT(boost::num_edges(g) == M - 1); + Edge e = edge(verts[5], verts[3], g).first; + remove_edge(e, g); + BOOST_ASSERT(num_edges(g) == M - 1); // Remove the "floor" edge from the house. - boost::remove_edge(verts[3], verts[2], g); - BOOST_ASSERT(boost::num_edges(g) == M - 2); + remove_edge(verts[3], verts[2], g); + BOOST_ASSERT(num_edges(g) == M - 2); // Fully disconnect the roof vertex. clear_vertex(verts[0], g); - BOOST_ASSERT(boost::num_edges(g) == M - 4); + BOOST_ASSERT(num_edges(g) == M - 4); // What happens if we try to remove an edge that doesn't exist? - boost::remove_edge(verts[5], verts[0], g); - BOOST_ASSERT(boost::num_edges(g) == M - 4); + remove_edge(verts[5], verts[0], g); + BOOST_ASSERT(num_edges(g) == M - 4); } template void disconnect_graph(Graph& g, VertexSet const& verts, boost::mpl::true_) { + using namespace boost; + BOOST_CONCEPT_ASSERT((EdgeListGraphConcept)); + // BOOST_CONCEPT_ASSERT((EdgeMutableGraphConcept)); + std::cout << "...disconnect_labeled\n"; typedef typename boost::graph_traits::edge_descriptor Edge; diff --git a/test/test_direction.hpp b/test/test_direction.hpp index 56b1ef11..fb84b90a 100644 --- a/test/test_direction.hpp +++ b/test/test_direction.hpp @@ -16,23 +16,26 @@ //@{ template void test_outdirected_graph(Graph const& g, VertexSet const& verts, boost::mpl::true_) { + using namespace boost; + BOOST_CONCEPT_ASSERT((IncidenceGraphConcept)); + std::cout << "...test_outdirected_graph\n"; - typedef typename boost::graph_traits::out_edge_iterator OutIter; + typedef typename graph_traits::out_edge_iterator OutIter; typedef std::pair OutRange; typedef std::vector OutSet; // Collect all of the out edge ranges from the graph. OutSet outs(verts.size()); for(size_t i = 0; i < verts.size(); ++i) { - outs[i] = boost::out_edges(verts[i], g); + outs[i] = out_edges(verts[i], g); } - BOOST_ASSERT(boost::distance(outs[0]) == 0); - BOOST_ASSERT(boost::distance(outs[1]) == 1); - BOOST_ASSERT(boost::distance(outs[2]) == 1); - BOOST_ASSERT(boost::distance(outs[3]) == 2); - BOOST_ASSERT(boost::distance(outs[4]) == 2); - BOOST_ASSERT(boost::distance(outs[5]) == 1); + BOOST_ASSERT(distance(outs[0]) == 0); + BOOST_ASSERT(distance(outs[1]) == 1); + BOOST_ASSERT(distance(outs[2]) == 1); + BOOST_ASSERT(distance(outs[3]) == 2); + BOOST_ASSERT(distance(outs[4]) == 2); + BOOST_ASSERT(distance(outs[5]) == 1); // Verify that the edges are actually correct. // TODO: Find a better way of testing connectivity with multiple edges. @@ -56,15 +59,18 @@ void test_outdirected_graph(Graph const& g, VertexSet const& verts, boost::mpl:: //@{ template void test_indirected_graph(Graph const& g, VertexSet const& verts, boost::mpl::true_) { + using namespace boost; + BOOST_CONCEPT_ASSERT((BidirectionalGraphConcept)); + std::cout << "...test_indirected_graph\n"; - typedef typename boost::graph_traits::in_edge_iterator InIter; + typedef typename graph_traits::in_edge_iterator InIter; typedef std::pair InRange; typedef std::vector InSet; // Collect all of the in edges from the graph. InSet ins(verts.size()); for(size_t i = 0; i < verts.size(); ++i) { - ins[i] = boost::in_edges(verts[i], g); + ins[i] = in_edges(verts[i], g); } BOOST_ASSERT(distance(ins[0]) == 2); @@ -91,25 +97,28 @@ void test_indirected_graph(Graph const& g, VertexSet const& verts, boost::mpl::f */ template void test_undirected_graph(Graph const& g, VertexSet const& verts, boost::mpl::true_) { + using namespace boost; + BOOST_CONCEPT_ASSERT((IncidenceGraphConcept)); + std::cout << "...test_undirected_graph\n"; - typedef typename boost::graph_traits::out_edge_iterator OutIter; + typedef typename graph_traits::out_edge_iterator OutIter; typedef std::pair OutRange; typedef std::vector OutSet; // The set of out edges is the same as the set of incident edges. OutSet outs(verts.size()); for(size_t i = 0; i < verts.size(); ++i) { - outs[i] = boost::out_edges(verts[i], g); + outs[i] = out_edges(verts[i], g); } // TODO: Actually test the end connections to ensure that these are // definitely correct. - BOOST_ASSERT(boost::distance(outs[0]) == 2); - BOOST_ASSERT(boost::distance(outs[1]) == 3); - BOOST_ASSERT(boost::distance(outs[2]) == 2); - BOOST_ASSERT(boost::distance(outs[3]) == 3); - BOOST_ASSERT(boost::distance(outs[4]) == 3); - BOOST_ASSERT(boost::distance(outs[5]) == 1); + BOOST_ASSERT(distance(outs[0]) == 2); + BOOST_ASSERT(distance(outs[1]) == 3); + BOOST_ASSERT(distance(outs[2]) == 2); + BOOST_ASSERT(distance(outs[3]) == 3); + BOOST_ASSERT(distance(outs[4]) == 3); + BOOST_ASSERT(distance(outs[5]) == 1); } template diff --git a/test/test_graph.hpp b/test/test_graph.hpp index 1ba9c8ca..3be722c2 100644 --- a/test/test_graph.hpp +++ b/test/test_graph.hpp @@ -20,6 +20,7 @@ #include #include #include +#include #include "typestr.hpp" @@ -87,23 +88,26 @@ struct EdgeBundle { template void test_graph(Graph& g) { + using namespace boost; + BOOST_CONCEPT_ASSERT((GraphConcept)); + std::cout << typestr(g) << "\n"; // Define a bunch of tags for the graph. - typename boost::graph_has_add_vertex::type can_add_vertex; - typename boost::graph_has_remove_vertex::type can_remove_vertex; - typename boost::is_labeled_graph::type is_labeled; - typename boost::is_directed_unidirectional_graph::type is_directed; - typename boost::is_directed_bidirectional_graph::type is_bidirectional; - typename boost::is_undirected_graph::type is_undirected; + typename graph_has_add_vertex::type can_add_vertex; + typename graph_has_remove_vertex::type can_remove_vertex; + typename is_labeled_graph::type is_labeled; + typename is_directed_unidirectional_graph::type is_directed; + typename is_directed_bidirectional_graph::type is_bidirectional; + typename is_undirected_graph::type is_undirected; // Test constrution and vertex list. build_graph(g, can_add_vertex, is_labeled); test_vertex_list_graph(g); // Collect the vertices for an easy method of "naming" them. - typedef typename boost::graph_traits::vertex_descriptor Vertex; - typedef typename boost::graph_traits::vertex_iterator VertexIterator; + typedef typename graph_traits::vertex_descriptor Vertex; + typedef typename graph_traits::vertex_iterator VertexIterator; std::vector verts; std::pair rng = vertices(g); for( ; rng.first != rng.second; ++rng.first) { diff --git a/test/test_graphs.cpp b/test/test_graphs.cpp index 96e84afd..9e33434c 100644 --- a/test/test_graphs.cpp +++ b/test/test_graphs.cpp @@ -150,12 +150,11 @@ int main() test_graph(g); } { - // Make srue that subgraph obeys the basi typedef property EdgeProp; typedef adjacency_list BaseGraph; typedef subgraph Graph; Graph g; - test_graph(g); +// test_graph(g); } } diff --git a/test/test_iteration.hpp b/test/test_iteration.hpp index b005830d..ce48e0d7 100644 --- a/test/test_iteration.hpp +++ b/test/test_iteration.hpp @@ -16,8 +16,11 @@ //@{ template void test_vertex_list_graph(Graph const& g) { + using namespace boost; + BOOST_CONCEPT_ASSERT((VertexListGraphConcept)); + std::cout << "...test_vertex_list_graph\n"; - typedef typename boost::graph_traits::vertex_iterator Iterator; + typedef typename graph_traits::vertex_iterator Iterator; typedef std::pair Range; Range rng = vertices(g); @@ -34,12 +37,15 @@ void test_vertex_list_graph(Graph const& g) { //@{ template void test_edge_list_graph(Graph const& g) { + using namespace boost; + BOOST_CONCEPT_ASSERT((EdgeListGraphConcept)); + std::cout << "...test_edge_list_graph\n"; - typedef typename boost::graph_traits::edge_iterator Iterator; + typedef typename graph_traits::edge_iterator Iterator; typedef std::pair Range; Range rng = edges(g); - BOOST_ASSERT(boost::num_edges(g) == M); + BOOST_ASSERT(num_edges(g) == M); BOOST_ASSERT(rng.first != rng.second); BOOST_ASSERT(std::distance(rng.first, rng.second) == int(M)); } diff --git a/test/test_properties.hpp b/test/test_properties.hpp index 3da4c654..e7790bc2 100644 --- a/test/test_properties.hpp +++ b/test/test_properties.hpp @@ -14,11 +14,12 @@ //@{ template void test_vertex_bundle(Graph& g, VertexSet const& verts, boost::mpl::true_) { - std::cout << "...test_vertex_bundle\n"; - typedef typename boost::graph_traits::vertex_descriptor Vertex; + using namespace boost; + BOOST_CONCEPT_ASSERT((GraphConcept)); + typedef typename graph_traits::vertex_descriptor Vertex; + BOOST_CONCEPT_ASSERT((PropertyGraphConcept)); - // This just has to compile. You can't actually get this map. - typedef typename boost::property_map::type TestMap; + std::cout << "...test_vertex_bundle\n"; // Test bundling via the graph object on the lollipop vertex. Vertex v = verts[5]; @@ -27,10 +28,16 @@ void test_vertex_bundle(Graph& g, VertexSet const& verts, boost::mpl::true_) { BOOST_ASSERT(g[v].value == 10); // Test bundling via the property map. - typedef typename boost::property_map::type BundleMap; + typedef typename property_map::type BundleMap; + BOOST_CONCEPT_ASSERT((ReadWritePropertyMapConcept)); BundleMap map = get(&VertexBundle::value, g); put(map, v, 5); BOOST_ASSERT(get(map, v) == 5); + + typedef typename property_map::const_type ConstBundleMap; + BOOST_CONCEPT_ASSERT((ReadablePropertyMapConcept)); + ConstBundleMap cmap = get(&VertexBundle::value, (Graph const&)g); + BOOST_ASSERT(get(cmap, v) == 5); } template @@ -45,10 +52,12 @@ void test_vertex_bundle(Graph&, VertexSet const&, boost::mpl::false_) //@{ template void test_edge_bundle(Graph& g, VertexSet const& verts, boost::mpl::true_) { - std::cout << "...test_edge_bundle\n"; - // This just has to compile. You can't actually get this map. + using namespace boost; + BOOST_CONCEPT_ASSERT((GraphConcept)); typedef typename boost::graph_traits::edge_descriptor Edge; - typedef typename boost::property_map::type TestMap; + BOOST_CONCEPT_ASSERT((PropertyGraphConcept)); + + std::cout << "...test_edge_bundle\n"; // Test bundling via the graph object on the lollipop edge. Edge e = boost::edge(verts[5], verts[3], g).first; @@ -58,9 +67,15 @@ void test_edge_bundle(Graph& g, VertexSet const& verts, boost::mpl::true_) { // Test bundling via the property map. typedef typename boost::property_map::type BundleMap; + BOOST_CONCEPT_ASSERT((ReadWritePropertyMapConcept)); BundleMap map = get(&EdgeBundle::value, g); put(map, e, 5); BOOST_ASSERT(get(map, e) == 5); + + typedef typename boost::property_map::const_type ConstBundleMap; + BOOST_CONCEPT_ASSERT((ReadablePropertyMapConcept)); + ConstBundleMap cmap = get(&EdgeBundle::value, (Graph const&)g); + BOOST_ASSERT(get(cmap, e) == 5); } template From 00211e91359126176b99040766645a20a4fd4c7b Mon Sep 17 00:00:00 2001 From: Andrew Sutton Date: Wed, 20 May 2009 17:07:49 +0000 Subject: [PATCH 187/224] Redistributing mutability traits specializations to specific files in order to avoid unnecessary includes. [SVN r53136] --- include/boost/graph/adjacency_list.hpp | 19 +++++++++ include/boost/graph/adjacency_matrix.hpp | 12 ++++++ include/boost/graph/directed_graph.hpp | 6 +++ .../boost/graph/graph_mutability_traits.hpp | 39 ------------------- include/boost/graph/subgraph.hpp | 1 + include/boost/graph/undirected_graph.hpp | 6 +++ 6 files changed, 44 insertions(+), 39 deletions(-) diff --git a/include/boost/graph/adjacency_list.hpp b/include/boost/graph/adjacency_list.hpp index b0afceba..6ba8f435 100644 --- a/include/boost/graph/adjacency_list.hpp +++ b/include/boost/graph/adjacency_list.hpp @@ -37,6 +37,7 @@ #endif #include +#include #include #include #include @@ -606,6 +607,24 @@ namespace boost { #endif +// Mutability Traits +#define ADJLIST_PARAMS \ + typename OEL, typename VL, typename D, typename VP, typename EP, \ + typename GP, typename EL +#define ADJLIST adjacency_list +template +struct graph_mutability_traits { + typedef mutable_property_graph_tag category; +}; + +// Can't remove vertices from adjacency lists with VL==vecS +template +struct graph_mutability_traits< adjacency_list > { + typedef add_only_property_graph_tag category; +}; +#undef ADJLIST_PARAMS +#undef ADJLIST + } // namespace boost diff --git a/include/boost/graph/adjacency_matrix.hpp b/include/boost/graph/adjacency_matrix.hpp index 91b00f93..fb2b3788 100644 --- a/include/boost/graph/adjacency_matrix.hpp +++ b/include/boost/graph/adjacency_matrix.hpp @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include @@ -1279,6 +1280,17 @@ namespace boost { #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; +}; +#undef ADJMAT_PARAMS +#undef ADJMAT + + } // namespace boost #endif // BOOST_ADJACENCY_MATRIX_HPP diff --git a/include/boost/graph/directed_graph.hpp b/include/boost/graph/directed_graph.hpp index 9026bae0..43326d5f 100644 --- a/include/boost/graph/directed_graph.hpp +++ b/include/boost/graph/directed_graph.hpp @@ -667,6 +667,12 @@ inline void renumber_indices(DIRECTED_GRAPH& g) { g.renumber_indices(); } +// Mutability Traits +template +struct graph_mutability_traits { + typedef mutable_property_graph_tag category; +}; + #undef DIRECTED_GRAPH_PARAMS #undef DIRECTED_GRAPH diff --git a/include/boost/graph/graph_mutability_traits.hpp b/include/boost/graph/graph_mutability_traits.hpp index 93cfa16e..726d8d14 100644 --- a/include/boost/graph/graph_mutability_traits.hpp +++ b/include/boost/graph/graph_mutability_traits.hpp @@ -196,46 +196,7 @@ struct is_add_only_property_graph /** @name Mutability Traits Specializations */ //@{ -#define ADJLIST_PARAMS \ - typename OEL, typename VL, typename D, typename VP, typename EP, \ - typename GP, typename EL -#define ADJLIST adjacency_list -template class adjacency_list; -template -struct graph_mutability_traits { - typedef mutable_property_graph_tag category; -}; -// Never remove vertices from adjacency lists with VL==vecS -template -struct graph_mutability_traits< adjacency_list > { - typedef add_only_property_graph_tag category; -}; -#undef ADJLIST_PARAMS -#undef ADJLIST - -template class directed_graph; -template -struct graph_mutability_traits< directed_graph > { - typedef mutable_property_graph_tag category; -}; - -template class undirected_graph; -template -struct graph_mutability_traits< undirected_graph > { - typedef mutable_property_graph_tag category; -}; - -#define ADJMAT_PARAMS \ - typename D, typename VP, typename EP, typename GP, typename A -#define ADJMAT adjacency_matrix -template class adjacency_matrix; -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/subgraph.hpp b/include/boost/graph/subgraph.hpp index be28ddab..f77b55dd 100644 --- a/include/boost/graph/subgraph.hpp +++ b/include/boost/graph/subgraph.hpp @@ -18,6 +18,7 @@ #include #include #include +#include #include #include diff --git a/include/boost/graph/undirected_graph.hpp b/include/boost/graph/undirected_graph.hpp index 260b5a9a..abfa4adb 100644 --- a/include/boost/graph/undirected_graph.hpp +++ b/include/boost/graph/undirected_graph.hpp @@ -675,6 +675,12 @@ inline void renumber_indices(UNDIRECTED_GRAPH& g) { g.renumber_indices(); } +// Mutability Traits +template +struct graph_mutability_traits { + typedef mutable_property_graph_tag category; +}; + #undef UNDIRECTED_GRAPH_PARAMS #undef UNDIRECTED_GRAPH From c2b83032f87df3e27a1107c3e367ed4d7ffca82b Mon Sep 17 00:00:00 2001 From: Andrew Sutton Date: Thu, 21 May 2009 14:33:18 +0000 Subject: [PATCH 188/224] Deprecated use of graph_detail::is_same. Removed usage from visitors header, and tagged the defining file with the #warning. [SVN r53151] --- include/boost/graph/detail/is_same.hpp | 8 ++++++++ include/boost/graph/visitors.hpp | 23 +++++++++-------------- test/bron_kerbosch_all_cliques.cpp | 2 +- test/tiernan_all_cycles.cpp | 2 +- 4 files changed, 19 insertions(+), 16 deletions(-) diff --git a/include/boost/graph/detail/is_same.hpp b/include/boost/graph/detail/is_same.hpp index 8027a47a..07330d30 100644 --- a/include/boost/graph/detail/is_same.hpp +++ b/include/boost/graph/detail/is_same.hpp @@ -9,6 +9,14 @@ #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 { diff --git a/include/boost/graph/visitors.hpp b/include/boost/graph/visitors.hpp index d42a1f89..1091f101 100644 --- a/include/boost/graph/visitors.hpp +++ b/include/boost/graph/visitors.hpp @@ -15,10 +15,11 @@ #include #include +#include +#include #include #include #include -#include #if BOOST_WORKAROUND(BOOST_MSVC, < 1300) // Stay out of the way of the concept checking class @@ -82,9 +83,6 @@ namespace boost { struct on_edge_not_minimized { enum { num = detail::on_edge_not_minimized_num }; }; - struct true_tag { enum { num = true }; }; - struct false_tag { enum { num = false }; }; - //======================================================================== // base_visitor and null_visitor @@ -107,21 +105,20 @@ namespace boost { namespace detail { template - inline void - invoke_dispatch(Visitor& v, T x, Graph& g, true_tag) { + inline void invoke_dispatch(Visitor& v, T x, Graph& g, mpl::true_) { v(x, g); } + template - inline void - invoke_dispatch(Visitor&, T, Graph&, false_tag) { } + inline void invoke_dispatch(Visitor&, T, Graph&, mpl::false_) + { } } // namespace detail template inline void invoke_visitors(std::pair& vlist, T x, Graph& g, Tag tag) { typedef typename Visitor::event_filter Category; - typedef typename graph_detail::is_same::is_same_tag - IsSameTag; + typedef typename is_same::type IsSameTag; detail::invoke_dispatch(vlist.first, x, g, IsSameTag()); invoke_visitors(vlist.second, x, g, tag); } @@ -130,8 +127,7 @@ namespace boost { inline void invoke_visitors(base_visitor& vis, T x, Graph& g, Tag) { typedef typename Visitor::event_filter Category; - typedef typename graph_detail::is_same::is_same_tag - IsSameTag; + typedef typename is_same::type IsSameTag; Visitor& v = static_cast(vis); detail::invoke_dispatch(v, x, g, IsSameTag()); } @@ -140,8 +136,7 @@ namespace boost { inline void invoke_visitors(Visitor& v, T x, Graph& g, Tag) { typedef typename Visitor::event_filter Category; - typedef typename graph_detail::is_same::is_same_tag - IsSameTag; + typedef typename is_same::type IsSameTag; detail::invoke_dispatch(v, x, g, IsSameTag()); } #endif diff --git a/test/bron_kerbosch_all_cliques.cpp b/test/bron_kerbosch_all_cliques.cpp index 946f8432..aa940b90 100644 --- a/test/bron_kerbosch_all_cliques.cpp +++ b/test/bron_kerbosch_all_cliques.cpp @@ -54,7 +54,7 @@ void test() // Generate random graphs with 15 vertices and 15% probability // of edge connection. static const size_t N = 20; - static const float P = 0.1; + static const double P = 0.1; boost::minstd_rand rng; Graph g(er(rng, N, P), er(), N); diff --git a/test/tiernan_all_cycles.cpp b/test/tiernan_all_cycles.cpp index 9568ce77..c51ae295 100644 --- a/test/tiernan_all_cycles.cpp +++ b/test/tiernan_all_cycles.cpp @@ -52,7 +52,7 @@ void test() // Generate random graphs with 15 vertices and 15% probability // of edge connection. static const size_t N = 20; - static const float P = 0.1; + static const double P = 0.1; boost::minstd_rand rng; Graph g(er(rng, N, P), er(), N); From be6033bbb8b9d2184ccb132ac65bd9bd6953dc66 Mon Sep 17 00:00:00 2001 From: Andrew Sutton Date: Fri, 22 May 2009 12:50:07 +0000 Subject: [PATCH 189/224] Added overloads to subgraph to work with const bundled property map. [SVN r53174] --- include/boost/graph/directed_graph.hpp | 7 ++--- include/boost/graph/subgraph.hpp | 41 ++++++++++++++++---------- test/test_graph.hpp | 2 -- test/test_graphs.cpp | 4 ++- 4 files changed, 30 insertions(+), 24 deletions(-) diff --git a/include/boost/graph/directed_graph.hpp b/include/boost/graph/directed_graph.hpp index 43326d5f..28b085dd 100644 --- a/include/boost/graph/directed_graph.hpp +++ b/include/boost/graph/directed_graph.hpp @@ -588,8 +588,7 @@ set_property(DIRECTED_GRAPH& g, Property p, Value v) template inline typename property_map::type -get(Type Bundle::* p, DIRECTED_GRAPH& g) -{ +get(Type Bundle::* p, DIRECTED_GRAPH& g) { typedef typename property_map< DIRECTED_GRAPH, Type Bundle::* >::type return_type; @@ -598,8 +597,7 @@ get(Type Bundle::* p, DIRECTED_GRAPH& g) template inline typename property_map::const_type -get(Type Bundle::* p, DIRECTED_GRAPH const& g) -{ +get(Type Bundle::* p, DIRECTED_GRAPH const& g) { typedef typename property_map< DIRECTED_GRAPH, Type Bundle::* >::const_type return_type; @@ -613,7 +611,6 @@ inline Type get(Type Bundle::* p, DIRECTED_GRAPH const& g, Key const& 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 diff --git a/include/boost/graph/subgraph.hpp b/include/boost/graph/subgraph.hpp index f77b55dd..c26f0b7d 100644 --- a/include/boost/graph/subgraph.hpp +++ b/include/boost/graph/subgraph.hpp @@ -841,37 +841,46 @@ namespace boost { } #ifndef BOOST_GRAPH_NO_BUNDLED_PROPERTIES - template - inline - typename property_map, T Bundle::*>::type - get(T Bundle::* p, subgraph& sg) - { - typedef typename property_map, T Bundle::*>::type - result_type; - return result_type(&sg, p); - } + 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 < + typename Graph, typename Type, typename Bundle, typename Key, + typename Value> + inline void put(Type Bundle::* p, Graph& g, Key const& k, Value const& v) + { put(get(p, g), k, v); } #endif template - void - put(Property, subgraph& g, const Key& k, const Value& val) - { + void put(Property, subgraph& g, const Key& k, const Value& val) { typedef typename property_map< subgraph, Property>::type PMap; PMap pmap(&g); pmap[k] = val; } template - inline - typename graph_property::type& + inline typename graph_property::type& get_property(subgraph& g, Tag tag) { return get_property(g.m_graph, tag); } template - inline - const typename graph_property::type& + inline const typename graph_property::type& get_property(const subgraph& g, Tag tag) { return get_property(g.m_graph, tag); } diff --git a/test/test_graph.hpp b/test/test_graph.hpp index 3be722c2..2fd4c94b 100644 --- a/test/test_graph.hpp +++ b/test/test_graph.hpp @@ -22,8 +22,6 @@ #include #include -#include "typestr.hpp" - #define BOOST_META_ASSERT(x) BOOST_ASSERT(x::value) typedef std::pair Pair; diff --git a/test/test_graphs.cpp b/test/test_graphs.cpp index 9e33434c..c0de2a98 100644 --- a/test/test_graphs.cpp +++ b/test/test_graphs.cpp @@ -8,6 +8,8 @@ #define BOOST_NO_HASH +#include "typestr.hpp" + #include #include #include @@ -154,7 +156,7 @@ int main() typedef adjacency_list BaseGraph; typedef subgraph Graph; Graph g; -// test_graph(g); + test_graph(g); } } From bdf6e6c8325754c8d74c77eb75a1423463c888cc Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Fri, 22 May 2009 21:33:16 +0000 Subject: [PATCH 190/224] Fixed typos in BGL index; fixes #3063 and #3065 [SVN r53191] --- doc/index.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/index.html b/doc/index.html index 579d5856..09b9e3ae 100644 --- a/doc/index.html +++ b/doc/index.html @@ -39,7 +39,7 @@ contribution of the The BGL is the formulation of this interface.

    The BGL graph interface and graph components are generic, in the -same sense as the the Standard Template Library (STL) [2]. In the following sections, we review the role that generic programming @@ -47,7 +47,7 @@ plays in the STL and compare that to how we applied generic programming in the context of graphs.

    -Of course, if you are already are familiar with generic programming, +Of course, if you are already familiar with generic programming, please dive right in! Here's the Table of Contents. From 615f47676bbaa807115a4748794b1a2ef017f7c3 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Sat, 23 May 2009 16:22:14 +0000 Subject: [PATCH 191/224] Reduced graph sizes to decrease test run time; fixes #2308 [SVN r53210] --- test/matching_test.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/test/matching_test.cpp b/test/matching_test.cpp index d9a1f8a0..33ab683b 100644 --- a/test/matching_test.cpp +++ b/test/matching_test.cpp @@ -353,6 +353,15 @@ int test_main(int argc, char* argv[]) matching_test(10, "adjacency_list (using lists)"); matching_test(10, "adjacency_matrix"); + matching_test(20, "adjacency_list (using vectors)"); + matching_test(20, "adjacency_list (using lists)"); + matching_test(20, "adjacency_matrix"); + + matching_test(21, "adjacency_list (using vectors)"); + matching_test(21, "adjacency_list (using lists)"); + matching_test(21, "adjacency_matrix"); + +#if 0 matching_test(50, "adjacency_list (using vectors)"); matching_test(50, "adjacency_list (using lists)"); matching_test(50, "adjacency_matrix"); @@ -360,6 +369,7 @@ int test_main(int argc, char* argv[]) matching_test(51, "adjacency_list (using vectors)"); matching_test(51, "adjacency_list (using lists)"); matching_test(51, "adjacency_matrix"); +#endif return 0; } From e18f677885ab2095fd0699d1487d550a0db26b72 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Sat, 23 May 2009 17:16:20 +0000 Subject: [PATCH 192/224] Changed GraphML writer to escape strings; added test of this; fixes #2567 [SVN r53213] --- include/boost/graph/graphml.hpp | 11 +++++++---- test/graphml_test.cpp | 6 +++++- test/graphml_test.xml | 7 ++++++- 3 files changed, 18 insertions(+), 6 deletions(-) diff --git a/include/boost/graph/graphml.hpp b/include/boost/graph/graphml.hpp index 531dee32..9e367d12 100644 --- a/include/boost/graph/graphml.hpp +++ b/include/boost/graph/graphml.hpp @@ -22,6 +22,7 @@ #include #include #include +#include #include #include @@ -226,6 +227,8 @@ write_graphml(std::ostream& out, const Graph& g, VertexIndexMap vertex_index, typedef typename graph_traits::edge_descriptor edge_descriptor; typedef typename graph_traits::vertex_descriptor vertex_descriptor; + using boost::property_tree::xml_parser::encode_char_entities; + BOOST_STATIC_CONSTANT(bool, graph_is_directed = (is_convertible::value)); @@ -254,7 +257,7 @@ write_graphml(std::ostream& out, const Graph& g, VertexIndexMap vertex_index, continue; 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")) << "\"" << " attr.name=\"" << i->first << "\"" << " attr.type=\"" << type_name << "\"" @@ -272,7 +275,7 @@ write_graphml(std::ostream& out, const Graph& g, VertexIndexMap vertex_index, if (i->second->key() == typeid(Graph)) { out << " first] << "\">" - << i->second->get_string(g) << "\n"; + << encode_char_entities(i->second->get_string(g)) << "\n"; } } @@ -287,7 +290,7 @@ write_graphml(std::ostream& out, const Graph& g, VertexIndexMap vertex_index, if (i->second->key() == typeid(vertex_descriptor)) { out << " first] << "\">" - << i->second->get_string(*v) << "\n"; + << encode_char_entities(i->second->get_string(*v)) << "\n"; } } out << " \n"; @@ -308,7 +311,7 @@ write_graphml(std::ostream& out, const Graph& g, VertexIndexMap vertex_index, if (i->second->key() == typeid(edge_descriptor)) { out << " first] << "\">" - << i->second->get_string(*e) << "\n"; + << encode_char_entities(i->second->get_string(*e)) << "\n"; } } out << " \n"; diff --git a/test/graphml_test.cpp b/test/graphml_test.cpp index f321196d..a69f66d3 100644 --- a/test/graphml_test.cpp +++ b/test/graphml_test.cpp @@ -29,6 +29,7 @@ #include #include #include +#include using namespace std; using namespace boost; @@ -36,12 +37,14 @@ using namespace boost; int main(int argc, char** argv) { typedef adjacency_list, + property >, property > graph_t; graph_t g; dynamic_properties dp; dp.property("foo",get(vertex_color_t(),g)); dp.property("weight",get(edge_weight_t(),g)); + dp.property("name",get(vertex_name_t(),g)); ifstream ifile(argv[1]); read_graphml(ifile, g, dp); @@ -62,6 +65,7 @@ int main(int argc, char** argv) dynamic_properties dp2; dp2.property("foo",get(vertex_color_t(),g2)); dp2.property("weight",get(edge_weight_t(),g2)); + dp2.property("name",get(vertex_name_t(),g2)); ifile.open("graphml_test_out.xml"); read_graphml(ifile, g2, dp2); ifile.close(); diff --git a/test/graphml_test.xml b/test/graphml_test.xml index 40b43a12..f805fa23 100644 --- a/test/graphml_test.xml +++ b/test/graphml_test.xml @@ -15,6 +15,9 @@ 0.0 + + hello + @@ -23,7 +26,9 @@ 100 - + + foo< + 0 From 5279b7e7432ef7c9d0e4cf3e32dd43ed06db9b51 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Sat, 23 May 2009 17:32:43 +0000 Subject: [PATCH 193/224] Fixed typos [SVN r53216] --- doc/adjacency_matrix.html | 2 +- doc/subgraph.html | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/adjacency_matrix.html b/doc/adjacency_matrix.html index e5d5e431..7da34fc0 100644 --- a/doc/adjacency_matrix.html +++ b/doc/adjacency_matrix.html @@ -215,7 +215,7 @@ href="./MutablePropertyGraph.html">MutablePropertyGraph, and Assignable. -

    Associates Types

    +

    Associated Types


    diff --git a/doc/subgraph.html b/doc/subgraph.html index 04576332..09d07b30 100644 --- a/doc/subgraph.html +++ b/doc/subgraph.html @@ -173,7 +173,7 @@ the Graph type models VertexListGraphsubgraph<Graph>
    will also models these concepts. -

    Associates Types

    +

    Associated Types

    If the graph is the root of the subgraph tree, then the vertex and edge descriptors are both the local descriptors for the root graph, From 268d57b5f89c9c980b4951e4aa50102a3be8d473 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Sat, 23 May 2009 18:07:02 +0000 Subject: [PATCH 194/224] Added graph properties to adjacency_matrix; fixed constructors to match documentation; fixes #875 [SVN r53217] --- include/boost/graph/adjacency_matrix.hpp | 75 +++++++++++++++++++++++- test/adjacency_matrix_test.cpp | 41 +++++++++++++ 2 files changed, 114 insertions(+), 2 deletions(-) diff --git a/include/boost/graph/adjacency_matrix.hpp b/include/boost/graph/adjacency_matrix.hpp index fb2b3788..cf02a1d6 100644 --- a/include/boost/graph/adjacency_matrix.hpp +++ b/include/boost/graph/adjacency_matrix.hpp @@ -600,13 +600,52 @@ namespace boost { typedef adjacency_matrix_class_tag graph_tag; // Constructor required by MutableGraph - adjacency_matrix(vertices_size_type n_vertices) + adjacency_matrix(vertices_size_type n_vertices, + const GraphProperty& p = GraphProperty()) : m_matrix(Directed::is_directed ? (n_vertices * n_vertices) : (n_vertices * (n_vertices + 1) / 2)), m_vertex_set(0, n_vertices), m_vertex_properties(n_vertices), - m_num_edges(0) { } + m_num_edges(0), + m_property(p) { } + + template + adjacency_matrix(EdgeIterator first, + EdgeIterator last, + vertices_size_type n_vertices, + const GraphProperty& p = GraphProperty()) + : m_matrix(Directed::is_directed ? + (n_vertices * n_vertices) + : (n_vertices * (n_vertices + 1) / 2)), + m_vertex_set(0, n_vertices), + m_vertex_properties(n_vertices), + m_num_edges(0), + m_property(p) + { + for (; first != last; ++first) { + add_edge(first->first, first->second, *this); + } + } + + template + adjacency_matrix(EdgeIterator first, + EdgeIterator last, + EdgePropertyIterator ep_iter, + vertices_size_type n_vertices, + const GraphProperty& p = GraphProperty()) + : m_matrix(Directed::is_directed ? + (n_vertices * n_vertices) + : (n_vertices * (n_vertices + 1) / 2)), + m_vertex_set(0, n_vertices), + m_vertex_properties(n_vertices), + m_num_edges(0), + m_property(p) + { + for (; first != last; ++first, ++ep_iter) { + add_edge(first->first, first->second, *ep_iter, *this); + } + } #ifndef BOOST_GRAPH_NO_BUNDLED_PROPERTIES // Directly access a vertex or edge bundle @@ -650,6 +689,7 @@ namespace boost { VertexList m_vertex_set; std::vector m_vertex_properties; size_type m_num_edges; + GraphProperty m_property; }; //========================================================================= @@ -994,6 +1034,37 @@ namespace boost { remove_edge(u, *vi, g); } + //========================================================================= + // 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()); + } + + template + inline + const + typename graph_property, Tag>::type& + get_property(const adjacency_matrix& g, Tag) + { + return get_property_value(g.m_property, Tag()); + } + //========================================================================= // Vertex Property Map diff --git a/test/adjacency_matrix_test.cpp b/test/adjacency_matrix_test.cpp index a3b942a9..43c75d42 100644 --- a/test/adjacency_matrix_test.cpp +++ b/test/adjacency_matrix_test.cpp @@ -42,6 +42,12 @@ #include +#include +#include // For std::sort +#include + +#include + template void run_test() { @@ -194,6 +200,41 @@ boost::add_edge(boost::vertex(1, g1), boost::vertex(2, g1), g1); BOOST_CHECK(boost::get(index_map1, boost::target(*iei1, g1)) == boost::get(index_map2, boost::target(*iei2, g2))); } } + + // Test construction from a range of pairs + std::vector > edge_pairs_g1; + BGL_FORALL_EDGES_T(e, g1, Graph1) { + edge_pairs_g1.push_back( + std::make_pair(get(index_map1, source(e, g1)), + get(index_map1, target(e, g1)))); + } + Graph2 g3(edge_pairs_g1.begin(), edge_pairs_g1.end(), num_vertices(g1)); + BOOST_CHECK(num_vertices(g1) == num_vertices(g3)); + std::vector > edge_pairs_g3; + IndexMap2 index_map3 = boost::get(boost::vertex_index_t(), g3); + BGL_FORALL_EDGES_T(e, g3, Graph2) { + edge_pairs_g3.push_back( + std::make_pair(get(index_map3, source(e, g3)), + get(index_map3, target(e, g3)))); + } + // Normalize the edge pairs for comparison + if (boost::is_convertible::directed_category*, boost::undirected_tag*>::value || boost::is_convertible::directed_category*, boost::undirected_tag*>::value) { + for (size_t i = 0; i < edge_pairs_g1.size(); ++i) { + if (edge_pairs_g1[i].first < edge_pairs_g1[i].second) { + std::swap(edge_pairs_g1[i].first, edge_pairs_g1[i].second); + } + } + for (size_t i = 0; i < edge_pairs_g3.size(); ++i) { + if (edge_pairs_g3[i].first < edge_pairs_g3[i].second) { + std::swap(edge_pairs_g3[i].first, edge_pairs_g3[i].second); + } + } + } + std::sort(edge_pairs_g1.begin(), edge_pairs_g1.end()); + std::sort(edge_pairs_g3.begin(), edge_pairs_g3.end()); + edge_pairs_g1.erase(std::unique(edge_pairs_g1.begin(), edge_pairs_g1.end()), edge_pairs_g1.end()); + edge_pairs_g3.erase(std::unique(edge_pairs_g3.begin(), edge_pairs_g3.end()), edge_pairs_g3.end()); + BOOST_CHECK(edge_pairs_g1 == edge_pairs_g3); } template From 025ae1f7b1e4c9a0418bdc5d26921b581d4c0773 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Sat, 23 May 2009 23:30:31 +0000 Subject: [PATCH 195/224] Changed to standard Boost reference_wrapper rather than wrap_ref [SVN r53221] --- include/boost/graph/breadth_first_search.hpp | 6 ++---- include/boost/graph/named_function_params.hpp | 21 +++++++------------ include/boost/graph/neighbor_bfs.hpp | 7 +++---- 3 files changed, 12 insertions(+), 22 deletions(-) diff --git a/include/boost/graph/breadth_first_search.hpp b/include/boost/graph/breadth_first_search.hpp index d28ad3ff..1cf06cf7 100644 --- a/include/boost/graph/breadth_first_search.hpp +++ b/include/boost/graph/breadth_first_search.hpp @@ -227,10 +227,9 @@ namespace boost { typedef typename Traits::vertex_descriptor Vertex; typedef boost::queue queue_t; queue_t Q; - detail::wrap_ref Qref(Q); breadth_first_search (g, s, - choose_param(get_param(params, buffer_param_t()), Qref).ref, + choose_param(get_param(params, buffer_param_t()), boost::ref(Q)).get(), vis, color); } @@ -333,11 +332,10 @@ namespace boost { typedef typename Traits::vertex_descriptor vertex_descriptor; typedef boost::queue queue_t; queue_t Q; - detail::wrap_ref Qref(Q); breadth_first_visit (ng, s, - choose_param(get_param(params, buffer_param_t()), Qref).ref, + choose_param(get_param(params, buffer_param_t()), boost::ref(Q)).get(), choose_param(get_param(params, graph_visitor), make_bfs_visitor(null_visitor())), choose_pmap(get_param(params, vertex_color), ng, vertex_color) diff --git a/include/boost/graph/named_function_params.hpp b/include/boost/graph/named_function_params.hpp index 7dbcd8a8..95926f4a 100644 --- a/include/boost/graph/named_function_params.hpp +++ b/include/boost/graph/named_function_params.hpp @@ -11,6 +11,7 @@ #define BOOST_GRAPH_NAMED_FUNCTION_PARAMS_HPP #include +#include namespace boost { @@ -41,14 +42,6 @@ namespace boost { struct diameter_range_t { }; struct learning_constant_range_t { }; - namespace detail { - template - struct wrap_ref { - wrap_ref(T& r) : ref(r) {} - T& ref; - }; - } - template struct bgl_named_params : public Base { @@ -245,11 +238,11 @@ namespace boost { } template - bgl_named_params, buffer_param_t, self> + bgl_named_params, buffer_param_t, self> buffer(Buffer& b) const { - typedef bgl_named_params, buffer_param_t, self> + typedef bgl_named_params, buffer_param_t, self> Params; - return Params(detail::wrap_ref(b), *this); + return Params(boost::ref(b), *this); } template @@ -547,10 +540,10 @@ namespace boost { } template - bgl_named_params, buffer_param_t> + bgl_named_params, buffer_param_t> buffer(Buffer& b) { - typedef bgl_named_params, buffer_param_t> Params; - return Params(detail::wrap_ref(b)); + typedef bgl_named_params, buffer_param_t> Params; + return Params(boost::ref(b)); } template diff --git a/include/boost/graph/neighbor_bfs.hpp b/include/boost/graph/neighbor_bfs.hpp index 1c7b9782..01cfe49b 100644 --- a/include/boost/graph/neighbor_bfs.hpp +++ b/include/boost/graph/neighbor_bfs.hpp @@ -17,6 +17,7 @@ (for directed graphs only. use normal BFS for undirected graphs) */ #include +#include #include #include #include @@ -211,7 +212,6 @@ namespace boost { typedef typename Traits::vertex_descriptor Vertex; typedef boost::queue queue_t; queue_t Q; - detail::wrap_ref Qref(Q); // Initialization typedef typename property_traits::value_type ColorValue; typedef color_traits Color; @@ -222,7 +222,7 @@ namespace boost { } neighbor_bfs_impl (g, s, - choose_param(get_param(params, buffer_param_t()), Qref).ref, + choose_param(get_param(params, buffer_param_t()), boost::ref(Q)).get(), vis, color); } @@ -306,11 +306,10 @@ namespace boost { // Buffer default typedef boost::queue queue_t; queue_t Q; - detail::wrap_ref Qref(Q); detail::neighbor_bfs_impl (g, s, - choose_param(get_param(params, buffer_param_t()), Qref).ref, + choose_param(get_param(params, buffer_param_t()), boost::ref(Q)).get(), choose_param(get_param(params, graph_visitor), make_neighbor_bfs_visitor(null_visitor())), choose_pmap(get_param(params, vertex_color), g, vertex_color) From 0fe3f9f7d7e868c9bf863da3f84d8bf48b65b170 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Sun, 24 May 2009 00:31:52 +0000 Subject: [PATCH 196/224] Used macros to simplify code [SVN r53222] --- include/boost/graph/named_function_params.hpp | 698 +++--------------- 1 file changed, 83 insertions(+), 615 deletions(-) diff --git a/include/boost/graph/named_function_params.hpp b/include/boost/graph/named_function_params.hpp index 95926f4a..1dba8a68 100644 --- a/include/boost/graph/named_function_params.hpp +++ b/include/boost/graph/named_function_params.hpp @@ -42,6 +42,53 @@ namespace boost { struct diameter_range_t { }; struct learning_constant_range_t { }; +#define BOOST_BGL_DECLARE_NAMED_PARAMS \ + 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(predecessor_map, vertex_predecessor) \ + BOOST_BGL_ONE_PARAM_CREF(rank_map, vertex_rank) \ + BOOST_BGL_ONE_PARAM_CREF(root_map, vertex_root) \ + BOOST_BGL_ONE_PARAM_CREF(root_vertex, root_vertex) \ + BOOST_BGL_ONE_PARAM_CREF(edge_centrality_map, edge_centrality) \ + BOOST_BGL_ONE_PARAM_CREF(centrality_map, vertex_centrality) \ + BOOST_BGL_ONE_PARAM_CREF(color_map, vertex_color) \ + BOOST_BGL_ONE_PARAM_CREF(vertex_color_map, vertex_color) \ + BOOST_BGL_ONE_PARAM_CREF(edge_color_map, edge_color) \ + BOOST_BGL_ONE_PARAM_CREF(capacity_map, edge_capacity) \ + BOOST_BGL_ONE_PARAM_CREF(residual_capacity_map, edge_residual_capacity) \ + BOOST_BGL_ONE_PARAM_CREF(reverse_edge_map, edge_reverse) \ + BOOST_BGL_ONE_PARAM_CREF(discover_time_map, vertex_discover_time) \ + BOOST_BGL_ONE_PARAM_CREF(lowpoint_map, vertex_lowpoint) \ + BOOST_BGL_ONE_PARAM_CREF(vertex_index_map, vertex_index) \ + BOOST_BGL_ONE_PARAM_CREF(vertex_index1_map, vertex_index1) \ + BOOST_BGL_ONE_PARAM_CREF(vertex_index2_map, vertex_index2) \ + BOOST_BGL_ONE_PARAM_CREF(visitor, graph_visitor) \ + BOOST_BGL_ONE_PARAM_CREF(distance_compare, distance_compare) \ + BOOST_BGL_ONE_PARAM_CREF(distance_combine, distance_combine) \ + BOOST_BGL_ONE_PARAM_CREF(distance_inf, distance_inf) \ + BOOST_BGL_ONE_PARAM_CREF(distance_zero, distance_zero) \ + BOOST_BGL_ONE_PARAM_CREF(edge_copy, edge_copy) \ + BOOST_BGL_ONE_PARAM_CREF(vertex_copy, vertex_copy) \ + BOOST_BGL_ONE_PARAM_REF(buffer, buffer_param) \ + BOOST_BGL_ONE_PARAM_CREF(orig_to_copy, orig_to_copy) \ + BOOST_BGL_ONE_PARAM_CREF(isomorphism_map, vertex_isomorphism) \ + BOOST_BGL_ONE_PARAM_CREF(vertex_invariant, vertex_invariant) \ + BOOST_BGL_ONE_PARAM_CREF(vertex_invariant1, vertex_invariant1) \ + BOOST_BGL_ONE_PARAM_CREF(vertex_invariant2, vertex_invariant2) \ + BOOST_BGL_ONE_PARAM_CREF(vertex_max_invariant, vertex_max_invariant) \ + BOOST_BGL_ONE_PARAM_CREF(polling, polling) \ + BOOST_BGL_ONE_PARAM_CREF(lookahead, lookahead) \ + BOOST_BGL_ONE_PARAM_CREF(in_parallel, in_parallel) \ + BOOST_BGL_ONE_PARAM_CREF(displacement_map, vertex_displacement) \ + BOOST_BGL_ONE_PARAM_CREF(attractive_force, attractive_force) \ + BOOST_BGL_ONE_PARAM_CREF(repulsive_force, repulsive_force) \ + BOOST_BGL_ONE_PARAM_CREF(force_pairs, force_pairs) \ + BOOST_BGL_ONE_PARAM_CREF(cooling, cooling) \ + BOOST_BGL_ONE_PARAM_CREF(iterations, iterations) \ + BOOST_BGL_ONE_PARAM_CREF(diameter_range, diameter_range) \ + BOOST_BGL_ONE_PARAM_CREF(learning_constant_range, learning_constant_range) + template struct bgl_named_params : public Base { @@ -53,629 +100,48 @@ namespace boost { bgl_named_params(T v, const Base& b) : Base(b), m_value(v) { } T m_value; - template - bgl_named_params - weight_map(const WeightMap& pmap) const { - typedef bgl_named_params Params; - return Params(pmap, *this); - } +#define BOOST_BGL_ONE_PARAM_REF(name, key) \ + template \ + bgl_named_params, BOOST_PP_CAT(key, _t), self> \ + name(PType& p) const { \ + typedef bgl_named_params, BOOST_PP_CAT(key, _t), self> Params; \ + return Params(boost::ref(p), *this); \ + } \ - template - bgl_named_params - weight_map2(const WeightMap& pmap) const { - typedef bgl_named_params Params; - return Params(pmap, *this); - } +#define BOOST_BGL_ONE_PARAM_CREF(name, key) \ + template \ + bgl_named_params \ + name(const PType& p) const { \ + typedef bgl_named_params Params; \ + return Params(p, *this); \ + } \ - template - bgl_named_params - distance_map(const DistanceMap& pmap) const { - typedef bgl_named_params Params; - return Params(pmap, *this); - } +BOOST_BGL_DECLARE_NAMED_PARAMS - template - bgl_named_params - predecessor_map(const PredecessorMap& pmap) const { - typedef bgl_named_params - Params; - return Params(pmap, *this); - } - - template - bgl_named_params - rank_map(const RankMap& pmap) const { - typedef bgl_named_params - Params; - return Params(pmap, *this); - } - - template - bgl_named_params - root_map(const RootMap& pmap) const { - typedef bgl_named_params - Params; - return Params(pmap, *this); - } - - template - bgl_named_params - root_vertex(const Vertex& r) const { - typedef bgl_named_params Params; - return Params(r, *this); - } - - template - bgl_named_params - edge_centrality_map(const EdgeCentralityMap& r) const { - typedef bgl_named_params Params; - return Params(r, *this); - } - - template - bgl_named_params - centrality_map(const CentralityMap& r) const { - typedef bgl_named_params Params; - return Params(r, *this); - } - - template - bgl_named_params - color_map(const ColorMap& pmap) const { - typedef bgl_named_params Params; - return Params(pmap, *this); - } - - template - bgl_named_params - vertex_color_map(const ColorMap& pmap) const { - typedef bgl_named_params Params; - return Params(pmap, *this); - } - - template - bgl_named_params - edge_color_map(const ColorMap& pmap) const { - typedef bgl_named_params Params; - return Params(pmap, *this); - } - - template - bgl_named_params - capacity_map(CapacityMap pmap) { - typedef bgl_named_params Params; - return Params(pmap, *this); - } - - template - bgl_named_params - residual_capacity_map(Residual_CapacityMap pmap) { - typedef bgl_named_params - Params; - return Params(pmap, *this); - } - - template - bgl_named_params - reverse_edge_map(ReverseMap pmap) { - typedef bgl_named_params - Params; - return Params(pmap, *this); - } - - template - bgl_named_params - discover_time_map(const DiscoverTimeMap& pmap) const { - typedef bgl_named_params - Params; - return Params(pmap, *this); - } - - template - bgl_named_params - lowpoint_map(const LowPointMap& pmap) const { - typedef bgl_named_params - Params; - return Params(pmap, *this); - } - - template - bgl_named_params - vertex_index_map(const IndexMap& pmap) const { - typedef bgl_named_params Params; - return Params(pmap, *this); - } - - template - bgl_named_params - vertex_index1_map(const IndexMap& pmap) const { - typedef bgl_named_params Params; - return Params(pmap, *this); - } - - template - bgl_named_params - vertex_index2_map(const IndexMap& pmap) const { - typedef bgl_named_params Params; - return Params(pmap, *this); - } - - template - bgl_named_params - visitor(const Visitor& vis) const { - typedef bgl_named_params Params; - return Params(vis, *this); - } - - template - bgl_named_params - distance_compare(Compare cmp) const { - typedef bgl_named_params Params; - return Params(cmp, *this); - } - - template - bgl_named_params - distance_combine(Combine cmb) const { - typedef bgl_named_params Params; - return Params(cmb, *this); - } - - template - bgl_named_params - distance_inf(Init init) const { - typedef bgl_named_params Params; - return Params(init, *this); - } - - template - bgl_named_params - distance_zero(Init init) const { - typedef bgl_named_params Params; - return Params(init, *this); - } - - template - bgl_named_params, buffer_param_t, self> - buffer(Buffer& b) const { - typedef bgl_named_params, buffer_param_t, self> - Params; - return Params(boost::ref(b), *this); - } - - template - bgl_named_params - edge_copy(const Copier& c) const { - typedef bgl_named_params Params; - return Params(c, *this); - } - - template - bgl_named_params - vertex_copy(const Copier& c) const { - typedef bgl_named_params Params; - return Params(c, *this); - } - - template - bgl_named_params - orig_to_copy(const Orig2CopyMap& c) const { - typedef bgl_named_params Params; - return Params(c, *this); - } - - template - bgl_named_params - isomorphism_map(const IsoMap& c) const { - typedef bgl_named_params Params; - return Params(c, *this); - } - - template - bgl_named_params - vertex_invariant(const VertexInvar& c) const { - typedef bgl_named_params Params; - return Params(c, *this); - } - - template - bgl_named_params - vertex_invariant1(const VertexInvar& c) const { - typedef bgl_named_params Params; - return Params(c, *this); - } - - template - bgl_named_params - vertex_invariant2(const VertexInvar& c) const { - typedef bgl_named_params Params; - return Params(c, *this); - } - - template - bgl_named_params - vertex_max_invariant(const VertexMaxInvar& c) const { - typedef bgl_named_params Params; - return Params(c, *this); - } - - bgl_named_params - polling(bool b) const { - return bgl_named_params(b, *this); - } - - template - bgl_named_params - lookahead(const Tp& x) const { - return bgl_named_params(x, *this); - } - - template - bgl_named_params - in_parallel(const Tp& x) const { - return bgl_named_params(x, *this); - } - - template - bgl_named_params - displacement_map(const VertexDisplacement& c) const { - typedef bgl_named_params Params; - return Params(c, *this); - } - - template - bgl_named_params - attractive_force(const AttractiveForce& c) { - typedef bgl_named_params Params; - return Params(c, *this); - } - - template - bgl_named_params - repulsive_force(const RepulsiveForce& c) { - typedef bgl_named_params Params; - return Params(c, *this); - } - - template - bgl_named_params - force_pairs(const ForcePairs& c) { - typedef bgl_named_params Params; - return Params(c, *this); - } - - template - bgl_named_params - cooling(const Cooling& c) { - typedef bgl_named_params Params; - return Params(c, *this); - } - - template - bgl_named_params - iterations(const TP& c) { - typedef bgl_named_params Params; - return Params(c, *this); - } - - template - bgl_named_params, diameter_range_t, self> - diameter_range(const std::pair& c) { - typedef bgl_named_params, diameter_range_t, self> Params; - return Params(c, *this); - } - - template - bgl_named_params, learning_constant_range_t, self> - learning_constant_range(const std::pair& c) { - typedef bgl_named_params, learning_constant_range_t, self> - Params; - return Params(c, *this); - } +#undef BOOST_BGL_ONE_PARAM_REF +#undef BOOST_BGL_ONE_PARAM_CREF }; - template - bgl_named_params - weight_map(WeightMap pmap) { - typedef bgl_named_params Params; - return Params(pmap); - } +#define BOOST_BGL_ONE_PARAM_REF(name, key) \ + template \ + bgl_named_params, BOOST_PP_CAT(key, _t)> \ + name(PType& p) { \ + typedef bgl_named_params, BOOST_PP_CAT(key, _t)> Params; \ + return Params(boost::ref(p)); \ + } \ - template - bgl_named_params - weight_map2(WeightMap pmap) { - typedef bgl_named_params Params; - return Params(pmap); - } +#define BOOST_BGL_ONE_PARAM_CREF(name, key) \ + template \ + bgl_named_params \ + name(const PType& p) { \ + typedef bgl_named_params Params; \ + return Params(p); \ + } \ - template - bgl_named_params - distance_map(DistanceMap pmap) { - typedef bgl_named_params Params; - return Params(pmap); - } +BOOST_BGL_DECLARE_NAMED_PARAMS - template - bgl_named_params - predecessor_map(PredecessorMap pmap) { - typedef bgl_named_params Params; - return Params(pmap); - } - - template - bgl_named_params - rank_map(RankMap pmap) { - typedef bgl_named_params Params; - return Params(pmap); - } - - template - bgl_named_params - root_map(RootMap pmap) { - typedef bgl_named_params Params; - return Params(pmap); - } - - template - bgl_named_params - root_vertex(const Vertex& r) { - typedef bgl_named_params Params; - return Params(r); - } - - template - bgl_named_params - edge_centrality_map(const EdgeCentralityMap& r) { - typedef bgl_named_params Params; - return Params(r); - } - - template - bgl_named_params - centrality_map(const CentralityMap& r) { - typedef bgl_named_params Params; - return Params(r); - } - - template - bgl_named_params - color_map(ColorMap pmap) { - typedef bgl_named_params Params; - return Params(pmap); - } - - template - bgl_named_params - capacity_map(CapacityMap pmap) { - typedef bgl_named_params Params; - return Params(pmap); - } - - template - bgl_named_params - residual_capacity_map(Residual_CapacityMap pmap) { - typedef bgl_named_params - Params; - return Params(pmap); - } - - template - bgl_named_params - reverse_edge_map(ReverseMap pmap) { - typedef bgl_named_params - Params; - return Params(pmap); - } - - template - bgl_named_params - discover_time_map(DiscoverTimeMap pmap) { - typedef bgl_named_params Params; - return Params(pmap); - } - - template - bgl_named_params - lowpoint_map(LowPointMap pmap) { - typedef bgl_named_params Params; - return Params(pmap); - } - - template - bgl_named_params - vertex_index_map(IndexMap pmap) { - typedef bgl_named_params Params; - return Params(pmap); - } - - template - bgl_named_params - vertex_index1_map(const IndexMap& pmap) { - typedef bgl_named_params Params; - return Params(pmap); - } - - template - bgl_named_params - vertex_index2_map(const IndexMap& pmap) { - typedef bgl_named_params Params; - return Params(pmap); - } - - template - bgl_named_params - visitor(const Visitor& vis) { - typedef bgl_named_params Params; - return Params(vis); - } - - template - bgl_named_params - distance_compare(Compare cmp) { - typedef bgl_named_params Params; - return Params(cmp); - } - - template - bgl_named_params - distance_combine(Combine cmb) { - typedef bgl_named_params Params; - return Params(cmb); - } - - template - bgl_named_params - distance_inf(Init init) { - typedef bgl_named_params Params; - return Params(init); - } - - template - bgl_named_params - distance_zero(Init init) { - typedef bgl_named_params Params; - return Params(init); - } - - template - bgl_named_params, buffer_param_t> - buffer(Buffer& b) { - typedef bgl_named_params, buffer_param_t> Params; - return Params(boost::ref(b)); - } - - template - bgl_named_params - edge_copy(const Copier& c) { - typedef bgl_named_params Params; - return Params(c); - } - - template - bgl_named_params - vertex_copy(const Copier& c) { - typedef bgl_named_params Params; - return Params(c); - } - - template - bgl_named_params - orig_to_copy(const Orig2CopyMap& c) { - typedef bgl_named_params Params; - return Params(c); - } - - template - bgl_named_params - isomorphism_map(const IsoMap& c) { - typedef bgl_named_params Params; - return Params(c); - } - - template - bgl_named_params - vertex_invariant(const VertexInvar& c) { - typedef bgl_named_params Params; - return Params(c); - } - - template - bgl_named_params - vertex_invariant1(const VertexInvar& c) { - typedef bgl_named_params Params; - return Params(c); - } - - template - bgl_named_params - vertex_invariant2(const VertexInvar& c) { - typedef bgl_named_params Params; - return Params(c); - } - - template - bgl_named_params - vertex_max_invariant(const VertexMaxInvar& c) { - typedef bgl_named_params Params; - return Params(c); - } - - bgl_named_params - inline polling(bool b) { - return bgl_named_params(b); - } - - - template - bgl_named_params - lookahead(const T& x) { - return bgl_named_params(x); - } - - template - bgl_named_params - in_parallel(const T& x) { - return bgl_named_params(x); - } - - template - bgl_named_params - displacement_map(const VertexDisplacement& c) { - typedef bgl_named_params Params; - return Params(c); - } - - template - bgl_named_params - attractive_force(const AttractiveForce& c) { - typedef bgl_named_params Params; - return Params(c); - } - - template - bgl_named_params - repulsive_force(const RepulsiveForce& c) { - typedef bgl_named_params Params; - return Params(c); - } - - template - bgl_named_params - force_pairs(const ForcePairs& c) { - typedef bgl_named_params Params; - return Params(c); - } - - template - bgl_named_params - cooling(const Cooling& c) { - typedef bgl_named_params Params; - return Params(c); - } - - template - bgl_named_params - iterations(const T& c) { - typedef bgl_named_params Params; - return Params(c); - } - - template - bgl_named_params, diameter_range_t> - diameter_range(const std::pair& c) { - typedef bgl_named_params, diameter_range_t> Params; - return Params(c); - } - - template - bgl_named_params, learning_constant_range_t> - learning_constant_range(const std::pair& c) { - typedef bgl_named_params, learning_constant_range_t> - Params; - return Params(c); - } +#undef BOOST_BGL_ONE_PARAM_REF +#undef BOOST_BGL_ONE_PARAM_CREF namespace detail { struct unused_tag_type {}; @@ -828,4 +294,6 @@ namespace boost { } // namespace boost +#undef BOOST_BGL_DECLARE_NAMED_PARAMS + #endif // BOOST_GRAPH_NAMED_FUNCTION_PARAMS_HPP From 39eda77bb0183a1d3f2ef50994374daac727d165 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Sun, 24 May 2009 05:41:32 +0000 Subject: [PATCH 197/224] Changed to Boost.Parameter for DFS as a test but kept old interface; added a lot of helper code to make that easier [SVN r53226] --- include/boost/graph/depth_first_search.hpp | 58 +---- include/boost/graph/named_function_params.hpp | 210 +++++++++++++++++- 2 files changed, 219 insertions(+), 49 deletions(-) diff --git a/include/boost/graph/depth_first_search.hpp b/include/boost/graph/depth_first_search.hpp index 51820d7b..5e2ba34c 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 @@ -219,43 +220,6 @@ namespace boost { depth_first_search(g, vis, color, *vertices(g).first); } - namespace detail { - template - struct dfs_dispatch { - - template - static void - apply(const VertexListGraph& g, DFSVisitor vis, Vertex start_vertex, - const bgl_named_params&, - ColorMap color) - { - depth_first_search(g, vis, color, start_vertex); - } - }; - - template <> - struct dfs_dispatch { - template - static void - apply(const VertexListGraph& g, DFSVisitor vis, Vertex start_vertex, - const bgl_named_params& params, - detail::error_property_not_found) - { - std::vector color_vec(num_vertices(g)); - default_color_type c = white_color; // avoid warning about un-init - depth_first_search - (g, vis, make_iterator_property_map - (color_vec.begin(), - choose_const_pmap(get_param(params, vertex_index), - g, vertex_index), c), - start_vertex); - } - }; - } // namespace detail - - template class dfs_visitor { public: @@ -314,26 +278,24 @@ namespace boost { } typedef dfs_visitor<> default_dfs_visitor; - // Named Parameter Variant template void depth_first_search(const VertexListGraph& g, const bgl_named_params& params) { - typedef typename property_value< bgl_named_params, - vertex_color_t>::type C; if (vertices(g).first == vertices(g).second) return; - detail::dfs_dispatch::apply + using namespace boost::graph::keywords; + typedef bgl_named_params params_type; + BOOST_GRAPH_DECLARE_CONVERTED_PARAMETERS(params_type, params) + BOOST_GRAPH_MAKE_COLOR_MAP_IF_NEEDED(VertexListGraph, arg_pack_type, g, arg_pack, color_map); + depth_first_search (g, - choose_param(get_param(params, graph_visitor), - make_dfs_visitor(null_visitor())), - choose_param(get_param(params, root_vertex_t()), - *vertices(g).first), - params, - get_param(params, vertex_color) - ); + arg_pack[_visitor | make_dfs_visitor(null_visitor())], + color_map, + arg_pack[_root_vertex | *vertices(g).first] + ); } template diff --git a/include/boost/graph/named_function_params.hpp b/include/boost/graph/named_function_params.hpp index 1dba8a68..ec567efb 100644 --- a/include/boost/graph/named_function_params.hpp +++ b/include/boost/graph/named_function_params.hpp @@ -12,6 +12,12 @@ #include #include +#include +#include +#include +#include +#include +#include namespace boost { @@ -53,7 +59,6 @@ namespace boost { BOOST_BGL_ONE_PARAM_CREF(edge_centrality_map, edge_centrality) \ BOOST_BGL_ONE_PARAM_CREF(centrality_map, vertex_centrality) \ BOOST_BGL_ONE_PARAM_CREF(color_map, vertex_color) \ - BOOST_BGL_ONE_PARAM_CREF(vertex_color_map, vertex_color) \ BOOST_BGL_ONE_PARAM_CREF(edge_color_map, edge_color) \ BOOST_BGL_ONE_PARAM_CREF(capacity_map, edge_capacity) \ BOOST_BGL_ONE_PARAM_CREF(residual_capacity_map, edge_residual_capacity) \ @@ -120,6 +125,11 @@ BOOST_BGL_DECLARE_NAMED_PARAMS #undef BOOST_BGL_ONE_PARAM_REF #undef BOOST_BGL_ONE_PARAM_CREF + + // Duplicate + template + bgl_named_params + vertex_color_map(const PType& p) const {return this->color_map(p);} }; #define BOOST_BGL_ONE_PARAM_REF(name, key) \ @@ -143,6 +153,11 @@ BOOST_BGL_DECLARE_NAMED_PARAMS #undef BOOST_BGL_ONE_PARAM_REF #undef BOOST_BGL_ONE_PARAM_CREF + // Duplicate + template + bgl_named_params + vertex_color_map(const PType& p) {return color_map(p);} + namespace detail { struct unused_tag_type {}; } @@ -292,6 +307,199 @@ BOOST_BGL_DECLARE_NAMED_PARAMS return Choice::apply(p, g, tag); } + // Declare all new tags + namespace graph { + namespace keywords { +#define BOOST_BGL_ONE_PARAM_REF(name, key) BOOST_PARAMETER_NAME(name) +#define BOOST_BGL_ONE_PARAM_CREF(name, key) BOOST_PARAMETER_NAME(name) + BOOST_BGL_DECLARE_NAMED_PARAMS +#undef BOOST_BGL_ONE_PARAM_REF +#undef BOOST_BGL_ONE_PARAM_CREF + } + } + + namespace detail { + template struct convert_one_keyword {}; +#define BOOST_BGL_ONE_PARAM_REF(name, key) \ + template <> \ + struct convert_one_keyword { \ + typedef boost::graph::keywords::tag::name type; \ + }; +#define BOOST_BGL_ONE_PARAM_CREF(name, key) BOOST_BGL_ONE_PARAM_REF(name, key) + BOOST_BGL_DECLARE_NAMED_PARAMS +#undef BOOST_BGL_ONE_PARAM_REF +#undef BOOST_BGL_ONE_PARAM_CREF + + template + struct convert_bgl_params_to_boost_parameter { + typedef typename convert_one_keyword::type new_kw; + typedef boost::parameter::aux::tagged_argument tagged_arg_type; + 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)); + } + }; + + 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();} + }; + + 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();} + }; + + struct bgl_parameter_not_found_type {}; + + template + struct parameter_exists : boost::mpl::not_::type, bgl_parameter_not_found_type> > {}; + } + +#define BOOST_GRAPH_DECLARE_CONVERTED_PARAMETERS(old_type, old_var) \ + typedef typename boost::detail::convert_bgl_params_to_boost_parameter::type arg_pack_type; \ + arg_pack_type arg_pack = boost::detail::convert_bgl_params_to_boost_parameter::conv(old_var); + + namespace detail { + + template + struct override_const_property_t { + typedef ArgType result_type; + result_type operator()(const Graph& g, const typename boost::add_reference::type a) const {return a;} + }; + + template + struct override_const_property_t { + typedef typename boost::property_map::const_type result_type; + result_type operator()(const Graph& g, const ArgType& a) const {return get(Prop(), g);} + }; + + template + typename override_const_property_t< + typename boost::parameter::value_type::type, + Prop, + Graph, + boost::detail::parameter_exists::value + >::result_type + override_const_property(const ArgPack& ap, const boost::parameter::keyword& t, const Graph& g, Prop prop) { + return override_const_property_t< + typename boost::parameter::value_type::type, + Prop, + Graph, + boost::detail::parameter_exists::value + >()(g, ap[t | 0]); + } + + 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;} + }; + + 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);} + }; + + template + typename override_property_t< + typename boost::parameter::value_type::type, + Prop, + Graph, + boost::detail::parameter_exists::value + >::result_type + override_property(const ArgPack& ap, const boost::parameter::keyword& t, const Graph& g, Prop prop) { + return override_property_t< + typename boost::parameter::value_type::type, + Prop, + Graph, + boost::detail::parameter_exists::value + >()(g, ap[t | 0]); + } + + } + + namespace detail { + + template + struct color_map_maker_helper { + typedef int data_type; + typedef PM map_type; + typedef std::pair pm_pair_type; + static void make_pm_pair(const Graph&, + Value, + const PM& pm, + const ArgPack&, + pm_pair_type& result) { + result.second = pm; + } + }; + + template + struct color_map_maker_helper { + typedef typename boost::remove_const< + typename override_const_property_t< + typename boost::parameter::value_type< + ArgPack, boost::graph::keywords::tag::vertex_index_map, int>::type, + boost::vertex_index_t, + Graph, + boost::detail::parameter_exists< + ArgPack, boost::graph::keywords::tag::vertex_index_map>::value + >::result_type>::type vi_map_type; + typedef std::vector data_type; + typedef + boost::iterator_property_map + map_type; + typedef std::pair pm_pair_type; + static void make_pm_pair(const Graph& g, + Value v, + const PM&, + const ArgPack& ap, + pm_pair_type& result) { + result.first.clear(); + result.first.resize(num_vertices(g), v); + result.second = map_type( + result.first.begin(), + override_const_property( + ap, + boost::graph::keywords::_vertex_index_map, + g, vertex_index)); + } + }; + + template + struct color_map_maker { + BOOST_STATIC_CONSTANT( + bool, + has_color_map = + (parameter_exists + ::value)); + typedef color_map_maker_helper::type + >::type> helper; + typedef typename helper::map_type map_type; + typedef typename helper::pm_pair_type pm_pair_type; + static void make_pm_pair(const Graph& g, const ArgPack& ap, pm_pair_type& result) { + helper::make_pm_pair(g, white_color, ap[boost::graph::keywords::_color_map | 0], ap, result); + } + }; + +#define BOOST_GRAPH_MAKE_COLOR_MAP_IF_NEEDED(GraphT, ArgPackT, graph, arg_pack, color_map) \ + typename boost::detail::color_map_maker::pm_pair_type BOOST_PP_CAT(cm_pair_, __LINE__); \ + boost::detail::color_map_maker::make_pm_pair(graph, arg_pack, BOOST_PP_CAT(cm_pair_, __LINE__)); \ + typename boost::detail::color_map_maker::map_type& color_map = BOOST_PP_CAT(cm_pair_, __LINE__).second; + + } + } // namespace boost #undef BOOST_BGL_DECLARE_NAMED_PARAMS From 8dd497a9f10ca9d2da483d171fde2573d6896987 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Mon, 25 May 2009 05:38:56 +0000 Subject: [PATCH 198/224] Changed new GraphViz parser to be less generic (so it can be built as a binary); fixed subgraph issues by doing a lot of tests on GraphViz itself and restructuring a lot of the parser; made docs only point to new parser and made old one not build by default (although it is not removed) [SVN r53237] --- build/Jamfile.v2 | 3 +- doc/read_graphviz.html | 59 +- doc/read_graphviz.rst | 50 +- .../boost/graph/detail/read_graphviz_new.hpp | 683 +-------------- include/boost/graph/graphviz.hpp | 21 +- src/read_graphviz_new.cpp | 810 ++++++++++++++++++ 6 files changed, 934 insertions(+), 692 deletions(-) create mode 100644 src/read_graphviz_new.cpp diff --git a/build/Jamfile.v2 b/build/Jamfile.v2 index fa0deba1..eb4c4787 100644 --- a/build/Jamfile.v2 +++ b/build/Jamfile.v2 @@ -47,9 +47,10 @@ explicit graphml ; lib boost_graph : - read_graphviz_spirit.cpp + read_graphviz_new.cpp graphml : + ../../regex/build//boost_regex BOOST_GRAPH_NO_LIB=1 shared:BOOST_GRAPH_DYN_LINK=1 # # Intel compiler ICEs if we turn optimization on diff --git a/doc/read_graphviz.html b/doc/read_graphviz.html index 75dd91a9..0d392889 100644 --- a/doc/read_graphviz.html +++ b/doc/read_graphviz.html @@ -286,7 +286,7 @@ ul.auto-toc {

    Boost read_graphviz

    - @@ -298,8 +298,13 @@ namespace boost { dynamic_properties& dp, const std::string& node_id = "node_id"); - template <typename BidirectionalIterator, typename MutableGraph> - bool read_graphviz(BidirectionalIterator begin, BidirectionalIterator end, + template <typename MutableGraph> + bool read_graphviz(std::string& str, MutableGraph& graph, + dynamic_properties& dp, + const std::string& node_id = "node_id"); + + template <typename InputIterator, typename MutableGraph> + bool read_graphviz(InputIterator begin, InputIterator end, MutableGraph& graph, dynamic_properties& dp, const std::string& node_id = "node_id"); @@ -309,11 +314,6 @@ namespace boost { GraphViz DOT language and builds a BGL graph that captures that description. Using these functions, you can initialize a graph using data stored as text.

    -

    The BOOST_GRAPH_USE_SPIRIT_PARSER macro may be defined before including -<boost/graph/graphviz.hpp> to include a previous parser implementation, -with the same interface, that uses Spirit for its implementation. The main -advantage of that version is that it supports subgraphs to a limited extent, -while the new parser does not support them at all.

    The DOT language can specify both directed and undirected graphs, and read_graphviz differentiates between the two. One must pass read_graphviz an undirected graph when reading an undirected graph; @@ -325,12 +325,12 @@ takes a read_graphviz stores node identifier names under the -vertex property map named node_id.

    +vertex property map named node_id.

    Requirements:
    @@ -378,6 +378,14 @@ struct undirected_graph_error : public graph_exception { virtual ~undirected_graph_error() throw(); virtual const char* what() const throw(); }; + +struct bad_graphviz_syntax: public graph_exception { + std::string errmsg; + + bad_graphviz_syntax(const std::string&); + virtual ~bad_graphviz_syntax() throw(); + virtual const char* what() const throw(); +};

    Under certain circumstances, read_graphviz will throw one of the above exceptions. The three concrete exceptions can all be caught @@ -398,6 +406,8 @@ language.

    type is passed to read_graph but the textual representation of the graph is undirected, as indicated by the graph keyword in the DOT language.

    +

    The bad_graphviz_syntax exception occurs when the graph input is not a +valid GraphViz graph.

    Example

    @@ -446,8 +456,8 @@ bool status = read_graphviz(gvgraph,graph,dp,"node_id");

    Building the GraphViz Readers

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

    +the "boost_graph" library. The library can be built by following the +Boost Jam Build Instructions for the subdirectory libs/graph/build.

    Notes

    @@ -462,24 +472,22 @@ corner cases that are not well specified.
  • On successful reading of a graph, every vertex and edge will have an associated value for every respective edge and vertex property encountered while interpreting the graph. These values will be set -using the dynamic_properties object. Some properties may be -put multiple times during the course of reading in order to -ensure the same semantics as the GraphViz tools. Those edges and +using the dynamic_properties object. Those edges and vertices that are not explicitly given a value for a property (and that property has no default) will be given the default constructed value of the value type. Be sure that property map value types are default constructible.
  • +
  • read_graphviz treats subgraphs as syntactic sugar. It does not +reflect subgraphs as actual entities in the BGL. Rather, they are +used to shorten some edge definitions as well as to give a subset +of all nodes or edges certain properties. For example, the +DOT graphs digraph { a -> subgraph {b -> c} -> e } and +digraph { a -> b -> e ; a -> c -> e ; b -> c} are equivalent.
  • +
  • Subgraph IDs refer to subgraphs defined earlier in the graph +description. Undefined subgraphs behave as empty subgraphs +({}). This is the same behavior as GraphViz.
  • - -

    See Also

    @@ -489,15 +497,14 @@ that property map value types are default constructible.

    Future Work

      -
    • Support for subgraphs (currently parsed but ignored).
    • Support for HTML strings.
    • Passing port information to BGL.
    • Expanding escape codes in the same way GraphViz does.
    • Enforcement of the strict keyword (ignoring self-loops and parallel edges).
    • +
    • Support for optional recognition of subgraphs as distinct entities.
    -
    diff --git a/doc/read_graphviz.rst b/doc/read_graphviz.rst index b528bb7b..fa5f6281 100644 --- a/doc/read_graphviz.rst +++ b/doc/read_graphviz.rst @@ -6,7 +6,7 @@ :align: middle :alt: Boost -.. Copyright (c) 2005 Trustees of Indiana University +.. Copyright (c) 2005-2009 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) @@ -21,8 +21,13 @@ __ ../../../index.htm dynamic_properties& dp, const std::string& node_id = "node_id"); - template - bool read_graphviz(BidirectionalIterator begin, BidirectionalIterator end, + template + bool read_graphviz(std::string& str, MutableGraph& graph, + dynamic_properties& dp, + const std::string& node_id = "node_id"); + + template + bool read_graphviz(InputIterator begin, InputIterator end, MutableGraph& graph, dynamic_properties& dp, const std::string& node_id = "node_id"); @@ -34,12 +39,6 @@ GraphViz_ DOT language and builds a BGL graph that captures that description. Using these functions, you can initialize a graph using data stored as text. -The ``BOOST_GRAPH_USE_SPIRIT_PARSER`` macro may be defined before including -```` to include a previous parser implementation, -with the same interface, that uses Spirit for its implementation. The main -advantage of that version is that it supports subgraphs to a limited extent, -while the new parser does not support them at all. - The DOT language can specify both directed and undirected graphs, and ``read_graphviz`` differentiates between the two. One must pass ``read_graphviz`` an undirected graph when reading an undirected graph; @@ -52,11 +51,11 @@ takes a dynamic_properties_ object and operates on its collection of property maps. The reader passes all the properties encountered to this object, using the GraphViz string keys as the property keys. Furthermore, ``read_graphviz`` stores node identifier names under the -vertex property map named node_id. +vertex property map named ``node_id``. Requirements: - The type of the graph must model the `Mutable Graph`_ concept. - - The type of the iterator must model the `Bidirectional Iterator`_ + - The type of the iterator must model the `Input Iterator`_ concept. - The property map value types must be default-constructible. @@ -96,6 +95,14 @@ Exceptions virtual const char* what() const throw(); }; + struct bad_graphviz_syntax: public graph_exception { + std::string errmsg; + + bad_graphviz_syntax(const std::string&); + virtual ~bad_graphviz_syntax() throw(); + virtual const char* what() const throw(); + }; + Under certain circumstances, ``read_graphviz`` will throw one of the above exceptions. The three concrete exceptions can all be caught using the general ``graph_exception`` moniker when greater precision @@ -120,6 +127,10 @@ type is passed to ``read_graph`` but the textual representation of the graph is undirected, as indicated by the ``graph`` keyword in the DOT language. +The ``bad_graphviz_syntax`` exception occurs when the graph input is not a +valid GraphViz graph. + + Example ------- The following example illustrates a relatively simple use of the @@ -171,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_regex" library. The library can be built by following the -`Boost Jam Build Instructions`_ for the subdirectory ``libs/regex/build``. +the "boost_graph" library. The library can be built by following the +`Boost Jam Build Instructions`_ for the subdirectory ``libs/graph/build``. Notes @@ -188,15 +199,12 @@ Notes - On successful reading of a graph, every vertex and edge will have an associated value for every respective edge and vertex property encountered while interpreting the graph. These values will be set - using the ``dynamic_properties`` object. Some properties may be - ``put`` multiple times during the course of reading in order to - ensure the same semantics as the GraphViz tools. Those edges and + using the ``dynamic_properties`` object. Those edges and vertices that are not explicitly given a value for a property (and that property has no default) will be given the default constructed value of the value type. **Be sure that property map value types are default constructible.** -.. - ``read_graphviz`` treats subgraphs as syntactic sugar. It does not reflect subgraphs as actual entities in the BGL. Rather, they are used to shorten some edge definitions as well as to give a subset @@ -204,10 +212,9 @@ Notes DOT graphs ``digraph { a -> subgraph {b -> c} -> e }`` and ``digraph { a -> b -> e ; a -> c -> e ; b -> c}`` are equivalent. -.. - Subgraph IDs refer to subgraphs defined earlier in the graph description. Undefined subgraphs behave as empty subgraphs - (``{}``). + (``{}``). This is the same behavior as GraphViz. See Also -------- @@ -218,8 +225,6 @@ write_graphviz_ Future Work ----------- - - Support for subgraphs (currently parsed but ignored). - - Support for HTML strings. - Passing port information to BGL. @@ -229,13 +234,12 @@ Future Work - Enforcement of the ``strict`` keyword (ignoring self-loops and parallel edges). -.. - Support for optional recognition of subgraphs as distinct entities. .. _GraphViz: http://graphviz.org/ .. _`Mutable Graph`: MutableGraph.html -.. _`Bidirectional Iterator`: http://www.sgi.com/tech/stl/BidirectionalIterator.html +.. _`Input Iterator`: http://www.sgi.com/tech/stl/InputIterator.html .. _dynamic_properties: ../../property_map/doc/dynamic_property_map.html .. _write_graphviz: write-graphviz.html .. _Boost Jam Build Instructions: ../../../more/getting_started.html#Build_Install diff --git a/include/boost/graph/detail/read_graphviz_new.hpp b/include/boost/graph/detail/read_graphviz_new.hpp index 18cadc5e..215f9ef9 100644 --- a/include/boost/graph/detail/read_graphviz_new.hpp +++ b/include/boost/graph/detail/read_graphviz_new.hpp @@ -29,13 +29,10 @@ #define BOOST_READ_GRAPHVIZ_NEW_HPP #include -#include #include #include #include -#include #include -#include // for std::exception #include #include #include @@ -43,661 +40,75 @@ #include #include #include -#include -#include -#include -#include -#include namespace boost { namespace read_graphviz_detail { - struct token { - enum token_type { - kw_strict, - kw_graph, - kw_digraph, - kw_node, - kw_edge, - kw_subgraph, - left_brace, - right_brace, - semicolon, - equal, - left_bracket, - right_bracket, - comma, - colon, - dash_greater, - dash_dash, - plus, - left_paren, - right_paren, - at, - identifier, - quoted_string, // Only used internally in tokenizer - eof, - invalid - } type; - std::string normalized_value; // May have double-quotes removed and/or some escapes replaced - token(token_type type, const std::string& normalized_value) - : type(type), normalized_value(normalized_value) {} - token(): type(invalid), normalized_value("") {} - friend std::ostream& operator<<(std::ostream& o, const token& t) { - switch (t.type) { - case token::kw_strict: o << ""; break; - case token::kw_graph: o << ""; break; - case token::kw_digraph: o << ""; break; - case token::kw_node: o << ""; break; - case token::kw_edge: o << ""; break; - case token::kw_subgraph: o << ""; break; - case token::left_brace: o << ""; break; - case token::right_brace: o << ""; break; - case token::semicolon: o << ""; break; - case token::equal: o << ""; break; - case token::left_bracket: o << ""; break; - case token::right_bracket: o << ""; break; - case token::comma: o << ""; break; - case token::colon: o << ""; break; - case token::dash_greater: o << ""; break; - case token::dash_dash: o << ""; break; - case token::plus: o << ""; break; - case token::left_paren: o << ""; break; - case token::right_paren: o << ""; break; - case token::at: o << ""; break; - case token::identifier: o << ""; break; - case token::quoted_string: o << ""; break; - case token::eof: o << ""; break; - default: o << ""; break; - } - o << " '" << t.normalized_value << "'"; - return o; - } - }; - - struct lex_error: public std::exception { - std::string errmsg; - char bad_char; - lex_error(const std::string& errmsg, char bad_char): errmsg(errmsg), bad_char(bad_char) { - this->errmsg += std::string(" (char is '") + bad_char + "')"; - } - const char* what() const throw () {return errmsg.c_str();} - ~lex_error() throw () {}; - }; - - struct parse_error: public std::exception { - std::string errmsg; - token bad_token; - parse_error(const std::string& errmsg, const token& bad_token): errmsg(errmsg), bad_token(bad_token) { - this->errmsg += std::string(" (token is \"") + boost::lexical_cast(bad_token) + "\")"; - } - const char* what() const throw () {return errmsg.c_str();} - ~parse_error() throw () {}; - }; - - template - struct tokenizer { - BidirectionalIterator begin, end; - std::vector lookahead; - // Precomputed regexes - boost::regex stuff_to_skip; - boost::regex basic_id_token; - boost::regex punctuation_token; - boost::regex number_token; - boost::regex quoted_string_token; - - tokenizer(BidirectionalIterator begin, BidirectionalIterator end) - : begin(begin), end(end) - { - std::string end_of_token = "(?=(?:\\W))"; - std::string whitespace = "(?:\\s+)"; - std::string slash_slash_comment = "(?://.*$)"; - std::string slash_star_comment = "(?:/\\*.*?\\*/)"; - std::string hash_comment = "(?:^#.*?$)"; - stuff_to_skip = "\\A(?:" + whitespace + "|" + slash_slash_comment + "|" + slash_star_comment + "|" + hash_comment + ")*"; - basic_id_token = "\\A([[:alpha:]_](?:\\w*))"; - punctuation_token = "\\A([][{};=,:+()@]|[-][>-])"; - number_token = "\\A([-]?(?:(?:\\.\\d+)|(?:\\d+(?:\\.\\d*)?)))"; - quoted_string_token = "\\A(\"(?:[^\"\\\\]|(?:[\\\\].))*\")"; - } - - void skip() { - boost::match_results results; - bool found = boost::regex_search(begin, end, results, stuff_to_skip); - assert (found); - boost::sub_match sm1 = results.suffix(); - assert (sm1.second == end); - begin = sm1.first; - } - - token get_token_raw() { - if (!lookahead.empty()) { - token t = lookahead.front(); - lookahead.erase(lookahead.begin()); - return t; - } - skip(); - if (begin == end) return token(token::eof, ""); - // Look for keywords first - bool found; - boost::match_results results; - found = boost::regex_search(begin, end, results, basic_id_token); - if (found) { - std::string str = results[1].str(); - std::string str_lower = boost::algorithm::to_lower_copy(str); - begin = results.suffix().first; - if (str_lower == "strict") { - return token(token::kw_strict, str); - } else if (str_lower == "graph") { - return token(token::kw_graph, str); - } else if (str_lower == "digraph") { - return token(token::kw_digraph, str); - } else if (str_lower == "node") { - return token(token::kw_node, str); - } else if (str_lower == "edge") { - return token(token::kw_edge, str); - } else if (str_lower == "subgraph") { - return token(token::kw_subgraph, str); - } else { - return token(token::identifier, str); - } - } - found = boost::regex_search(begin, end, results, punctuation_token); - if (found) { - std::string str = results[1].str(); - begin = results.suffix().first; - switch (str[0]) { - case '[': return token(token::left_bracket, str); - case ']': return token(token::right_bracket, str); - case '{': return token(token::left_brace, str); - case '}': return token(token::right_brace, str); - case ';': return token(token::semicolon, str); - case '=': return token(token::equal, str); - case ',': return token(token::comma, str); - case ':': return token(token::colon, str); - case '+': return token(token::plus, str); - case '(': return token(token::left_paren, str); - case ')': return token(token::right_paren, str); - case '@': return token(token::at, str); - case '-': { - 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: assert (!"Definition of punctuation_token does not match switch statement"); std::abort(); - } - } - found = boost::regex_search(begin, end, results, number_token); - if (found) { - std::string str = results[1].str(); - begin = results.suffix().first; - return token(token::identifier, str); - } - found = boost::regex_search(begin, end, results, quoted_string_token); - if (found) { - std::string str = results[1].str(); - begin = results.suffix().first; - // Remove the beginning and ending quotes - assert (str.size() >= 2); - str.erase(str.begin()); - str.erase(str.end() - 1); - // Unescape quotes in the middle, but nothing else (see format spec) - for (size_t i = 0; i + 1 < str.size() /* May change */; ++i) { - if (str[i] == '\\' && str[i + 1] == '"') { - str.erase(str.begin() + i); - // Don't need to adjust i - } else if (str[i] == '\\' && str[i + 1] == '\n') { - str.erase(str.begin() + i); - str.erase(str.begin() + i); - --i; // Invert ++ that will be applied - } - } - return token(token::quoted_string, str); - } - if (*begin == '<') { - throw_lex_error("HTML strings not supported"); - return token(); - } else { - throw_lex_error("Invalid character"); - return token(); - } - } - - token peek_token_raw() { - if (lookahead.empty()) { - token t = get_token_raw(); - lookahead.push_back(t); - } - return lookahead.front(); - } - - token get_token() { // Handle string concatenation - token t = get_token_raw(); - if (t.type != token::quoted_string) return t; - std::string str = t.normalized_value; - while (peek_token_raw().type == token::plus) { - get_token_raw(); - token t2 = get_token_raw(); - if (t2.type != token::quoted_string) { - throw_lex_error("Must have quoted string after string concatenation"); - } - str += t2.normalized_value; - } - return token(token::identifier, str); // Note that quoted_string does not get passed to the parser - } - - void throw_lex_error(const std::string& errmsg) { - boost::throw_exception(lex_error(errmsg, *begin)); - } - }; + typedef std::string node_name; + typedef std::string subgraph_name; typedef std::map properties; - struct node_id { - std::string name; + struct node_and_port { + node_name name; std::string angle; // Or empty if no angle std::vector location; // Up to two identifiers + + friend inline bool operator==(const node_and_port& a, const node_and_port& b) { + return a.name == b.name && + a.angle == b.angle && + a.location == b.location; + } + + friend inline bool operator<(const node_and_port& a, const node_and_port& b) { + if (a.name != b.name) return a.name < b.name; + if (a.angle != b.angle) return a.angle < b.angle; + return a.location < b.location; + } }; - // Parser policy object should have the following methods: - // struct parser_policy { - // void do_node(const node_id& n, const properties& default_props, const properties& custom_props); - // void do_edge(const node_id& a, const node_id& b, const properties& props); - // void do_begin_graph(bool is_strict, bool is_directed, const std::string& name); - // void do_end_graph(const properties& props); - // void do_begin_subgraph(const std::string& name); - // void do_end_subgraph(const properties& props); - // }; + struct edge_info { + node_and_port source; + node_and_port target; + properties props; + }; - template - struct parser { - tokenizer the_tokenizer; - std::vector lookahead; + struct parser_result { bool graph_is_directed; - properties graph_props; - properties node_props; - properties edge_props; - Policy hooks; - - parser(BidirectionalIterator begin, BidirectionalIterator end, Policy hooks) - : the_tokenizer(begin, end), lookahead(), hooks(hooks) {} - - token get() { - if (lookahead.empty()) { - token t = the_tokenizer.get_token(); - return t; - } else { - token t = lookahead.front(); - lookahead.erase(lookahead.begin()); - return t; - } - } - - token peek() { - if (lookahead.empty()) { - lookahead.push_back(the_tokenizer.get_token()); - } - return lookahead.front(); - } - - void error(const std::string& str) { - boost::throw_exception(parse_error(str, peek())); - } - - void parse_graph(bool want_directed) { - bool is_strict = false; - bool is_directed; - std::string name; - if (peek().type == token::kw_strict) {get(); is_strict = true;} - switch (peek().type) { - case token::kw_graph: is_directed = false; break; - case token::kw_digraph: is_directed = true; break; - default: error("Wanted \"graph\" or \"digraph\""); - } - graph_is_directed = is_directed; // Used to check edges - if (want_directed != graph_is_directed) { - if (want_directed) { - boost::throw_exception(boost::undirected_graph_error()); - } else { - boost::throw_exception(boost::directed_graph_error()); - } - } - hooks.do_begin_graph(is_strict, is_directed, name); - get(); - switch (peek().type) { - case token::identifier: name = peek().normalized_value; get(); break; - case token::left_brace: break; - default: error("Wanted a graph name or left brace"); - } - if (peek().type == token::left_brace) get(); else error("Wanted a left brace to start the graph"); - parse_stmt_list(); - if (peek().type == token::right_brace) get(); else error("Wanted a right brace to end the graph"); - hooks.do_end_graph(graph_props); - if (peek().type == token::eof) {} else error("Wanted end of file"); - } - - void parse_stmt_list() { - while (true) { - if (peek().type == token::right_brace) return; - parse_stmt(); - if (peek().type == token::semicolon) get(); - } - } - - void parse_stmt() { - switch (peek().type) { - case token::kw_node: - case token::kw_edge: - case token::kw_graph: parse_attr_stmt(); break; - case token::kw_subgraph: - case token::left_brace: parse_subgraph(); break; - case token::identifier: { - token id = get(); - switch (peek().type) { - case token::dash_dash: - case token::dash_greater: { - node_id n = parse_node_id_rest(id); - parse_edge_stmt(n); - break; - } - case token::equal: { - get(); - if (peek().type != token::identifier) error("Wanted identifier as right side of ="); - token id2 = get(); - graph_props[id.normalized_value] = id2.normalized_value; - break; - } - default: { - node_id n = parse_node_id_rest(id); - parse_node_stmt(n); - break; - } - } - break; - } - default: error("Invalid start token for statement"); - } - } - - void parse_attr_stmt() { - switch (get().type) { - case token::kw_graph: parse_attr_list(graph_props); break; - case token::kw_node: parse_attr_list(node_props); break; - case token::kw_edge: parse_attr_list(edge_props); break; - default: assert (!"Bad attr_stmt case"); std::abort(); - } - } - - void parse_subgraph() { - std::string name; - if (peek().type == token::kw_subgraph) { - get(); - if (peek().type == token::identifier) { - name = get().normalized_value; - } - } - properties saved_node_props = node_props; - properties saved_edge_props = edge_props; - properties saved_graph_props = graph_props; - if (peek().type != token::left_brace) { - if (name.empty()) error("Subgraph reference needs a name"); - hooks.do_subgraph_reference(name); - return; - } - hooks.do_begin_subgraph(name); - if (peek().type == token::left_brace) get(); else error("Wanted left brace to start subgraph"); - parse_stmt_list(); - if (peek().type == token::right_brace) get(); else error("Wanted right brace to end subgraph"); - hooks.do_end_subgraph(graph_props); - node_props = saved_node_props; - edge_props = saved_edge_props; - graph_props = saved_graph_props; - if (peek().type == token::dash_greater || - peek().type == token::dash_dash) { // FIXME - std::cerr << "FIXME: Subgraphs in edges are not supported" << std::endl; - error("Unsupported subgraph edge case"); - } - } - - node_id parse_node_id_rest(const token& name) { - // A node ID is a node name, followed optionally by a port angle and a - // port location (in either order); a port location is either :id, - // :id:id, or :(id,id); the last two forms are treated as equivalent - // although I am not sure about that. - node_id id; - id.name = name.normalized_value; - parse_more: - switch (peek().type) { - case token::at: { - get(); - if (peek().type != token::identifier) error("Wanted identifier as port angle"); - if (id.angle != "") error("Duplicate port angle"); - id.angle = get().normalized_value; - goto parse_more; - } - case token::colon: { - get(); - if (!id.location.empty()) error("Duplicate port location"); - switch (peek().type) { - case token::identifier: { - id.location.push_back(get().normalized_value); - switch (peek().type) { - case token::colon: { - get(); - if (peek().type != token::identifier) error("Wanted identifier as port location"); - id.location.push_back(get().normalized_value); - goto parse_more; - } - default: goto parse_more; - } - } - case token::left_paren: { - get(); - if (peek().type != token::identifier) error("Wanted identifier as first element of port location"); - id.location.push_back(get().normalized_value); - if (peek().type != token::comma) error("Wanted comma between parts of port location"); - get(); - if (peek().type != token::identifier) error("Wanted identifier as second element of port location"); - id.location.push_back(get().normalized_value); - if (peek().type != token::right_paren) error("Wanted right parenthesis to close port location"); - get(); - goto parse_more; - } - default: error("Wanted identifier or left parenthesis as start of port location"); - } - } - default: break; - } - return id; - } - - node_id parse_node_id() { - if (peek().type != token::identifier) error("Wanted identifier as node name (subgraphs not supported yet)"); - token name = get(); - return parse_node_id_rest(name); - } - - void parse_node_stmt(const node_id& n) { - properties this_node_props; - if (peek().type == token::left_bracket) parse_attr_list(this_node_props); - hooks.do_node(n, node_props, this_node_props); - } - - void parse_edge_stmt(const node_id& lhs) { - std::vector nodes_in_chain(1, lhs); - while (true) { - bool leave_loop = true; - switch (peek().type) { - case token::dash_dash: { - if (graph_is_directed) error("Using -- in directed graph"); - get(); - nodes_in_chain.push_back(parse_node_id()); - leave_loop = false; - break; - } - case token::dash_greater: { - if (!graph_is_directed) error("Using -> in undirected graph"); - get(); - nodes_in_chain.push_back(parse_node_id()); - leave_loop = false; - break; - } - default: leave_loop = true; break; - } - if (leave_loop) break; - } - properties this_edge_props = 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 - for (size_t i = 0; i + 1 < nodes_in_chain.size(); ++i) { - hooks.do_edge(nodes_in_chain[i], nodes_in_chain[i + 1], this_edge_props); - } - } - - void parse_attr_list(properties& props) { - while (true) { - if (peek().type == token::left_bracket) get(); else error("Wanted left bracket to start attribute list"); - while (true) { - switch (peek().type) { - case token::right_bracket: break; - case token::identifier: { - std::string lhs = get().normalized_value; - std::string rhs = "true"; - if (peek().type == token::equal) { - get(); - if (peek().type != token::identifier) error("Wanted identifier as value of attributed"); - rhs = get().normalized_value; - } - props[lhs] = rhs; - break; - } - default: error("Wanted identifier as name of attribute"); - } - if (peek().type == token::comma) {get(); continue;} - break; - } - if (peek().type == token::right_bracket) get(); else error("Wanted right bracket to end attribute list"); - if (peek().type != token::left_bracket) break; - } - } + bool graph_is_strict; + std::map nodes; // Global set + std::vector edges; + std::map graph_props; // Root and subgraphs }; - struct graph_parser_policy { - ::boost::detail::graph::mutate_graph* mg; + // The actual parser, from libs/graph/src/read_graphviz_new.cpp + void parse_graphviz_from_string(const std::string& str, parser_result& result, bool want_directed); - typedef boost::detail::graph::node_t vertex; - typedef boost::detail::graph::edge_t edge; - - std::map vertex_map; - std::map edge_map; - - graph_parser_policy(::boost::detail::graph::mutate_graph* mg) - : mg(mg), - vertex_map(), - edge_map() - {} - - bool node_exists(const node_id& n) const { - std::map::const_iterator i = vertex_map.find(n.name); - return (i != vertex_map.end()); - } - - vertex get_or_build_node(const node_id& n) { - // FIXME: use ports - std::map::const_iterator i = vertex_map.find(n.name); - if (i == vertex_map.end()) { - vertex v = n.name; - mg->do_add_vertex(v); - vertex_map.insert(std::make_pair(v, v)); - return v; - } else { - return i->second; - } - } - - static std::string node_id_to_string(const node_id& n) { - std::string result = n.name; - for (size_t i = 0; i < n.location.size(); ++i) { - result += ":" + n.location[i]; - } - if (!n.angle.empty()) result += "@" + n.angle; - return result; - } - - static std::string props_to_string(const properties& props) { - std::string result = "["; - for (properties::const_iterator i = props.begin(); i != props.end(); ++i) { - if (i != props.begin()) result += ", "; - result += i->first + "=" + i->second; - } - result += "]"; - return result; - } - - void do_node(const node_id& n, const properties& def_props, const properties& new_props) { - std::cerr << node_id_to_string(n) << " " << props_to_string(def_props) << " " << props_to_string(new_props) << std::endl; - properties props_to_set = new_props; - if (!node_exists(n)) { // Only use defaults if node is new - props_to_set.insert(def_props.begin(), def_props.end()); // This keeps old properties in preference to ones from def_props - } - vertex v = get_or_build_node(n); - for (properties::const_iterator i = props_to_set.begin(); i != props_to_set.end(); ++i) { - mg->set_node_property(i->first, v, i->second); - } - } - - void do_edge(const node_id& a, const node_id& b, const properties& props) { - std::cerr << node_id_to_string(a) << " -> " << node_id_to_string(b) << " " << props_to_string(props) << std::endl; - edge e = edge::new_edge(); - mg->do_add_edge(e, get_or_build_node(a), get_or_build_node(b)); - for (properties::const_iterator i = props.begin(); i != props.end(); ++i) { - mg->set_edge_property(i->first, e, i->second); - } - } - - void do_begin_graph(bool is_strict, bool is_directed, const std::string& name) { - ignore_unused_variable_warning(is_strict); - ignore_unused_variable_warning(is_directed); - ignore_unused_variable_warning(name); - // std::cerr << "starting" << (is_strict ? " strict" : "") << " " << (is_directed ? "directed" : "undirected") << " graph named " << name << std::endl; - } - - void do_end_graph(const properties& props) { - std::cerr << "ending graph " << props_to_string(props) << std::endl; - for (properties::const_iterator i = props.begin(); i != props.end(); ++i) { - mg->set_graph_property(i->first, i->second); - } - } - - void do_subgraph_reference(const std::string& name) { - ignore_unused_variable_warning(name); - // std::cerr << "subgraph reference to " << name << std::endl; - } - - void do_begin_subgraph(const std::string& name) { - ignore_unused_variable_warning(name); - // std::cerr << "starting subgraph named " << name << std::endl; - } - - void do_end_subgraph(const properties& props) { - ignore_unused_variable_warning(props); - // std::cerr << "ending subgraph " << props_to_string(props) << std::endl; - } - }; + // Translate from those results to a graph + void translate_results_to_graph(const parser_result& r, ::boost::detail::graph::mutate_graph* mg); } // namespace read_graphviz_detail -template -bool read_graphviz(BidirectionalIterator begin, BidirectionalIterator end, +// This is also in boost/graph/graphviz.hpp +namespace detail { + namespace graph { + BOOST_GRAPH_DECL bool read_graphviz(const std::string& str, boost::detail::graph::mutate_graph* mg); + } // end namespace graph +} // end namespace detail + +template +bool read_graphviz(const std::string& str, MutableGraph& graph, boost::dynamic_properties& dp, std::string const& node_id = "node_id") { boost::detail::graph::mutate_graph_impl mg(graph, dp, node_id); - read_graphviz_detail::graph_parser_policy policy(&mg); - read_graphviz_detail::parser p(begin, end, policy); - p.parse_graph(mg.is_directed()); - return true; + return detail::graph::read_graphviz(str, &mg); +} + +template +bool read_graphviz(InputIter begin, InputIter end, + MutableGraph& graph, boost::dynamic_properties& dp, + std::string const& node_id = "node_id") { + return read_graphviz(std::string(begin, end), graph, dp, node_id); } } // namespace boost diff --git a/include/boost/graph/graphviz.hpp b/include/boost/graph/graphviz.hpp index 88dff67d..771143e9 100644 --- a/include/boost/graph/graphviz.hpp +++ b/include/boost/graph/graphviz.hpp @@ -491,11 +491,12 @@ namespace boost { // These four require linking the BGL-Graphviz library: libbgl-viz.a // from the /src directory. - extern void read_graphviz(const std::string& file, GraphvizDigraph& g); - extern void read_graphviz(FILE* file, GraphvizDigraph& g); - - extern void read_graphviz(const std::string& file, GraphvizGraph& g); - extern void read_graphviz(FILE* file, GraphvizGraph& g); + // Library has not existed for a while + // extern void read_graphviz(const std::string& file, GraphvizDigraph& g); + // extern void read_graphviz(FILE* file, GraphvizDigraph& g); + // + // extern void read_graphviz(const std::string& file, GraphvizGraph& g); + // extern void read_graphviz(FILE* file, GraphvizGraph& g); class dynamic_properties_writer { @@ -654,6 +655,14 @@ struct undirected_graph_error : public graph_exception { } }; +struct bad_graphviz_syntax: public graph_exception { + std::string errmsg; + bad_graphviz_syntax(const std::string& errmsg) + : errmsg(errmsg) {} + const char* what() const throw () {return errmsg.c_str();} + ~bad_graphviz_syntax() throw () {}; +}; + namespace detail { namespace graph { typedef std::string id_t; @@ -789,7 +798,7 @@ bool read_graphviz(std::istream& in, MutableGraph& graph, std::copy(std::istream_iterator(in), std::istream_iterator(), std::back_inserter(data)); - return read_graphviz(data.begin(),data.end(),graph,dp,node_id); + return read_graphviz(data,graph,dp,node_id); } } // namespace boost diff --git a/src/read_graphviz_new.cpp b/src/read_graphviz_new.cpp new file mode 100644 index 00000000..3f846dfa --- /dev/null +++ b/src/read_graphviz_new.cpp @@ -0,0 +1,810 @@ +// Copyright 2004-9 Trustees of Indiana University + +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// +// read_graphviz_new.cpp - +// Initialize a model of the BGL's MutableGraph concept and an associated +// collection of property maps using a graph expressed in the GraphViz +// DOT Language. +// +// Based on the grammar found at: +// http://www.graphviz.org/cvs/doc/info/lang.html +// +// Jeremiah rewrite used grammar found at: +// http://www.graphviz.org/doc/info/lang.html +// and page 34 or http://www.graphviz.org/pdf/dotguide.pdf +// +// See documentation for this code at: +// http://www.boost.org/libs/graph/doc/read-graphviz.html +// + +// Author: Jeremiah Willcock +// Ronald Garcia +// + +#include +#include +#include +#include +#include +#include +#include +#include // for std::exception +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost { + +namespace read_graphviz_detail { + struct token { + enum token_type { + kw_strict, + kw_graph, + kw_digraph, + kw_node, + kw_edge, + kw_subgraph, + left_brace, + right_brace, + semicolon, + equal, + left_bracket, + right_bracket, + comma, + colon, + dash_greater, + dash_dash, + plus, + left_paren, + right_paren, + at, + identifier, + quoted_string, // Only used internally in tokenizer + eof, + invalid + } type; + std::string normalized_value; // May have double-quotes removed and/or some escapes replaced + token(token_type type, const std::string& normalized_value) + : type(type), normalized_value(normalized_value) {} + token(): type(invalid), normalized_value("") {} + friend std::ostream& operator<<(std::ostream& o, const token& t) { + switch (t.type) { + case token::kw_strict: o << ""; break; + case token::kw_graph: o << ""; break; + case token::kw_digraph: o << ""; break; + case token::kw_node: o << ""; break; + case token::kw_edge: o << ""; break; + case token::kw_subgraph: o << ""; break; + case token::left_brace: o << ""; break; + case token::right_brace: o << ""; break; + case token::semicolon: o << ""; break; + case token::equal: o << ""; break; + case token::left_bracket: o << ""; break; + case token::right_bracket: o << ""; break; + case token::comma: o << ""; break; + case token::colon: o << ""; break; + case token::dash_greater: o << ""; break; + case token::dash_dash: o << ""; break; + case token::plus: o << ""; break; + case token::left_paren: o << ""; break; + case token::right_paren: o << ""; break; + case token::at: o << ""; break; + case token::identifier: o << ""; break; + case token::quoted_string: o << ""; break; + case token::eof: o << ""; break; + default: o << ""; break; + } + o << " '" << t.normalized_value << "'"; + return o; + } + }; + + bad_graphviz_syntax lex_error(const std::string& errmsg, char bad_char) { + return bad_graphviz_syntax(errmsg + " (char is '" + bad_char + "')"); + } + + bad_graphviz_syntax parse_error(const std::string& errmsg, const token& bad_token) { + return bad_graphviz_syntax(errmsg + " (token is \"" + boost::lexical_cast(bad_token) + "\")"); + } + + struct tokenizer { + std::string::const_iterator begin, end; + std::vector lookahead; + // Precomputed regexes + boost::regex stuff_to_skip; + boost::regex basic_id_token; + boost::regex punctuation_token; + boost::regex number_token; + boost::regex quoted_string_token; + + tokenizer(const std::string& str) : begin(str.begin()), end(str.end()) + { + std::string end_of_token = "(?=(?:\\W))"; + std::string whitespace = "(?:\\s+)"; + std::string slash_slash_comment = "(?://.*$)"; + std::string slash_star_comment = "(?:/\\*.*?\\*/)"; + std::string hash_comment = "(?:^#.*?$)"; + stuff_to_skip = "\\A(?:" + whitespace + "|" + slash_slash_comment + "|" + slash_star_comment + "|" + hash_comment + ")*"; + basic_id_token = "\\A([[:alpha:]_](?:\\w*))"; + punctuation_token = "\\A([][{};=,:+()@]|[-][>-])"; + number_token = "\\A([-]?(?:(?:\\.\\d+)|(?:\\d+(?:\\.\\d*)?)))"; + quoted_string_token = "\\A(\"(?:[^\"\\\\]|(?:[\\\\].))*\")"; + } + + void skip() { + boost::match_results results; + bool found = boost::regex_search(begin, end, results, stuff_to_skip); + assert (found); + boost::sub_match sm1 = results.suffix(); + assert (sm1.second == end); + begin = sm1.first; + } + + token get_token_raw() { + if (!lookahead.empty()) { + token t = lookahead.front(); + lookahead.erase(lookahead.begin()); + return t; + } + skip(); + if (begin == end) return token(token::eof, ""); + // Look for keywords first + bool found; + boost::match_results results; + found = boost::regex_search(begin, end, results, basic_id_token); + if (found) { + std::string str = results[1].str(); + std::string str_lower = boost::algorithm::to_lower_copy(str); + begin = results.suffix().first; + if (str_lower == "strict") { + return token(token::kw_strict, str); + } else if (str_lower == "graph") { + return token(token::kw_graph, str); + } else if (str_lower == "digraph") { + return token(token::kw_digraph, str); + } else if (str_lower == "node") { + return token(token::kw_node, str); + } else if (str_lower == "edge") { + return token(token::kw_edge, str); + } else if (str_lower == "subgraph") { + return token(token::kw_subgraph, str); + } else { + return token(token::identifier, str); + } + } + found = boost::regex_search(begin, end, results, punctuation_token); + if (found) { + std::string str = results[1].str(); + begin = results.suffix().first; + switch (str[0]) { + case '[': return token(token::left_bracket, str); + case ']': return token(token::right_bracket, str); + case '{': return token(token::left_brace, str); + case '}': return token(token::right_brace, str); + case ';': return token(token::semicolon, str); + case '=': return token(token::equal, str); + case ',': return token(token::comma, str); + case ':': return token(token::colon, str); + case '+': return token(token::plus, str); + case '(': return token(token::left_paren, str); + case ')': return token(token::right_paren, str); + case '@': return token(token::at, str); + case '-': { + 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: assert (!"Definition of punctuation_token does not match switch statement"); std::abort(); + } + } + found = boost::regex_search(begin, end, results, number_token); + if (found) { + std::string str = results[1].str(); + begin = results.suffix().first; + return token(token::identifier, str); + } + found = boost::regex_search(begin, end, results, quoted_string_token); + if (found) { + std::string str = results[1].str(); + begin = results.suffix().first; + // Remove the beginning and ending quotes + assert (str.size() >= 2); + str.erase(str.begin()); + str.erase(str.end() - 1); + // Unescape quotes in the middle, but nothing else (see format spec) + for (size_t i = 0; i + 1 < str.size() /* May change */; ++i) { + if (str[i] == '\\' && str[i + 1] == '"') { + str.erase(str.begin() + i); + // Don't need to adjust i + } else if (str[i] == '\\' && str[i + 1] == '\n') { + str.erase(str.begin() + i); + str.erase(str.begin() + i); + --i; // Invert ++ that will be applied + } + } + return token(token::quoted_string, str); + } + if (*begin == '<') { + throw_lex_error("HTML strings not supported"); + return token(); + } else { + throw_lex_error("Invalid character"); + return token(); + } + } + + token peek_token_raw() { + if (lookahead.empty()) { + token t = get_token_raw(); + lookahead.push_back(t); + } + return lookahead.front(); + } + + token get_token() { // Handle string concatenation + token t = get_token_raw(); + if (t.type != token::quoted_string) return t; + std::string str = t.normalized_value; + while (peek_token_raw().type == token::plus) { + get_token_raw(); + token t2 = get_token_raw(); + if (t2.type != token::quoted_string) { + throw_lex_error("Must have quoted string after string concatenation"); + } + str += t2.normalized_value; + } + return token(token::identifier, str); // Note that quoted_string does not get passed to the parser + } + + void throw_lex_error(const std::string& errmsg) { + boost::throw_exception(lex_error(errmsg, *begin)); + } + }; + + struct edge_endpoint { + bool is_subgraph; + node_and_port node_ep; + subgraph_name subgraph_ep; + + static edge_endpoint node(const node_and_port& ep) { + edge_endpoint r; + r.is_subgraph = false; + r.node_ep = ep; + return r; + } + + static edge_endpoint subgraph(const subgraph_name& ep) { + edge_endpoint r; + r.is_subgraph = true; + r.subgraph_ep = ep; + return r; + } + }; + + struct node_or_subgraph_ref { + bool is_subgraph; + std::string name; // Name for subgraphs or nodes, "___root___" for root graph + }; + + static node_or_subgraph_ref noderef(const node_name& n) { + node_or_subgraph_ref r; + r.is_subgraph = false; + r.name = n; + return r; + } + + static node_or_subgraph_ref subgraphref(const subgraph_name& n) { + node_or_subgraph_ref r; + r.is_subgraph = true; + r.name = n; + return r; + } + + typedef std::vector subgraph_member_list; + + struct subgraph_info { + properties def_node_props; + properties def_edge_props; + subgraph_member_list members; + }; + + struct parser { + tokenizer the_tokenizer; + std::vector lookahead; + parser_result& r; + std::map subgraphs; + std::string current_subgraph_name; + int sgcounter; // Counter for anonymous subgraphs + + subgraph_info& current() {return subgraphs[current_subgraph_name];} + properties& current_graph_props() {return r.graph_props[current_subgraph_name];} + subgraph_member_list& current_members() {return current().members;} + + parser(const std::string& gr, parser_result& result) + : the_tokenizer(gr), lookahead(), r(result), sgcounter(0) { + current_subgraph_name = "___root___"; + current() = subgraph_info(); // Initialize root graph + current_graph_props().clear(); + current_members().clear(); + } + + token get() { + if (lookahead.empty()) { + token t = the_tokenizer.get_token(); + return t; + } else { + token t = lookahead.front(); + lookahead.erase(lookahead.begin()); + return t; + } + } + + token peek() { + if (lookahead.empty()) { + lookahead.push_back(the_tokenizer.get_token()); + } + return lookahead.front(); + } + + void error(const std::string& str) { + boost::throw_exception(parse_error(str, peek())); + } + + void parse_graph(bool want_directed) { + bool is_strict = false; + bool is_directed; + std::string name; + if (peek().type == token::kw_strict) {get(); is_strict = true;} + switch (peek().type) { + case token::kw_graph: is_directed = false; break; + case token::kw_digraph: is_directed = true; break; + default: error("Wanted \"graph\" or \"digraph\""); + } + r.graph_is_directed = is_directed; // Used to check edges + r.graph_is_strict = is_strict; + if (want_directed != r.graph_is_directed) { + if (want_directed) { + boost::throw_exception(boost::undirected_graph_error()); + } else { + boost::throw_exception(boost::directed_graph_error()); + } + } + get(); + switch (peek().type) { + case token::identifier: name = peek().normalized_value; get(); break; + case token::left_brace: break; + default: error("Wanted a graph name or left brace"); + } + if (peek().type == token::left_brace) get(); else error("Wanted a left brace to start the graph"); + parse_stmt_list(); + if (peek().type == token::right_brace) get(); else error("Wanted a right brace to end the graph"); + if (peek().type == token::eof) {} else error("Wanted end of file"); + } + + void parse_stmt_list() { + while (true) { + if (peek().type == token::right_brace) return; + parse_stmt(); + if (peek().type == token::semicolon) get(); + } + } + + void parse_stmt() { + switch (peek().type) { + case token::kw_node: + case token::kw_edge: + case token::kw_graph: parse_attr_stmt(); break; + case token::kw_subgraph: + case token::left_brace: + case token::identifier: { + token id = get(); + if (id.type == token::identifier && peek().type == token::equal) { // Graph property + get(); + if (peek().type != token::identifier) error("Wanted identifier as right side of ="); + token id2 = get(); + current_graph_props()[id.normalized_value] = id2.normalized_value; + } else { + edge_endpoint ep = parse_endpoint_rest(id); + if (peek().type == token::dash_dash || peek().type == token::dash_greater) { // Edge + parse_edge_stmt(ep); + } else { + if (!ep.is_subgraph) { // Only nodes can have attribute lists + // This node already exists because of its first mention + // (properties set to defaults by parse_node_and_port, called + // by parse_endpoint_rest) + properties this_node_props; + if (peek().type == token::left_bracket) { + parse_attr_list(this_node_props); + } + for (properties::const_iterator i = this_node_props.begin(); + i != this_node_props.end(); ++i) { + // Override old properties with same names + r.nodes[ep.node_ep.name][i->first] = i->second; + } + current_members().push_back(noderef(ep.node_ep.name)); + } else { + current_members().push_back(subgraphref(ep.subgraph_ep)); + } + } + } + break; + } + default: error("Invalid start token for statement"); + } + } + + void parse_attr_stmt() { + switch (get().type) { + 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"); std::abort(); + } + } + + edge_endpoint parse_endpoint() { + switch (peek().type) { + case token::kw_subgraph: + case token::left_brace: + case token::identifier: { + token first = get(); + return parse_endpoint_rest(first); + } + default: { + error("Wanted \"subgraph\", \"{\", or identifier to start node or subgraph"); + return edge_endpoint(); + } + } + } + + edge_endpoint parse_endpoint_rest(const token& first_token) { + switch (first_token.type) { + case token::kw_subgraph: + case token::left_brace: return edge_endpoint::subgraph(parse_subgraph(first_token)); + default: return edge_endpoint::node(parse_node_and_port(first_token)); + } + } + + subgraph_name parse_subgraph(const token& first_token) { + std::string name; + bool is_anonymous = true; + if (first_token.type == token::kw_subgraph) { + if (peek().type == token::identifier) { + name = get().normalized_value; + is_anonymous = false; + } + } + if (is_anonymous) { + name = "___subgraph_" + + boost::lexical_cast(++sgcounter); + } + if (subgraphs.find(name) == subgraphs.end()) { + subgraphs[name] = current(); // Initialize properties and defaults + subgraphs[name].members.clear(); // Except member list + } + if (first_token.type == token::kw_subgraph && peek().type != token::left_brace) { + if (is_anonymous) error("Subgraph reference needs a name"); + return name; + } + subgraph_name old_sg = current_subgraph_name; + current_subgraph_name = name; + if (peek().type == token::left_brace) get(); else error("Wanted left brace to start subgraph"); + parse_stmt_list(); + if (peek().type == token::right_brace) get(); else error("Wanted right brace to end subgraph"); + current_subgraph_name = old_sg; + return name; + } + + node_and_port parse_node_and_port(const token& name) { + // A node ID is a node name, followed optionally by a port angle and a + // port location (in either order); a port location is either :id, + // :id:id, or :(id,id); the last two forms are treated as equivalent + // although I am not sure about that. + node_and_port id; + id.name = name.normalized_value; + parse_more: + switch (peek().type) { + case token::at: { + get(); + if (peek().type != token::identifier) error("Wanted identifier as port angle"); + if (id.angle != "") error("Duplicate port angle"); + id.angle = get().normalized_value; + goto parse_more; + } + case token::colon: { + get(); + if (!id.location.empty()) error("Duplicate port location"); + switch (peek().type) { + case token::identifier: { + id.location.push_back(get().normalized_value); + switch (peek().type) { + case token::colon: { + get(); + if (peek().type != token::identifier) error("Wanted identifier as port location"); + id.location.push_back(get().normalized_value); + goto parse_more; + } + default: goto parse_more; + } + } + case token::left_paren: { + get(); + if (peek().type != token::identifier) error("Wanted identifier as first element of port location"); + id.location.push_back(get().normalized_value); + if (peek().type != token::comma) error("Wanted comma between parts of port location"); + get(); + if (peek().type != token::identifier) error("Wanted identifier as second element of port location"); + id.location.push_back(get().normalized_value); + if (peek().type != token::right_paren) error("Wanted right parenthesis to close port location"); + get(); + goto parse_more; + } + default: error("Wanted identifier or left parenthesis as start of port location"); + } + } + default: break; + } + if (r.nodes.find(id.name) == r.nodes.end()) { // First mention + r.nodes[id.name] = current().def_node_props; + } + return id; + } + + void parse_edge_stmt(const edge_endpoint& lhs) { + std::vector nodes_in_chain(1, lhs); + while (true) { + bool leave_loop = true; + switch (peek().type) { + case token::dash_dash: { + if (r.graph_is_directed) error("Using -- in directed graph"); + get(); + nodes_in_chain.push_back(parse_endpoint()); + leave_loop = false; + break; + } + case token::dash_greater: { + if (!r.graph_is_directed) error("Using -> in undirected graph"); + get(); + nodes_in_chain.push_back(parse_endpoint()); + leave_loop = false; + break; + } + default: leave_loop = true; break; + } + if (leave_loop) break; + } + 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 + 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); + } + } + + // Do an edge from the file, the edge may need to be expanded if it connects to a subgraph + void do_orig_edge(const edge_endpoint& src, const edge_endpoint& tgt, const properties& props) { + std::set sources = get_recursive_members(src); + std::set targets = get_recursive_members(tgt); + for (std::set::const_iterator i = sources.begin(); i != sources.end(); ++i) { + for (std::set::const_iterator j = targets.begin(); j != targets.end(); ++j) { + do_edge(*i, *j, props); + } + } + } + + // Get nodes in an edge_endpoint, recursively + std::set get_recursive_members(const edge_endpoint& orig_ep) { + std::set result; + std::vector worklist(1, orig_ep); + std::set done; + while (!worklist.empty()) { + edge_endpoint ep = worklist.back(); + worklist.pop_back(); + if (ep.is_subgraph) { + if (done.find(ep.subgraph_ep) == done.end()) { + done.insert(ep.subgraph_ep); + std::map::const_iterator + info_i = subgraphs.find(ep.subgraph_ep); + if (info_i != subgraphs.end()) { + const subgraph_member_list& members = info_i->second.members; + for (subgraph_member_list::const_iterator i = members.begin(); + i != members.end(); ++i) { + node_or_subgraph_ref ref = *i; + if (ref.is_subgraph) { + worklist.push_back(edge_endpoint::subgraph(ref.name)); + } else { + node_and_port np; + np.name = ref.name; + worklist.push_back(edge_endpoint::node(np)); + } + } + } + } + } else { + result.insert(ep.node_ep); + } + } + return result; + } + + // Do a fixed-up edge, with only nodes as endpoints + void do_edge(const node_and_port& src, const node_and_port& tgt, const properties& props) { + edge_info e; + e.source = src; + e.target = tgt; + e.props = props; + r.edges.push_back(e); + } + + void parse_attr_list(properties& props) { + while (true) { + if (peek().type == token::left_bracket) get(); else error("Wanted left bracket to start attribute list"); + while (true) { + switch (peek().type) { + case token::right_bracket: break; + case token::identifier: { + std::string lhs = get().normalized_value; + std::string rhs = "true"; + if (peek().type == token::equal) { + get(); + if (peek().type != token::identifier) error("Wanted identifier as value of attributed"); + rhs = get().normalized_value; + } + props[lhs] = rhs; + break; + } + default: error("Wanted identifier as name of attribute"); + } + if (peek().type == token::comma) {get(); continue;} + break; + } + if (peek().type == token::right_bracket) get(); else error("Wanted right bracket to end attribute list"); + if (peek().type != token::left_bracket) break; + } + } + }; + + void parse_graphviz_from_string(const std::string& str, parser_result& result, bool want_directed) { + parser p(str, result); + p.parse_graph(want_directed); + } + + // Some debugging stuff + std::ostream& operator<<(std::ostream& o, const node_and_port& n) { + o << n.name; + for (size_t i = 0; i < n.location.size(); ++i) { + o << ":" << n.location[i]; + } + if (!n.angle.empty()) o << "@" << n.angle; + return o; + } + + // Can't be operator<< because properties is just an std::map + std::string props_to_string(const properties& props) { + std::string result = "["; + for (properties::const_iterator i = props.begin(); i != props.end(); ++i) { + if (i != props.begin()) result += ", "; + result += i->first + "=" + i->second; + } + result += "]"; + return result; + } + + 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; + mg->do_add_vertex(i->first); + for (properties::const_iterator j = i->second.begin(); j != i->second.end(); ++j) { + mg->set_node_property(j->first, i->first, j->second); + } + } + for (std::vector::const_iterator i = r.edges.begin(); i != r.edges.end(); ++i) { + const edge_info& ei = *i; + std::cerr << ei.source << " -> " << ei.target << " " << props_to_string(ei.props) << std::endl; + edge e = edge::new_edge(); + mg->do_add_edge(e, ei.source.name, ei.target.name); + for (properties::const_iterator j = ei.props.begin(); j != ei.props.end(); ++j) { + mg->set_edge_property(j->first, e, j->second); + } + } + 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 + 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) { + mg->set_graph_property(i->first, i->second); + } + } + +} // end namespace read_graphviz_detail + +namespace detail { + namespace graph { + + bool read_graphviz(const std::string& str, boost::detail::graph::mutate_graph* mg) { + read_graphviz_detail::parser_result parsed_file; + read_graphviz_detail::parse_graphviz_from_string(str, parsed_file, mg->is_directed()); + read_graphviz_detail::translate_results_to_graph(parsed_file, mg); + return true; + } + + } // end namespace graph +} // end namespace detail + +} // end namespace boost + +// GraphViz format notes (tested using "dot version 1.13 (v16) (Mon August 23, +// 2004)", grammar from references in read_graphviz_new.hpp): + +// Subgraphs don't nest (all a0 subgraphs are the same thing), but a node or +// subgraph can have multiple parents (sources online say that the layout +// algorithms can't handle non-tree structures of clusters, but it seems to +// read them the same from the file). The containment relation is required to +// be a DAG, though; it appears that a node or subgraph can't be moved into an +// ancestor of a subgraph where it already was (we don't enforce that but do a +// DFS when finding members to prevent cycles). Nodes get their properties by +// when they are first mentioned, and can only have them overridden after that +// by explicit properties on that particular node. Closing and reopening the +// same subgraph name adds to its members, and graph properties and node/edge +// defaults are preserved in that subgraph. The members of a subgraph used in +// an edge are gathered when the edge is read, even if new members are added to +// the subgraph later. Ports are allowed in a lot more places in the grammar +// than Dot uses. For example, declaring a node seems to ignore ports, and I +// don't think it's possible to set properties on a particular port. Adding an +// edge between two ports on the same node seems to make Dot unhappy (crashed +// for me). + +// Test graph for GraphViz behavior on strange combinations of subgraphs and +// such. I don't have anywhere else to put this file. + +#if 0 +dIGRaph foo { + node [color=blue] + subgraph a -> b + subgraph a {c} + subgraph a -> d + subgraph a {node [color=red]; e} + subgraph a -> f + subgraph a {g} -> h + subgraph a {node [color=green]; i} -> j + subgraph a {node [color=yellow]} + + subgraph a0 {node [color=black]; subgraph a1 {node [color=white]}} + node [color=pink] zz + subgraph a0 {x1} + subgraph a0 {subgraph a1 {x2}} + + subgraph a0 -> x3 + subgraph a0 {subgraph a1 -> x3} + x3 + subgraph a0 {subgraph a0 {node [color=xxx]; x2} x7} + x2 [color=yyy] + subgraph cluster_ax {foo; subgraph a0} + subgraph a0 {foo2} + subgraph cluster_ax {foo3} + // subgraph a0 -> subgraph a0 + + bgcolor=yellow + subgraph cluster_a2 {y1} + // y1:n -> y1:(s,3)@se + y1@se [color=green] + y1@n [color=red] +} +#endif From 1b463407379b5e4f7d02ccf8703f22a7988890ed Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Mon, 25 May 2009 23:59:45 +0000 Subject: [PATCH 199/224] Added backslash-newline as a form of whitespace outside strings [SVN r53264] --- src/read_graphviz_new.cpp | 7 ++++++- test/graphviz_test.cpp | 2 +- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/read_graphviz_new.cpp b/src/read_graphviz_new.cpp index 3f846dfa..9cab1352 100644 --- a/src/read_graphviz_new.cpp +++ b/src/read_graphviz_new.cpp @@ -137,7 +137,12 @@ namespace read_graphviz_detail { std::string slash_slash_comment = "(?://.*$)"; std::string slash_star_comment = "(?:/\\*.*?\\*/)"; std::string hash_comment = "(?:^#.*?$)"; - stuff_to_skip = "\\A(?:" + whitespace + "|" + slash_slash_comment + "|" + slash_star_comment + "|" + hash_comment + ")*"; + std::string backslash_newline = "(?:[\\\\][\\n])"; + stuff_to_skip = "\\A(?:" + whitespace + "|" + + slash_slash_comment + "|" + + slash_star_comment + "|" + + hash_comment + "|" + + backslash_newline + ")*"; basic_id_token = "\\A([[:alpha:]_](?:\\w*))"; punctuation_token = "\\A([][{};=,:+()@]|[-][>-])"; number_token = "\\A([-]?(?:(?:\\.\\d+)|(?:\\d+(?:\\.\\d*)?)))"; diff --git a/test/graphviz_test.cpp b/test/graphviz_test.cpp index 83f79f2a..4c3a3490 100644 --- a/test/graphviz_test.cpp +++ b/test/graphviz_test.cpp @@ -174,7 +174,7 @@ int test_main(int, char*[]) { { 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] }"); + gs_t gs("graph { a node [mass = 7.7] c e [mass =\\\n6.66] }"); BOOST_CHECK((test_graph(gs,3,masses,weight_map_t()))); } From c5bcc31f22d29fb387896cdae0ddf87074ab051b Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Tue, 26 May 2009 00:10:22 +0000 Subject: [PATCH 200/224] Fixed strict graph support [SVN r53265] --- doc/read_graphviz.rst | 3 --- src/read_graphviz_new.cpp | 9 +++++++++ 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/doc/read_graphviz.rst b/doc/read_graphviz.rst index fa5f6281..12c79298 100644 --- a/doc/read_graphviz.rst +++ b/doc/read_graphviz.rst @@ -231,9 +231,6 @@ Future Work - Expanding escape codes in the same way GraphViz does. - - Enforcement of the ``strict`` keyword (ignoring self-loops and parallel - edges). - - Support for optional recognition of subgraphs as distinct entities. diff --git a/src/read_graphviz_new.cpp b/src/read_graphviz_new.cpp index 9cab1352..2c5a1210 100644 --- a/src/read_graphviz_new.cpp +++ b/src/read_graphviz_new.cpp @@ -335,6 +335,7 @@ namespace read_graphviz_detail { std::map subgraphs; std::string current_subgraph_name; int sgcounter; // Counter for anonymous subgraphs + std::set > existing_edges; // Used for checking in strict graphs subgraph_info& current() {return subgraphs[current_subgraph_name];} properties& current_graph_props() {return r.graph_props[current_subgraph_name];} @@ -649,6 +650,14 @@ namespace read_graphviz_detail { // Do a fixed-up edge, with only nodes as endpoints void do_edge(const node_and_port& src, const node_and_port& tgt, const properties& props) { + if (r.graph_is_strict) { + if (src.name == tgt.name) return; + std::pair tag(src.name, tgt.name); + if (existing_edges.find(tag) != existing_edges.end()) { + return; // Parallel edge + } + existing_edges.insert(tag); + } edge_info e; e.source = src; e.target = tgt; From e9709979defa0d5403137bd00c733807ae4a8265 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Tue, 26 May 2009 01:08:48 +0000 Subject: [PATCH 201/224] Added support for HTML identifiers [SVN r53268] --- doc/read_graphviz.html | 3 --- doc/read_graphviz.rst | 2 -- src/read_graphviz_new.cpp | 33 +++++++++++++++++++++++++++++++-- test/graphviz_test.cpp | 10 ++++++++++ 4 files changed, 41 insertions(+), 7 deletions(-) diff --git a/doc/read_graphviz.html b/doc/read_graphviz.html index 0d392889..324ba7cc 100644 --- a/doc/read_graphviz.html +++ b/doc/read_graphviz.html @@ -497,11 +497,8 @@ description. Undefined subgraphs behave as empty subgraphs

    Future Work

      -
    • Support for HTML strings.
    • Passing port information to BGL.
    • Expanding escape codes in the same way GraphViz does.
    • -
    • Enforcement of the strict keyword (ignoring self-loops and parallel -edges).
    • Support for optional recognition of subgraphs as distinct entities.
    diff --git a/doc/read_graphviz.rst b/doc/read_graphviz.rst index 12c79298..053d1ef2 100644 --- a/doc/read_graphviz.rst +++ b/doc/read_graphviz.rst @@ -225,8 +225,6 @@ write_graphviz_ Future Work ----------- - - Support for HTML strings. - - Passing port information to BGL. - Expanding escape codes in the same way GraphViz does. diff --git a/src/read_graphviz_new.cpp b/src/read_graphviz_new.cpp index 2c5a1210..ed1d5b43 100644 --- a/src/read_graphviz_new.cpp +++ b/src/read_graphviz_new.cpp @@ -129,6 +129,8 @@ namespace read_graphviz_detail { boost::regex punctuation_token; boost::regex number_token; boost::regex quoted_string_token; + boost::regex xml_tag_token; + boost::regex cdata; tokenizer(const std::string& str) : begin(str.begin()), end(str.end()) { @@ -147,6 +149,8 @@ namespace read_graphviz_detail { punctuation_token = "\\A([][{};=,:+()@]|[-][>-])"; number_token = "\\A([-]?(?:(?:\\.\\d+)|(?:\\d+(?:\\.\\d*)?)))"; quoted_string_token = "\\A(\"(?:[^\"\\\\]|(?:[\\\\].))*\")"; + xml_tag_token = "\\A<(/?)(?:[^!?'\"]|(?:'[^']*?')|(?:\"[^\"]*?\"))*?(/?)>"; + cdata = "\\A\\Q\\E"; } void skip() { @@ -245,8 +249,33 @@ namespace read_graphviz_detail { return token(token::quoted_string, str); } if (*begin == '<') { - throw_lex_error("HTML strings not supported"); - return token(); + std::string::const_iterator saved_begin = begin; + int counter = 0; + do { + if (begin == end) throw_lex_error("Unclosed HTML string"); + if (*begin != '<') { + ++begin; + continue; + } + found = boost::regex_search(begin, end, results, xml_tag_token); + if (found) { + begin = results.suffix().first; + if (results[1].str() == "/") { // Close tag + --counter; + } else if (results[2].str() == "/") { // Empty tag + } else { // Open tag + ++counter; + } + continue; + } + found = boost::regex_search(begin, end, results, cdata); + if (found) { + begin = results.suffix().first; + continue; + } + throw_lex_error("Invalid contents in HTML string"); + } while (counter > 0); + return token(token::identifier, std::string(saved_begin, begin)); } else { throw_lex_error("Invalid character"); return token(); diff --git a/test/graphviz_test.cpp b/test/graphviz_test.cpp index 4c3a3490..d78b637b 100644 --- a/test/graphviz_test.cpp +++ b/test/graphviz_test.cpp @@ -248,6 +248,16 @@ int test_main(int, char*[]) { graph_name))); } + // Graph Property Test 3 (HTML) + { + mass_map_t masses; + 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))); + } + // Comments embedded in strings { gs_t gs( From e7054fb0905ceeedc83149a2ba1341b12072d70d Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Tue, 26 May 2009 01:13:36 +0000 Subject: [PATCH 202/224] Fixed handling of lex errors at end of input [SVN r53269] --- src/read_graphviz_new.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/read_graphviz_new.cpp b/src/read_graphviz_new.cpp index ed1d5b43..8c84b0c1 100644 --- a/src/read_graphviz_new.cpp +++ b/src/read_graphviz_new.cpp @@ -113,7 +113,11 @@ namespace read_graphviz_detail { }; bad_graphviz_syntax lex_error(const std::string& errmsg, char bad_char) { - return bad_graphviz_syntax(errmsg + " (char is '" + bad_char + "')"); + if (bad_char == '\0') { + return bad_graphviz_syntax(errmsg + " (at end of input)"); + } else { + return bad_graphviz_syntax(errmsg + " (char is '" + bad_char + "')"); + } } bad_graphviz_syntax parse_error(const std::string& errmsg, const token& bad_token) { @@ -306,7 +310,7 @@ namespace read_graphviz_detail { } void throw_lex_error(const std::string& errmsg) { - boost::throw_exception(lex_error(errmsg, *begin)); + boost::throw_exception(lex_error(errmsg, (begin == end ? '\0' : *begin))); } }; From 186d6baaaa07504c3cdafb3623af4d17e2e68330 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Tue, 26 May 2009 15:42:40 +0000 Subject: [PATCH 203/224] Added no-color-map version of Dijkstra's algorithm from Michael Hansen [SVN r53282] --- .../dijkstra_shortest_paths_no_color_map.hpp | 147 ++++++++++++++++++ 1 file changed, 147 insertions(+) create mode 100644 include/boost/graph/dijkstra_shortest_paths_no_color_map.hpp diff --git a/include/boost/graph/dijkstra_shortest_paths_no_color_map.hpp b/include/boost/graph/dijkstra_shortest_paths_no_color_map.hpp new file mode 100644 index 00000000..268a70b9 --- /dev/null +++ b/include/boost/graph/dijkstra_shortest_paths_no_color_map.hpp @@ -0,0 +1,147 @@ +//======================================================================= +// Copyright 1997, 1998, 1999, 2000 University of Notre Dame. +// Copyright 2009 Trustees of Indiana University. +// Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek, Michael Hansen +// +// 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_DIJKSTRA_NO_COLOR_MAP_HPP +#define BOOST_GRAPH_DIJKSTRA_NO_COLOR_MAP_HPP + +#include +#include +#include +#include +#include +#include + +namespace boost { + +template +void dijkstra_shortest_paths_no_color_map + (const Graph& graph, + typename graph_traits::vertex_descriptor start_vertex, + PredecessorMap predecessor_map, + DistanceMap distance_map, + WeightMap weight_map, + VertexIndexMap vertex_index_map, + DistanceCompare distance_compare, + DistanceWeightCombine distance_weight_combine, + DistanceInfinity distance_infinity, + DistanceZero distance_zero, + DijkstraVisitor visitor) +{ + 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 + distance_indirect_compare(distance_map, distance_compare); + + // Choose vertex queue type +#if BOOST_GRAPH_DIJKSTRA_USE_RELAXED_HEAP + typedef relaxed_heap + VertexQueue; + VertexQueue vertex_queue(num_vertices(graph), + distance_indirect_compare, + vertex_index_map); +#else + // Default - use d-ary heap (d = 4) + typedef + detail::vertex_property_map_generator + IndexInHeapMapHelper; + typedef typename IndexInHeapMapHelper::type IndexInHeapMap; + typedef + d_ary_heap_indirect + VertexQueue; + + boost::scoped_array index_in_heap_map_holder; + IndexInHeapMap index_in_heap = + IndexInHeapMapHelper::build(graph, vertex_index_map, + index_in_heap_map_holder); + VertexQueue vertex_queue(distance_map, index_in_heap, distance_compare); +#endif + + // Initialize vertices + BGL_FORALL_VERTICES_T(current_vertex, graph, Graph) { + visitor.initialize_vertex(current_vertex, graph); + + // Default all distances to infinity + put(distance_map, current_vertex, distance_infinity); + + // Default all vertex predecessors to the vertex itself + put(predecessor_map, current_vertex, current_vertex); + } + + // Set distance for start_vertex to zero + put(distance_map, start_vertex, distance_zero); + + // Add vertex to the queue + vertex_queue.push(start_vertex); + + // Starting vertex will always be the first discovered vertex + visitor.discover_vertex(start_vertex, graph); + + while (!vertex_queue.empty()) { + Vertex min_vertex = vertex_queue.top(); + vertex_queue.pop(); + + visitor.examine_vertex(min_vertex, graph); + + // Check if any other vertices can be reached + Distance min_vertex_distance = get(distance_map, min_vertex); + + if (!distance_compare(min_vertex_distance, distance_infinity)) { + // This is the minimum vertex, so all other vertices are unreachable + return; + } + + // Examine neighbors of min_vertex + typedef typename graph_traits::edge_descriptor Edge; + typename graph_traits::out_edge_iterator edge_iter, edge_iter_end; + BGL_FORALL_OUT_EDGES_T(current_edge, min_vertex, graph, Graph) { + visitor.examine_edge(current_edge, graph); + + // Check if the edge has a negative weight + if (distance_compare(get(weight_map, current_edge), distance_zero)) { + boost::throw_exception(negative_edge()); + } + + Vertex neighbor_vertex = target(current_edge, graph); + Distance neighbor_vertex_distance = get(distance_map, neighbor_vertex); + bool is_neighbor_undiscovered = + !distance_compare(neighbor_vertex_distance, distance_infinity); + + // Attempt to relax the edge + bool was_edge_relaxed = relax(current_edge, graph, weight_map, + predecessor_map, distance_map, + distance_weight_combine, distance_compare); + + if (was_edge_relaxed) { + vertex_queue.update(neighbor_vertex); + visitor.edge_relaxed(current_edge, graph); + } 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); + } // end while queue not empty +} + +} // namespace boost + +#endif // BOOST_GRAPH_DIJKSTRA_NO_COLOR_MAP_HPP From f8960081b27082ee7b6bb8006dbfb6973786a416 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Tue, 26 May 2009 16:10:45 +0000 Subject: [PATCH 204/224] Added no-color-map Dijkstra to test [SVN r53283] --- test/dijkstra_heap_performance.cpp | 36 ++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/test/dijkstra_heap_performance.cpp b/test/dijkstra_heap_performance.cpp index 37d1160a..0b78f740 100644 --- a/test/dijkstra_heap_performance.cpp +++ b/test/dijkstra_heap_performance.cpp @@ -11,6 +11,7 @@ #endif #include +#include #include #include #include @@ -104,6 +105,7 @@ int main(int argc, char* argv[]) std::vector binary_heap_distances(n); std::vector relaxed_heap_distances(n); + std::vector no_color_map_distances(n); // Run binary or d-ary heap version std::cout << "Running Dijkstra's with binary heap..."; @@ -141,6 +143,40 @@ int main(int argc, char* argv[]) // Verify that the results are equivalent BOOST_TEST(binary_heap_distances == relaxed_heap_distances); + // Run Michael's no-color-map version +#ifdef BOOST_GRAPH_DIJKSTRA_USE_RELAXED_HEAP + std::cout << "Running Dijkstra's (no color map) with relaxed heap..."; +#else + std::cout << "Running Dijkstra's (no color map) with d-ary heap (d=4)..."; +#endif + std::cout.flush(); + t.restart(); +#ifdef BOOST_GRAPH_DIJKSTRA_TESTING_DIETMAR + dijkstra_heap_kind = dijkstra_relaxed_heap; +#else + dijkstra_relaxed_heap = true; +#endif + dijkstra_shortest_paths_no_color_map + (g, vertex(0, g), + boost::dummy_property_map(), + boost::make_iterator_property_map(&no_color_map_distances[0], + get(boost::vertex_index, g), + 0.), + get(boost::edge_weight, g), + get(boost::vertex_index, g), + std::less(), + boost::closed_plus(), + (std::numeric_limits::max)(), + 0, + make_dijkstra_visitor(null_visitor()) + ); + double no_color_map_time = t.elapsed(); + std::cout << no_color_map_time << " seconds.\n" + << "Speedup = " << (binary_heap_time / no_color_map_time) << ".\n"; + + // Verify that the results are equivalent + BOOST_TEST(binary_heap_distances == no_color_map_distances); + #ifdef BOOST_GRAPH_DIJKSTRA_TESTING_DIETMAR run_test(g, "d-ary heap (d=2)", dijkstra_d_heap_2, binary_heap_distances); run_test(g, "d-ary heap (d=3)", dijkstra_d_heap_3, binary_heap_distances); From bec5451742e636313911af3c94b4d4c1d1d58b35 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Tue, 26 May 2009 16:11:25 +0000 Subject: [PATCH 205/224] Fixed bad syntax [SVN r53284] --- include/boost/graph/dijkstra_shortest_paths_no_color_map.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 268a70b9..9e6307b2 100644 --- a/include/boost/graph/dijkstra_shortest_paths_no_color_map.hpp +++ b/include/boost/graph/dijkstra_shortest_paths_no_color_map.hpp @@ -107,7 +107,7 @@ void dijkstra_shortest_paths_no_color_map // Examine neighbors of min_vertex typedef typename graph_traits::edge_descriptor Edge; typename graph_traits::out_edge_iterator edge_iter, edge_iter_end; - BGL_FORALL_OUT_EDGES_T(current_edge, min_vertex, graph, Graph) { + BGL_FORALL_OUTEDGES_T(min_vertex, current_edge, graph, Graph) { visitor.examine_edge(current_edge, graph); // Check if the edge has a negative weight From f72b7b9d1d2c42645a2d5796420727716e064c9a Mon Sep 17 00:00:00 2001 From: Andrew Sutton Date: Tue, 26 May 2009 20:06:07 +0000 Subject: [PATCH 206/224] Modifications to subgraph, graph testing framework. [SVN r53286] --- include/boost/graph/subgraph.hpp | 17 ++++++++++++----- test/subgraph.cpp | 24 +++++++++++++++++++++++- test/test_construction.hpp | 25 +++++++++++++++++++++++++ test/test_graph.hpp | 7 ++++++- test/test_graphs.cpp | 7 ------- 5 files changed, 66 insertions(+), 14 deletions(-) diff --git a/include/boost/graph/subgraph.hpp b/include/boost/graph/subgraph.hpp index c26f0b7d..2e5069b8 100644 --- a/include/boost/graph/subgraph.hpp +++ b/include/boost/graph/subgraph.hpp @@ -41,10 +41,9 @@ namespace boost { // assumed that the edge vertices are assigned automatically, they are // explicitly assigned here. // - // NOTE [asutton]: The requirement of internal indexing causes this to fail - // for many, many graphs (i.e., those of non-vecS storage, and using bundled - // properties). To work around this - in part - you can do the following: - + // NOTE: The requirement of internal indexing causes this to fail for many, + // many graphs (i.e., those of non-vecS storage, and using bundled + // properties). template class subgraph { typedef graph_traits Traits; @@ -682,6 +681,15 @@ namespace boost { return u_local; } + template + typename subgraph::vertex_descriptor + add_vertex(typename subgraph::vertex_property_type const& vp, + subgraph& g) + { + // UNDER CONSTRUCTION + assert(false); + } + template void remove_vertex(typename subgraph::vertex_descriptor u, subgraph& g) @@ -690,7 +698,6 @@ namespace boost { assert(false); } - //=========================================================================== // Functions required by the PropertyGraph concept diff --git a/test/subgraph.cpp b/test/subgraph.cpp index 62a2b0a9..4f538d8e 100644 --- a/test/subgraph.cpp +++ b/test/subgraph.cpp @@ -12,9 +12,10 @@ #include #include #include - #include +#include "test_graph.hpp" + // UNDER CONSTRUCTION int test_main(int argc, char* argv[]) @@ -110,6 +111,27 @@ int test_main(int argc, char* argv[]) } } + // Bootstrap the test_graph framework. + // TODO: Subgraph is fundamentally broken for property types. + // TODO: Under construction. + { + using namespace boost; + typedef property EdgeProp; + typedef adjacency_list BaseGraph; + typedef subgraph Graph; + typedef graph_traits::vertex_descriptor Vertex; + Graph g; + Vertex v = add_vertex(g); + + typedef property_map::type BundleMap; + BundleMap map = get(&VertexBundle::value, g); + get(map, v); +// put(map, v, 5); +// BOOST_ASSERT(get(map, v) == 5); + +// test_graph(g); + return 0; + } } return 0; } diff --git a/test/test_construction.hpp b/test/test_construction.hpp index 07a4d7ab..213ef037 100644 --- a/test/test_construction.hpp +++ b/test/test_construction.hpp @@ -51,6 +51,31 @@ void build_graph(Graph& g, boost::mpl::false_, boost::mpl::true_) { } //@} +/** @name Build Mutable + * For mutable property graphs, try to add a vertex with a property. This test + * actually builds a new graph - or at least tries to. We're not testing for + * labeled graphs since that's actually done in build_graph above. + */ +//@{ +template +void build_property_graph(Graph const& g, Add, Label) +{ } + +template +void build_property_graph(Graph const& g, boost::mpl::true_, boost::mpl::false_) { + using namespace boost; + BOOST_CONCEPT_ASSERT((VertexMutablePropertyGraphConcept)); + typedef typename vertex_property::type VertexProp; + + std::cout << "...build mutable\n"; + + // Start with clean graph. Nothing really to assert. Just make sure it + // copmpiles. + Graph h; + add_vertex(VertexProp(), h); +} +//@} + /** @name Connect Graph * Given a constructed graph, connect the edges to create a the standard diff --git a/test/test_graph.hpp b/test/test_graph.hpp index 2fd4c94b..826d5404 100644 --- a/test/test_graph.hpp +++ b/test/test_graph.hpp @@ -15,12 +15,15 @@ * differentiate testable features of graph instances. */ +#include "typestr.hpp" + #include #include #include +#include #include #include -#include +#include #define BOOST_META_ASSERT(x) BOOST_ASSERT(x::value) @@ -101,6 +104,7 @@ void test_graph(Graph& g) { // Test constrution and vertex list. build_graph(g, can_add_vertex, is_labeled); + build_property_graph(g, can_add_vertex, is_labeled); test_vertex_list_graph(g); // Collect the vertices for an easy method of "naming" them. @@ -114,6 +118,7 @@ void test_graph(Graph& g) { // Test connection and edge list connect_graph(g, verts, is_labeled); +// connect_property_graph(g, verts, is_labeld); test_edge_list_graph(g); // Test properties diff --git a/test/test_graphs.cpp b/test/test_graphs.cpp index c0de2a98..47b9cdbc 100644 --- a/test/test_graphs.cpp +++ b/test/test_graphs.cpp @@ -151,12 +151,5 @@ int main() Graph g; test_graph(g); } - { - typedef property EdgeProp; - typedef adjacency_list BaseGraph; - typedef subgraph Graph; - Graph g; - test_graph(g); - } } From 863b976726d28c0518c2613b5712726dab939aa7 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Tue, 26 May 2009 19:28:31 +0000 Subject: [PATCH 207/224] Fixed bug in default for distance_combine [SVN r53287] --- doc/dijkstra_shortest_paths.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/dijkstra_shortest_paths.html b/doc/dijkstra_shortest_paths.html index 57a1f778..af54435e 100644 --- a/doc/dijkstra_shortest_paths.html +++ b/doc/dijkstra_shortest_paths.html @@ -317,7 +317,7 @@ IN: distance_combine(CombineFunction cmb) WeightMap property map. The result type must be the same type as the distance value type.
    - Default: std::plus<D> with + Default: closed_plus<D> with D=typename property_traits<DistanceMap>::value_type
    Python: Unsupported parameter. From 791a5f0e724fdd1c56ad8c6e1fde0e7549d5a486 Mon Sep 17 00:00:00 2001 From: Andrew Sutton Date: Tue, 26 May 2009 22:22:55 +0000 Subject: [PATCH 208/224] Augmenting property lookup strategies for subgraphs. [SVN r53289] --- include/boost/graph/properties.hpp | 1 + include/boost/graph/subgraph.hpp | 1250 +++++++++++++++------------- test/Jamfile.v2 | 4 + 3 files changed, 699 insertions(+), 556 deletions(-) diff --git a/include/boost/graph/properties.hpp b/include/boost/graph/properties.hpp index 0f4b35c5..8c92ab0b 100644 --- a/include/boost/graph/properties.hpp +++ b/include/boost/graph/properties.hpp @@ -385,6 +385,7 @@ namespace boost { { }; } + // Specialize the property map template to generate bundled property maps. template struct property_map { diff --git a/include/boost/graph/subgraph.hpp b/include/boost/graph/subgraph.hpp index 2e5069b8..826b34e5 100644 --- a/include/boost/graph/subgraph.hpp +++ b/include/boost/graph/subgraph.hpp @@ -27,40 +27,57 @@ namespace boost { - struct subgraph_tag { }; +struct subgraph_tag { }; - // Invariants of an induced subgraph: - // - If vertex u is in subgraph g, then u must be in g.parent(). - // - If edge e is in subgraph g, then e must be in g.parent(). - // - If edge e=(u,v) is in the root graph, then edge e - // is also in any subgraph that contains both vertex u and v. +/** @name Property Lookup + * The local_property and global_property functions are used to create + * structures that determine the lookup strategy for properties in subgraphs. + */ +//@{ +template +struct local_subgraph_property { + local_subgraph_property(T x) : value(x) { } + T value; +}; - // The Graph template parameter must have a vertex_index and edge_index - // internal property. It is assumed that the vertex indices are assigned - // automatically by the graph during a call to add_vertex(). It is not - // assumed that the edge vertices are assigned automatically, they are - // explicitly assigned here. - // - // NOTE: The requirement of internal indexing causes this to fail for many, - // many graphs (i.e., those of non-vecS storage, and using bundled - // properties). - template - class subgraph { +template +inline local_subgraph_property local(T x) +{ return local_subgraph_property(x); } + +template +struct global_subgraph_property { + global_subgraph_property(T x) : value(x) { } + T value; +}; + +template +inline global_subgraph_property global(T x) +{ return global_subgraph_property(x); } +//@} + +// Invariants of an induced subgraph: +// - If vertex u is in subgraph g, then u must be in g.parent(). +// - If edge e is in subgraph g, then e must be in g.parent(). +// - If edge e=(u,v) is in the root graph, then edge e +// is also in any subgraph that contains both vertex u and v. + +// The Graph template parameter must have a vertex_index and edge_index +// internal property. It is assumed that the vertex indices are assigned +// automatically by the graph during a call to add_vertex(). It is not +// assumed that the edge vertices are assigned automatically, they are +// explicitly assigned here. + +template +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; - - static vertex_descriptor null_vertex() - { - return Traits::null_vertex(); - } - +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; // IncidenceGraph requirements typedef typename Traits::out_edge_iterator out_edge_iterator; @@ -87,117 +104,109 @@ namespace boost { typedef Graph graph_type; typedef typename Graph::graph_property_type graph_property_type; - // Constructors - // Create the main graph, the root of the subgraph tree subgraph() - : m_parent(0), m_edge_counter(0) + : m_parent(0), m_edge_counter(0) { } + subgraph(const graph_property_type& p) - : m_graph(p), m_parent(0), m_edge_counter(0) + : m_graph(p), m_parent(0), m_edge_counter(0) { } - subgraph(vertices_size_type n, - const graph_property_type& p = graph_property_type()) - : m_graph(n, p), m_parent(0), m_edge_counter(0), m_global_vertex(n) + + subgraph(vertices_size_type n, const graph_property_type& p = graph_property_type()) + : m_graph(n, p), m_parent(0), m_edge_counter(0), m_global_vertex(n) { - typename Graph::vertex_iterator v, v_end; - vertices_size_type i = 0; - for (tie(v, v_end) = vertices(m_graph); v != v_end; ++v) - m_global_vertex[i++] = *v; + typename Graph::vertex_iterator v, v_end; + vertices_size_type i = 0; + for(tie(v, v_end) = vertices(m_graph); v != v_end; ++v) + m_global_vertex[i++] = *v; } // copy constructor subgraph(const subgraph& x) - : m_graph(x.m_graph), 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) + : m_graph(x.m_graph), 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 - for (typename ChildrenList::const_iterator i = x.m_children.begin(); - i != x.m_children.end(); ++i) - m_children.push_back(new subgraph( **i )); + // Do a deep copy (recursive). + for(typename ChildrenList::const_iterator i = x.m_children.begin(); + i != x.m_children.end(); ++i) + { + m_children.push_back(new subgraph( **i )); + } } ~subgraph() { - for (typename ChildrenList::iterator i = m_children.begin(); - i != m_children.end(); ++i) - delete *i; + for(typename ChildrenList::iterator i = m_children.begin(); + i != m_children.end(); ++i) + { + delete *i; + } } + // Return a null vertex descriptor for the graph. + static vertex_descriptor null_vertex() + { return Traits::null_vertex(); } + // Create a subgraph subgraph& create_subgraph() { - m_children.push_back(new subgraph()); - m_children.back()->m_parent = this; - return *m_children.back(); + m_children.push_back(new subgraph()); + m_children.back()->m_parent = this; + return *m_children.back(); } // Create a subgraph with the specified vertex set. template - subgraph& create_subgraph(VertexIterator first, - VertexIterator last) - { - m_children.push_back(new subgraph()); - m_children.back()->m_parent = this; - for (; first != last; ++first) - add_vertex(*first, *m_children.back()); - return *m_children.back(); + subgraph& create_subgraph(VertexIterator first, VertexIterator last) { + m_children.push_back(new subgraph()); + m_children.back()->m_parent = this; + for(; first != last; ++first) { + add_vertex(*first, *m_children.back()); + } + return *m_children.back(); } // local <-> global descriptor conversion functions vertex_descriptor local_to_global(vertex_descriptor u_local) const - { - return m_global_vertex[u_local]; - } - vertex_descriptor global_to_local(vertex_descriptor u_global) const - { - vertex_descriptor u_local; bool in_subgraph; - tie(u_local, in_subgraph) = this->find_vertex(u_global); - assert(in_subgraph == true); - return u_local; + { return m_global_vertex[u_local]; } + + vertex_descriptor global_to_local(vertex_descriptor u_global) const { + vertex_descriptor u_local; bool in_subgraph; + tie(u_local, in_subgraph) = this->find_vertex(u_global); + assert(in_subgraph == true); + return u_local; } + edge_descriptor local_to_global(edge_descriptor e_local) const - { - return m_global_edge[get(get(edge_index, m_graph), e_local)]; - } + { return m_global_edge[get(get(edge_index, m_graph), e_local)]; } + edge_descriptor global_to_local(edge_descriptor e_global) const - { - return - (*m_local_edge.find(get(get(edge_index, root().m_graph), e_global))).second; - } + { return (*m_local_edge.find(get(get(edge_index, root().m_graph), e_global))).second; } // Is vertex u (of the root graph) contained in this subgraph? // If so, return the matching local vertex. std::pair - find_vertex(vertex_descriptor u_global) const - { - typename std::map::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); + find_vertex(vertex_descriptor u_global) const { + typename std::map::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); } // Return the parent graph. subgraph& parent() { return *m_parent; } const subgraph& parent() const { return *m_parent; } + // Return true if this is the root subgraph bool is_root() const { return m_parent == 0; } // Return the root graph of the subgraph tree. - subgraph& root() { - if (this->is_root()) - return *this; - else - return m_parent->root(); - } - const subgraph& root() const { - if (this->is_root()) - return *this; - else - return m_parent->root(); - } + subgraph& root() + { return is_root() ? *this : m_parent->root(); } + + const subgraph& root() const + { return is_root() ? *this : m_parent->root(); } // Return the children subgraphs of this graph/subgraph. // Use a list of pointers because the VC++ std::list doesn't like @@ -216,16 +225,12 @@ namespace boost { > const_children_iterator; - std::pair - children() const - { + std::pair children() const { return std::make_pair(const_children_iterator(m_children.begin()), const_children_iterator(m_children.end())); } - std::pair - children() - { + std::pair children() { return std::make_pair(children_iterator(m_children.begin()), children_iterator(m_children.end())); } @@ -233,22 +238,41 @@ namespace boost { std::size_t num_children() const { return m_children.size(); } #ifndef BOOST_GRAPH_NO_BUNDLED_PROPERTIES - // Bundled properties support - template + // Defualt property access delegates the lookup to global properties. + template typename graph::detail::bundled_result::type& operator[](Descriptor x) - { - if (m_parent == 0) return m_graph[x]; - else return root().m_graph[local_to_global(x)]; - } + { return is_root() ? m_graph[x] : root().m_graph[local_to_global(x)]; } - template + template typename graph::detail::bundled_result::type const& operator[](Descriptor x) const - { - if (m_parent == 0) return m_graph[x]; - else return root().m_graph[local_to_global(x)]; - } + { return is_root() ? m_graph[x] : root().m_graph[local_to_global(x)]; } + + // Local property access returns the local property of the given descripor. + template + typename graph::detail::bundled_result::type& + operator[](local_subgraph_property x) + { return m_graph[x.value]; } + + template + typename graph::detail::bundled_result::type const& + operator[](local_subgraph_property x) const + { return m_graph[x.value]; } + + // Global property access returns the global property associated with the + // given descriptor. This is an alias for the default bundled property + // access operations. + template + typename graph::detail::bundled_result::type& + operator[](global_subgraph_property x) + { return (*this)[x.value]; } + + template + typename graph::detail::bundled_result::type const& + operator[](global_subgraph_property x) const + { return (*this)[x.value]; } + #endif // BOOST_GRAPH_NO_BUNDLED_PROPERTIES // private: @@ -257,46 +281,62 @@ namespace boost { BOOST_STATIC_ASSERT((!is_same::value)); +private: + typedef std::vector GlobalVertexList; + typedef std::vector GlobalEdgeList; + typedef std::map LocalVertexMap; + typedef std::map LocalEdgeMap; + // TODO: Should the LocalVertexMap be: map? + // TODO: Can we relax the indexing requirement if both descriptors are + // LessThanComparable? + // TODO: Should we really be using unorderd_map for improved lookup times? + +public: // Probably shouldn't be public.... Graph m_graph; subgraph* m_parent; edge_index_type m_edge_counter; // for generating unique edge indices ChildrenList m_children; - std::vector m_global_vertex; // local -> global - std::map m_local_vertex; // global -> local - std::vector m_global_edge; // local -> global - std::map m_local_edge; // global -> local + GlobalVertexList m_global_vertex; // local -> global + LocalVertexMap m_local_vertex; // global -> local + GlobalEdgeList m_global_edge; // local -> global + LocalEdgeMap m_local_edge; // global -> local - edge_descriptor - local_add_edge(vertex_descriptor u_local, vertex_descriptor v_local, - edge_descriptor e_global) + edge_descriptor local_add_edge(vertex_descriptor u_local, + vertex_descriptor v_local, + edge_descriptor e_global) { - edge_descriptor e_local; - bool inserted; - tie(e_local, inserted) = add_edge(u_local, v_local, m_graph); - put(edge_index, m_graph, e_local, m_edge_counter++); - m_global_edge.push_back(e_global); - m_local_edge[get(get(edge_index, this->root()), e_global)] = e_local; - return e_local; + edge_descriptor e_local; + bool inserted; + tie(e_local, inserted) = add_edge(u_local, v_local, m_graph); + put(edge_index, m_graph, e_local, m_edge_counter++); + m_global_edge.push_back(e_global); + m_local_edge[get(get(edge_index, this->root()), e_global)] = e_local; + return e_local; } - - }; +}; #ifndef BOOST_GRAPH_NO_BUNDLED_PROPERTIES - template - struct vertex_bundle_type > : vertex_bundle_type { }; +// TODO: I don't think these are required since the default metafunction +// returns Graph::vertex_bundled. +template +struct vertex_bundle_type > + : vertex_bundle_type +{ }; - template - struct edge_bundle_type > : edge_bundle_type { }; +template +struct edge_bundle_type > + : edge_bundle_type +{ }; #endif // BOOST_GRAPH_NO_BUNDLED_PROPERTIES - //=========================================================================== - // Functions special to the Subgraph Class +//=========================================================================== +// Functions special to the Subgraph Class - template - typename subgraph::vertex_descriptor - add_vertex(typename subgraph::vertex_descriptor u_global, - subgraph& g) - { +template +typename subgraph::vertex_descriptor +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::edge_descriptor e_global; @@ -309,167 +349,163 @@ namespace boost { // remember edge global and local maps { - typename subgraph::out_edge_iterator ei, ei_end; - for (tie(ei, ei_end) = out_edges(u_global, r); - ei != ei_end; ++ei) { - e_global = *ei; - v_global = target(e_global, r); - if (g.find_vertex(v_global).second == true) - g.local_add_edge(u_local, g.global_to_local(v_global), e_global); - } + typename subgraph::out_edge_iterator ei, ei_end; + for (tie(ei, ei_end) = out_edges(u_global, r); + ei != ei_end; ++ei) { + e_global = *ei; + v_global = target(e_global, r); + if (g.find_vertex(v_global).second == true) + g.local_add_edge(u_local, g.global_to_local(v_global), e_global); + } } if (is_directed(g)) { // not necessary for undirected graph - typename subgraph::vertex_iterator vi, vi_end; - typename subgraph::out_edge_iterator ei, ei_end; - for (tie(vi, vi_end) = vertices(r); vi != vi_end; ++vi) { - v_global = *vi; - if (g.find_vertex(v_global).second) - for (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) - g.local_add_edge(g.global_to_local(v_global), u_local, e_global); - } - } + typename subgraph::vertex_iterator vi, vi_end; + typename subgraph::out_edge_iterator ei, ei_end; + for(tie(vi, vi_end) = vertices(r); vi != vi_end; ++vi) { + v_global = *vi; + if(g.find_vertex(v_global).second) + for(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) { + g.local_add_edge(g.global_to_local(v_global), u_local, e_global); + } + } + } } return u_local; - } +} - //=========================================================================== - // Functions required by the IncidenceGraph concept +// NOTE: Descriptors are local unless otherwise noted. - template - std::pair::out_edge_iterator, - typename graph_traits::out_edge_iterator> - out_edges(typename graph_traits::vertex_descriptor u_local, - const subgraph& g) - { return out_edges(u_local, g.m_graph); } +//=========================================================================== +// Functions required by the IncidenceGraph concept - template - typename graph_traits::degree_size_type - out_degree(typename graph_traits::vertex_descriptor u_local, - const subgraph& g) - { return out_degree(u_local, g.m_graph); } +template +std::pair::out_edge_iterator, + typename graph_traits::out_edge_iterator> +out_edges(typename graph_traits::vertex_descriptor v, const subgraph& g) +{ return out_edges(v, g.m_graph); } - template - typename graph_traits::vertex_descriptor - source(typename graph_traits::edge_descriptor e_local, - const subgraph& g) - { return source(e_local, g.m_graph); } +template +typename graph_traits::degree_size_type +out_degree(typename graph_traits::vertex_descriptor v, const subgraph& g) +{ return out_degree(v, g.m_graph); } - template - typename graph_traits::vertex_descriptor - target(typename graph_traits::edge_descriptor e_local, - const subgraph& g) - { return target(e_local, g.m_graph); } +template +typename graph_traits::vertex_descriptor +source(typename graph_traits::edge_descriptor e, const subgraph& g) +{ return source(e, g.m_graph); } - //=========================================================================== - // Functions required by the BidirectionalGraph concept +template +typename graph_traits::vertex_descriptor +target(typename graph_traits::edge_descriptor e, const subgraph& g) +{ return target(e, g.m_graph); } - template - std::pair::in_edge_iterator, - typename graph_traits::in_edge_iterator> - in_edges(typename graph_traits::vertex_descriptor u_local, - const subgraph& g) - { return in_edges(u_local, g.m_graph); } +//=========================================================================== +// Functions required by the BidirectionalGraph concept - template - typename graph_traits::degree_size_type - in_degree(typename graph_traits::vertex_descriptor u_local, - const subgraph& g) - { return in_degree(u_local, g.m_graph); } +template +std::pair::in_edge_iterator, + typename graph_traits::in_edge_iterator> +in_edges(typename graph_traits::vertex_descriptor v, const subgraph& g) +{ return in_edges(v, g.m_graph); } - template - typename graph_traits::degree_size_type - degree(typename graph_traits::vertex_descriptor u_local, - const subgraph& g) - { return degree(u_local, g.m_graph); } +template +typename graph_traits::degree_size_type +in_degree(typename graph_traits::vertex_descriptor v, const subgraph& g) +{ return in_degree(v, g.m_graph); } - //=========================================================================== - // Functions required by the AdjacencyGraph concept +template +typename graph_traits::degree_size_type +degree(typename graph_traits::vertex_descriptor v, const subgraph& g) +{ return degree(v, g.m_graph); } - template - std::pair::adjacency_iterator, - typename subgraph::adjacency_iterator> - adjacent_vertices(typename subgraph::vertex_descriptor u_local, - const subgraph& g) - { return adjacent_vertices(u_local, g.m_graph); } +//=========================================================================== +// Functions required by the AdjacencyGraph concept - //=========================================================================== - // Functions required by the VertexListGraph concept +template +std::pair::adjacency_iterator, + typename subgraph::adjacency_iterator> +adjacent_vertices(typename subgraph::vertex_descriptor v, const subgraph& g) +{ return adjacent_vertices(v, g.m_graph); } - template - std::pair::vertex_iterator, - typename subgraph::vertex_iterator> - vertices(const subgraph& g) - { return vertices(g.m_graph); } +//=========================================================================== +// Functions required by the VertexListGraph concept - template - typename subgraph::vertices_size_type - num_vertices(const subgraph& g) - { return num_vertices(g.m_graph); } +template +std::pair::vertex_iterator, + typename subgraph::vertex_iterator> +vertices(const subgraph& g) +{ return vertices(g.m_graph); } - //=========================================================================== - // Functions required by the EdgeListGraph concept +template +typename subgraph::vertices_size_type +num_vertices(const subgraph& g) +{ return num_vertices(g.m_graph); } - template - std::pair::edge_iterator, - typename subgraph::edge_iterator> - edges(const subgraph& g) - { return edges(g.m_graph); } +//=========================================================================== +// Functions required by the EdgeListGraph concept - template - typename subgraph::edges_size_type - num_edges(const subgraph& g) - { return num_edges(g.m_graph); } +template +std::pair::edge_iterator, + typename subgraph::edge_iterator> +edges(const subgraph& g) +{ return edges(g.m_graph); } - //=========================================================================== - // Functions required by the AdjacencyMatrix concept +template +typename subgraph::edges_size_type +num_edges(const subgraph& g) +{ return num_edges(g.m_graph); } - template - std::pair::edge_descriptor, bool> - edge(typename subgraph::vertex_descriptor u_local, - typename subgraph::vertex_descriptor v_local, - const subgraph& g) - { - return edge(u_local, v_local, g.m_graph); - } +//=========================================================================== +// Functions required by the AdjacencyMatrix concept - //=========================================================================== - // Functions required by the MutableGraph concept +template +std::pair::edge_descriptor, bool> +edge(typename subgraph::vertex_descriptor u, + typename subgraph::vertex_descriptor v, + const subgraph& g) +{ return edge(u, v, g.m_graph); } - namespace detail { +//=========================================================================== +// Functions required by the MutableGraph concept + +namespace detail { template - void add_edge_recur_down - (Vertex u_global, Vertex v_global, Edge e_global, subgraph& g); + void add_edge_recur_down(Vertex u_global, Vertex v_global, Edge e_global, + subgraph& g); template void children_add_edge(Vertex u_global, Vertex v_global, Edge e_global, Children& c, subgraph* orig) { - for (typename Children::iterator i = c.begin(); i != c.end(); ++i) - if ((*i)->find_vertex(u_global).second - && (*i)->find_vertex(v_global).second) - add_edge_recur_down(u_global, v_global, e_global, **i, orig); + for(typename Children::iterator i = c.begin(); i != c.end(); ++i) { + if ((*i)->find_vertex(u_global).second && + (*i)->find_vertex(v_global).second) + { + add_edge_recur_down(u_global, v_global, e_global, **i, orig); + } + } } template - void add_edge_recur_down - (Vertex u_global, Vertex v_global, Edge e_global, subgraph& g, - subgraph* orig) + void add_edge_recur_down(Vertex u_global, Vertex v_global, Edge e_global, + subgraph& g, subgraph* orig) { - if (&g != orig ) { - // add local edge only if u_global and v_global are in subgraph g - Vertex u_local, v_local; - bool u_in_subgraph, v_in_subgraph; - tie(u_local, u_in_subgraph) = g.find_vertex(u_global); - tie(v_local, v_in_subgraph) = g.find_vertex(v_global); - if (u_in_subgraph && v_in_subgraph) - g.local_add_edge(u_local, v_local, e_global); - } - children_add_edge(u_global, v_global, e_global, g.m_children, orig); + if(&g != orig ) { + // add local edge only if u_global and v_global are in subgraph g + Vertex u_local, v_local; + bool u_in_subgraph, v_in_subgraph; + tie(u_local, u_in_subgraph) = g.find_vertex(u_global); + tie(v_local, v_in_subgraph) = g.find_vertex(v_global); + if(u_in_subgraph && v_in_subgraph) { + g.local_add_edge(u_local, v_local, e_global); + } + } + children_add_edge(u_global, v_global, e_global, g.m_children, orig); } template @@ -478,58 +514,57 @@ namespace boost { const typename Graph::edge_property_type& ep, subgraph& g, subgraph* orig) { - if (g.is_root()) { - typename subgraph::edge_descriptor e_global; + if(g.is_root()) { + typename subgraph::edge_descriptor e_global; + bool inserted; + tie(e_global, inserted) = add_edge(u_global, v_global, ep, g.m_graph); + put(edge_index, g.m_graph, e_global, g.m_edge_counter++); + g.m_global_edge.push_back(e_global); + children_add_edge(u_global, v_global, e_global, g.m_children, orig); + return std::make_pair(e_global, inserted); + } else { + return add_edge_recur_up(u_global, v_global, ep, *g.m_parent, orig); + } + } + +} // namespace detail + +// Add an edge to the subgraph g, specified by the local vertex descriptors u +// and v. In addition, the edge will be added to any (all) other subgraphs that +// contain vertex descriptors u and v. + +template +std::pair::edge_descriptor, bool> +add_edge(typename subgraph::vertex_descriptor u, + typename subgraph::vertex_descriptor v, + const typename G::edge_property_type& ep, + subgraph& g) +{ + if (g.is_root()) { + // u and v are really global + return detail::add_edge_recur_up(u, v, ep, g, &g); + } else { + typename subgraph::edge_descriptor e_local, e_global; bool inserted; - tie(e_global, inserted) = add_edge(u_global, v_global, ep, g.m_graph); - put(edge_index, g.m_graph, e_global, g.m_edge_counter++); - g.m_global_edge.push_back(e_global); - children_add_edge(u_global, v_global, e_global, g.m_children, orig); - return std::make_pair(e_global, inserted); - } else - return add_edge_recur_up(u_global, v_global, ep, *g.m_parent, orig); + tie(e_global, inserted) = + detail::add_edge_recur_up(g.local_to_global(u), + g.local_to_global(v), + ep, g, &g); + e_local = g.local_add_edge(u, v, e_global); + return std::make_pair(e_local, inserted); } +} - } // namespace detail - - // Add an edge to the subgraph g, specified by the local vertex - // descriptors u and v. In addition, the edge will be added to any - // other subgraphs which contain vertex descriptors u and v. - - template - std::pair::edge_descriptor, bool> - add_edge(typename subgraph::vertex_descriptor u_local, - typename subgraph::vertex_descriptor v_local, - const typename G::edge_property_type& ep, - subgraph& g) - { - if (g.is_root()) // u_local and v_local are really global - return detail::add_edge_recur_up(u_local, v_local, ep, g, &g); - else { - typename subgraph::edge_descriptor e_local, e_global; - bool inserted; - tie(e_global, inserted) = detail::add_edge_recur_up - (g.local_to_global(u_local), g.local_to_global(v_local), ep, g, &g); - e_local = g.local_add_edge(u_local, v_local, e_global); - return std::make_pair(e_local, inserted); - } - } - - template - std::pair::edge_descriptor, bool> - add_edge(typename subgraph::vertex_descriptor u, - typename subgraph::vertex_descriptor v, - subgraph& g) - { - typename G::edge_property_type ep; - return add_edge(u, v, ep, g); - } - - namespace detail { +template +std::pair::edge_descriptor, bool> +add_edge(typename subgraph::vertex_descriptor u, + typename subgraph::vertex_descriptor v, + subgraph& g) +{ return add_edge(u, v, typename G::edge_property_type(), g); } +namespace detail { //------------------------------------------------------------------------- // implementation of remove_edge(u,v,g) - template void remove_edge_recur_down(Vertex u_global, Vertex v_global, subgraph& g); @@ -538,378 +573,481 @@ namespace boost { void children_remove_edge(Vertex u_global, Vertex v_global, Children& c) { - for (typename Children::iterator i = c.begin(); i != c.end(); ++i) - if ((*i)->find_vertex(u_global).second - && (*i)->find_vertex(v_global).second) - remove_edge_recur_down(u_global, v_global, **i); + for(typename Children::iterator i = c.begin(); i != c.end(); ++i) { + if((*i)->find_vertex(u_global).second && + (*i)->find_vertex(v_global).second) + { + remove_edge_recur_down(u_global, v_global, **i); + } + } } template void remove_edge_recur_down(Vertex u_global, Vertex v_global, subgraph& g) { - Vertex u_local, v_local; - u_local = g.m_local_vertex[u_global]; - v_local = g.m_local_vertex[v_global]; - remove_edge(u_local, v_local, g.m_graph); - children_remove_edge(u_global, v_global, g.m_children); + Vertex u_local, v_local; + u_local = g.m_local_vertex[u_global]; + v_local = g.m_local_vertex[v_global]; + remove_edge(u_local, v_local, g.m_graph); + children_remove_edge(u_global, v_global, g.m_children); } template void remove_edge_recur_up(Vertex u_global, Vertex v_global, subgraph& g) { - if (g.is_root()) { - remove_edge(u_global, v_global, g.m_graph); - children_remove_edge(u_global, v_global, g.m_children); - } else - remove_edge_recur_up(u_global, v_global, *g.m_parent); + if(g.is_root()) { + remove_edge(u_global, v_global, g.m_graph); + children_remove_edge(u_global, v_global, g.m_children); + } else { + remove_edge_recur_up(u_global, v_global, *g.m_parent); + } } //------------------------------------------------------------------------- // implementation of remove_edge(e,g) - template void remove_edge_recur_down(Edge e_global, subgraph& g); 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); + 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); + } + } } 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); + 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); + 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); + } } - } // namespace detail +} // namespace detail - template - void - remove_edge(typename subgraph::vertex_descriptor u_local, - typename subgraph::vertex_descriptor v_local, - subgraph& g) - { - if (g.is_root()) - detail::remove_edge_recur_up(u_local, v_local, g); - else - detail::remove_edge_recur_up(g.local_to_global(u_local), - g.local_to_global(v_local), g); - } +template +void +remove_edge(typename subgraph::vertex_descriptor u, + typename subgraph::vertex_descriptor v, + subgraph& g) +{ + if(g.is_root()) { + detail::remove_edge_recur_up(u, v, g); + } else { + detail::remove_edge_recur_up(g.local_to_global(u), + g.local_to_global(v), g); + } +} - template - void - remove_edge(typename subgraph::edge_descriptor e_local, - subgraph& g) - { - if (g.is_root()) - detail::remove_edge_recur_up(e_local, g); - else - detail::remove_edge_recur_up(g.local_to_global(e_local), g); - } +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); + } +} - template - void - remove_edge_if(Predicate p, subgraph& g) - { - // This is wrong... - remove_edge_if(p, g.m_graph); - } +// TODO: This is wrong... +template +void +remove_edge_if(Predicate p, subgraph& g) +{ remove_edge_if(p, g.m_graph); } - template - void - clear_vertex(typename subgraph::vertex_descriptor v_local, - subgraph& g) - { - // this is wrong... - clear_vertex(v_local, g.m_graph); - } - - namespace detail { +// TODO: Ths is wrong +template +void +clear_vertex(typename subgraph::vertex_descriptor v, subgraph& g) +{ clear_vertex(v, g.m_graph); } +namespace detail { template typename subgraph::vertex_descriptor add_vertex_recur_up(subgraph& g) { - typename subgraph::vertex_descriptor u_local, u_global; - if (g.is_root()) { + typename subgraph::vertex_descriptor u_local, u_global; + if (g.is_root()) { + u_global = add_vertex(g.m_graph); + g.m_global_vertex.push_back(u_global); + } else { + u_global = add_vertex_recur_up(*g.m_parent); + u_local = add_vertex(g.m_graph); + g.m_global_vertex.push_back(u_global); + g.m_local_vertex[u_global] = u_local; + } + return u_global; + } +} // namespace detail + +template +typename subgraph::vertex_descriptor +add_vertex(subgraph& g) +{ + typename subgraph::vertex_descriptor u_local, u_global; + if(g.is_root()) { u_global = add_vertex(g.m_graph); g.m_global_vertex.push_back(u_global); - } else { - u_global = add_vertex_recur_up(*g.m_parent); + u_local = u_global; + } else { + u_global = detail::add_vertex_recur_up(g.parent()); u_local = add_vertex(g.m_graph); g.m_global_vertex.push_back(u_global); g.m_local_vertex[u_global] = u_local; - } - return u_global; - } - - } // namespace detail - - template - typename subgraph::vertex_descriptor - add_vertex(subgraph& g) - { - typename subgraph::vertex_descriptor u_local, u_global; - if (g.is_root()) { - u_global = add_vertex(g.m_graph); - g.m_global_vertex.push_back(u_global); - u_local = u_global; - } else { - u_global = detail::add_vertex_recur_up(g.parent()); - u_local = add_vertex(g.m_graph); - g.m_global_vertex.push_back(u_global); - g.m_local_vertex[u_global] = u_local; } return u_local; - } +} - template - typename subgraph::vertex_descriptor - add_vertex(typename subgraph::vertex_property_type const& vp, - subgraph& g) - { - // UNDER CONSTRUCTION - assert(false); - } - template - void remove_vertex(typename subgraph::vertex_descriptor u, - subgraph& g) - { - // UNDER CONSTRUCTION - assert(false); - } +// TODO: Under Construction +template +void remove_vertex(typename subgraph::vertex_descriptor u, subgraph& g) +{ assert(false); } - //=========================================================================== - // Functions required by the PropertyGraph concept +//=========================================================================== +// Functions required by the PropertyGraph concept - template - class subgraph_global_property_map +/** + * The global property map returns the global properties associated with local + * descriptors. + */ +template +class subgraph_global_property_map : public put_get_helper< typename property_traits::reference, - subgraph_global_property_map > - { + subgraph_global_property_map + > +{ typedef property_traits Traits; - public: +public: typedef typename Traits::category category; typedef typename Traits::value_type value_type; typedef typename Traits::key_type key_type; typedef typename Traits::reference reference; - subgraph_global_property_map() { } + subgraph_global_property_map() + { } subgraph_global_property_map(GraphPtr g) - : m_g(g) { } + : m_g(g) + { } - inline reference operator[](key_type e_local) const { - PropertyMap pmap = get(Tag(), m_g->root().m_graph); - if (m_g->m_parent == 0) - return pmap[e_local]; - else - return pmap[m_g->local_to_global(e_local)]; + reference operator[](key_type e) const { + PropertyMap pmap = get(Tag(), m_g->root().m_graph); + return m_g->is_root() + ? pmap[e] + : pmap[m_g->local_to_global(e)]; } - GraphPtr m_g; - }; - template - class subgraph_local_property_map + GraphPtr m_g; +}; + +/** + * The local property map returns the local property associated with the local + * descriptors. + */ +template +class subgraph_local_property_map : public put_get_helper< typename property_traits::reference, - subgraph_local_property_map > - { + subgraph_local_property_map + > +{ typedef property_traits Traits; - public: +public: typedef typename Traits::category category; typedef typename Traits::value_type value_type; typedef typename Traits::key_type key_type; typedef typename Traits::reference reference; - subgraph_local_property_map() { } + subgraph_local_property_map() + { } subgraph_local_property_map(GraphPtr g) - : m_g(g) { } + : m_g(g) + { } - inline reference operator[](key_type e_local) const { - PropertyMap pmap = get(Tag(), *m_g); - return pmap[e_local]; + reference operator[](key_type e) const { + PropertyMap pmap = get(Tag(), *m_g); + return pmap[e]; } + GraphPtr m_g; - }; +}; - namespace detail { +namespace detail { + struct subgraph_global_pmap { + template + class bind_ { + typedef typename SubGraph::graph_type Graph; + typedef SubGraph* SubGraphPtr; + typedef const SubGraph* const_SubGraphPtr; + typedef typename property_map::type PMap; + typedef typename property_map::const_type const_PMap; + public: + typedef subgraph_global_property_map type; + typedef subgraph_global_property_map + const_type; + }; + }; - struct subgraph_any_pmap { - template - class bind_ { - typedef typename SubGraph::graph_type Graph; - typedef SubGraph* SubGraphPtr; - typedef const SubGraph* const_SubGraphPtr; - typedef typename property_map::type PMap; - typedef typename property_map::const_type const_PMap; - public: - typedef subgraph_global_property_map type; - typedef subgraph_global_property_map - const_type; - }; - }; - struct subgraph_id_pmap { - template - struct bind_ { - typedef typename SubGraph::graph_type Graph; - typedef SubGraph* SubGraphPtr; - typedef const SubGraph* const_SubGraphPtr; - typedef typename property_map::type PMap; - typedef typename property_map::const_type const_PMap; - public: - typedef subgraph_local_property_map type; - typedef subgraph_local_property_map - const_type; - }; + struct subgraph_local_pmap { + template + struct bind_ { + typedef typename SubGraph::graph_type Graph; + typedef SubGraph* SubGraphPtr; + typedef const SubGraph* const_SubGraphPtr; + typedef typename property_map::type PMap; + typedef typename property_map::const_type const_PMap; + public: + typedef subgraph_local_property_map type; + typedef subgraph_local_property_map + const_type; + }; }; + + // These metafunctions select the corresponding metafunctions above, and + // are used by the choose_pmap metafunction below to specialize the choice + // of local/global property map. template struct subgraph_choose_pmap_helper { - typedef subgraph_any_pmap type; + typedef subgraph_global_pmap type; }; template <> struct subgraph_choose_pmap_helper { - typedef subgraph_id_pmap type; + typedef subgraph_local_pmap type; }; + + // Determine the kind of property. If SameType, then + // the property lookup is always local. Otherwise, the lookup is global. template struct subgraph_choose_pmap { - typedef typename subgraph_choose_pmap_helper::type Helper; - typedef typename Helper::template bind_ Bind; - typedef typename Bind::type type; - typedef typename Bind::const_type const_type; + typedef typename subgraph_choose_pmap_helper::type Helper; + typedef typename Helper::template bind_ Bind; + typedef typename Bind::type type; + typedef typename Bind::const_type const_type; }; + + // Used by the vertex/edge property selectors to determine the kind(s) of + // property maps used by the property_map type generator. struct subgraph_property_generator { - template - struct bind_ { - typedef subgraph_choose_pmap Choice; - typedef typename Choice::type type; - typedef typename Choice::const_type const_type; - }; + template + struct bind_ { + typedef subgraph_choose_pmap Choice; + typedef typename Choice::type type; + typedef typename Choice::const_type const_type; + }; }; } // namespace detail - template <> - struct vertex_property_selector { +template <> +struct vertex_property_selector { typedef detail::subgraph_property_generator type; - }; +}; - template <> - struct edge_property_selector { +template <> +struct edge_property_selector { typedef detail::subgraph_property_generator type; - }; +}; - template - typename property_map< subgraph, Property>::type - get(Property, subgraph& g) - { +#ifndef BOOST_GRAPH_NO_BUNDLED_PROPERTIES +template +struct subgraph_local_bundle_property_map + : put_get_helper< + T&, + subgraph_local_bundle_property_map + > +{ + typedef Descriptor key_type; + typedef typename remove_const::type value_type; + typedef T& reference; + typedef lvalue_property_map_tag category; + + subgraph_local_bundle_property_map() + { } + + subgraph_local_bundle_property_map(Graph* g, T Bundle::* p) + : m_g(g), m_prop(p) + { } + + reference operator[](key_type k) const + { return (*m_g)[local(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. + +template +struct property_map, local_subgraph_property > +{ +private: + 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_c< + detail::is_vertex_bundle::value, + typename Traits::vertex_descriptor, + typename Traits::edge_descriptor + >::type Desc; + + // Deduce the bundled property type + typedef typename mpl::if_c< + detail::is_vertex_bundle::value, + VertBundled, + EdgeBundled + >::type Prop; +public: + typedef subgraph_local_bundle_property_map type; + typedef subgraph_local_bundle_property_map const_type; +}; +#endif + +template +typename property_map, Property>::type +get(Property, subgraph& g) { typedef typename property_map< subgraph, Property>::type PMap; return PMap(&g); - } +} - template - typename property_map< subgraph, Property>::const_type - get(Property, const subgraph& g) - { +template +typename property_map, Property>::const_type +get(Property, const subgraph& g) { typedef typename property_map< subgraph, Property>::const_type PMap; return PMap(&g); - } +} - template - typename property_traits< - typename property_map< subgraph, Property>::const_type - >::value_type - get(Property, const subgraph& g, const Key& k) - { +template +typename property_traits< + typename property_map, Property>::const_type +>::value_type +get(Property, const subgraph& g, const Key& k) { typedef typename property_map< subgraph, Property>::const_type PMap; PMap pmap(&g); return pmap[k]; - } +} #ifndef BOOST_GRAPH_NO_BUNDLED_PROPERTIES - 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::*>::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 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 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); } + +// ========================================================= +// Localized bundled, get + +template +inline typename property_map< + subgraph, local_subgraph_property +>::type +get(local_subgraph_property p, subgraph& g) { + typedef typename property_map< + subgraph, local_subgraph_property + >::type Map; + return Map(&g, p.value); +} + +template +inline typename property_map< + subgraph, local_subgraph_property +>::const_type +get(local_subgraph_property p, subgraph const& g) { + typedef typename property_map< + subgraph, local_subgraph_property + >::const_type Map; + return Map(&g, p.value); +} + +template +inline Type get(local_subgraph_property p, + subgraph const& g, + Key const& k) +{ return get(get(p, g), k); } - template < - typename Graph, typename Type, typename Bundle, typename Key, - typename Value> - inline void put(Type Bundle::* p, Graph& g, Key const& k, Value const& v) - { put(get(p, g), k, v); } #endif - template - void put(Property, subgraph& g, const Key& k, const Value& val) { +template +void put(Property, subgraph& g, const Key& k, const Value& val) { typedef typename property_map< subgraph, Property>::type PMap; PMap pmap(&g); pmap[k] = val; - } +} - template - inline typename graph_property::type& - get_property(subgraph& g, Tag tag) { +template +inline typename graph_property::type& +get_property(subgraph& g, Tag tag) { return get_property(g.m_graph, tag); - } +} - template - inline const typename graph_property::type& - get_property(const subgraph& g, Tag tag) { +template +inline const typename graph_property::type& +get_property(const subgraph& g, Tag tag) { return get_property(g.m_graph, tag); - } +} - //=========================================================================== - // Miscellaneous Functions +//=========================================================================== +// Miscellaneous Functions - template - typename subgraph::vertex_descriptor - vertex(typename subgraph::vertices_size_type n, const subgraph& g) - { - return vertex(n, g.m_graph); - } +template +typename subgraph::vertex_descriptor +vertex(typename subgraph::vertices_size_type n, const subgraph& g) +{ return vertex(n, g.m_graph); } - //=========================================================================== - // Mutability Traits - // Just pull the mutability traits form the underlying graph. Note that this - // will probably fail (badly) for labeled graphs. - template - struct graph_mutability_traits< subgraph > { - typedef typename graph_mutability_traits::category category; - }; +//=========================================================================== +// Mutability Traits +// Just pull the mutability traits form the underlying graph. Note that this +// will probably fail (badly) for labeled graphs. +template +struct graph_mutability_traits< subgraph > { + typedef typename graph_mutability_traits::category category; +}; } // namespace boost diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index e87f7a9e..b1a8776c 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -70,8 +70,12 @@ test-suite graph_test : [ compile reverse_graph_cc.cpp ] [ run sequential_vertex_coloring.cpp ] + + # TODO: Merge these into a single test framework. [ run subgraph.cpp ../../test/build//boost_test_exec_monitor ] [ run subgraph_bundled.cpp ] + [ run subgraph_props.cpp ] + [ run isomorphism.cpp ../../test/build//boost_test_exec_monitor ] [ run adjacency_matrix_test.cpp ] [ compile vector_graph_cc.cpp ] From 686376231a9178bb3ad137d97127f9ac81a35206 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Wed, 27 May 2009 20:54:24 +0000 Subject: [PATCH 209/224] Added more updates, docs, and tests from Michael Hansen [SVN r53327] --- doc/dijkstra_shortest_paths.html | 1 + doc/dijkstra_shortest_paths_no_color_map.html | 397 ++++++++++++++++++ doc/table_of_contents.html | 1 + example/dijkstra-no-color-map-example.cpp | 99 +++++ .../dijkstra_shortest_paths_no_color_map.hpp | 327 ++++++++++----- test/Jamfile.v2 | 1 + test/dijkstra_no_color_map_compare.cpp | 124 ++++++ 7 files changed, 838 insertions(+), 112 deletions(-) create mode 100644 doc/dijkstra_shortest_paths_no_color_map.html create mode 100644 example/dijkstra-no-color-map-example.cpp create mode 100644 test/dijkstra_no_color_map_compare.cpp diff --git a/doc/dijkstra_shortest_paths.html b/doc/dijkstra_shortest_paths.html index af54435e..c9a8bda0 100644 --- a/doc/dijkstra_shortest_paths.html +++ b/doc/dijkstra_shortest_paths.html @@ -19,6 +19,7 @@ dijkstra_shortest_paths +

    See also dijkstra_shortest_paths_no_color_map

    diff --git a/doc/dijkstra_shortest_paths_no_color_map.html b/doc/dijkstra_shortest_paths_no_color_map.html
    new file mode 100644
    index 00000000..e7358a1c
    --- /dev/null
    +++ b/doc/dijkstra_shortest_paths_no_color_map.html
    @@ -0,0 +1,397 @@
    +
    +
    +
    +Boost Graph Library: Dijkstra's Shortest Paths (No Color Map)
    + 
    +C++ Boost 
    +
    +
    + +

    +dijkstra_shortest_paths_no_color_map +

    + +

    See also dijkstra_shortest_paths + +

    +

    +// named parameter version
    +template <typename Graph, typename Param, typename Tag, typename Rest>
    +void dijkstra_shortest_paths_no_color_map
    +  (const Graph& graph,
    +   typename graph_traits<Graph>::vertex_descriptor start_vertex,
    +   const bgl_named_params& params);
    +   
    +// non-named parameter version
    +template <typename Graph, typename DijkstraVisitor, 
    +	  typename PredecessorMap, typename DistanceMap,
    +	  typename WeightMap, typename VertexIndexMap, typename DistanceCompare, typename DistanceWeightCombine, 
    +	  typename DistanceInfinity, typename DistanceZero>
    +void dijkstra_shortest_paths_no_color_map
    +  (const Graph& graph,
    +   typename graph_traits<Graph>::vertex_descriptor start_vertex, 
    +   PredecessorMap predecessor_map, DistanceMap distance_map, WeightMap weight_map, 
    +   VertexIndexMap index_map,
    +   DistanceCompare distance_compare, DistanceWeightCombine distance_weight_combine,
    +   DistanceInfinity distance_infinity, DistanceZero distance_zero);
    +
    +// version that does not initialize the property maps
    +template <typename Graph, typename DijkstraVisitor, 
    +	  typename PredecessorMap, typename DistanceMap,
    +	  typename WeightMap, typename VertexIndexMap, typename DistanceCompare, typename DistanceWeightCombine, 
    +	  typename DistanceInfinity, typename DistanceZero>
    +void dijkstra_shortest_paths_no_color_map_no_init
    +  (const Graph& graph,
    +   typename graph_traits<Graph>::vertex_descriptor start_vertex, 
    +   PredecessorMap predecessor_map, DistanceMap distance_map, WeightMap weight_map, 
    +   VertexIndexMap index_map,
    +   DistanceCompare distance_compare, DistanceWeightCombine distance_weight_combine,
    +   DistanceInfinity distance_infinity, DistanceZero distance_zero);
    +
    + +

    +This algorithm [10,8] solves the single-source +shortest-paths problem on a weighted, directed or undirected graph for +the case where all edge weights are nonnegative. Use the Bellman-Ford +algorithm for the case when some edge weights are negative. Use +breadth-first search instead of Dijkstra's algorithm when all edge +weights are equal to one. For the definition of the shortest-path +problem see Section Shortest-Paths +Algorithms for some background to the shortest-path problem. +

    + +

    +There are two main options for obtaining output from the +dijkstra_shortest_paths_no_color_map() function. If you provide a +distance property map through the distance_map() parameter +then the shortest distance from the start vertex to every other +vertex in the graph will be recorded in the distance map. Also you can +record the shortest paths tree in a predecessor map: for each vertex +u in V, p[u] will be the predecessor of u in +the shortest paths tree (unless p[u] = u, in which case u is +either the source or a vertex unreachable from the source). In +addition to these two options, the user can provide their own +custom-made visitor that takes actions during any of the +algorithm's event points.

    + +

    +Dijkstra's algorithm finds all the shortest paths from the source +vertex to every other vertex by iteratively "growing" the set of +vertices S to which it knows the shortest path. At each step of +the algorithm, the next vertex added to S is determined by a +priority queue. The queue contains the vertices in V - S[1] prioritized by their distance label, which is the +length of the shortest path seen so far for each vertex. The vertex +u at the top of the priority queue is then added to S, +and each of its out-edges is relaxed: if the distance to u plus +the weight of the out-edge (u,v) is less than the distance +label for v then the estimated distance for vertex v is +reduced. The algorithm then loops back, processing the next vertex at +the top of the priority queue. The algorithm finishes when the +priority queue is empty. +

    +

    +The algorithm uses the distance map to keep +track of which set each vertex is in. Vertices with a non-infinite distance are in +S. Vertices with an infinite distance are in V-S and have +not yet been discovered. +

    +

    +The following is the pseudo-code for Dijkstra's single-source shortest +paths algorithm. w is the edge weight, d is the distance label, +and p is the predecessor of each vertex which is used to encode +the shortest paths tree. Q is a priority queue that supports the +DECREASE-KEY operation. The visitor event points for the algorithm are +indicated by the labels on the right. +

    + + + + + + +
    +
    +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 != Ø)
    +    u := EXTRACT-MIN(Q)
    +    for each vertex v in Adj[u]
    +      if (w(u,v) + d[u] < d[v])
    +        d[v] := w(u,v) + d[u]
    +        p[v] := u 
    +        DECREASE-KEY(Q, v)
    +      else
    +      	...
    +      if (d[v] was originally infinity) 
    +        INSERT(Q, v)   
    +    end for
    +  end while
    +  return (d, p)
    +
    +
    +
    +
    +initialize vertex u
    +
    +
    +
    +
    +discover vertex s
    +
    +examine vertex u
    +examine edge (u,v)
    +
    +edge (u,v) relaxed
    +
    +
    +
    +edge (u,v) not relaxed
    +
    +discover vertex v
    +finish vertex u
    +
    +
    + +

    Where Defined

    + +boost/graph/dijkstra_shortest_paths_no_color_map.hpp + +

    Parameters

    + +IN: const Graph& graph +
    + The graph object on which the algorithm will be applied. + The type Graph must be a model of + Vertex List Graph + and Incidence Graph.
    +
    + +IN: vertex_descriptor start_vertex +
    + The source vertex. All distance will be calculated from this vertex, + and the shortest paths tree will be rooted at this vertex.
    +
    + +

    Named Parameters

    + +IN: weight_map(WeightMap weight_map) +
    + The weight or ``length'' of each edge in the graph. The weights + must all be non-negative and non-infinite. The algorithm will throw a + negative_edge + exception is 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, graph)
    +
    + +IN: index_map(VertexIndexMap index_map) +
    + This maps each vertex to an integer in the range [0, + num_vertices(graph)). This is necessary for efficient updates of the + heap data structure [61] when an edge is relaxed. + The type + VertexIndexMap must be a model of + Readable Property Map. The value type of the map must be an + integer type. The vertex descriptor type of the graph needs to be + usable as the key type of the map.
    + Default: get(vertex_index, graph). + 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. +
    +
    + +OUT: predecessor_map(PredecessorMap predecessor_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] = + u then u is either the source vertex or a vertex that is + not reachable from the source. The PredecessorMap type + must be a Read/Write + Property Map whose key and value types are the same as the vertex + descriptor type of the graph.
    + Default: dummy_property_map
    + + Python: Must be a vertex_vertex_map for the graph.
    +
    + +UTIL/OUT: distance_map(DistanceMap distance_map) +
    + The shortest path weight from the source vertex start_vertex to each + vertex in the graph graph 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. + + The value type of the distance map is the element type of a Monoid formed with the distance_weight_combine + function object and the distance_zero object for the identity + element. Also the distance value type must have a + StrictWeakOrdering provided by the distance_compare function + object.
    + Default: + iterator_property_map created from a + std::vector of the WeightMap's value type of size + num_vertices(graph) and using the index_map for the index + map.
    +
    + +IN: distance_compare(CompareFunction distance_compare) +
    + This function is use to compare distances to determine which vertex + is closer to the source vertex. The DistanceCompareFunction type + must be a model of Binary + Predicate and have argument types that match the value type of + the DistanceMap property map.
    + + Default: + std::less<D> with D=typename + property_traits<DistanceMap>::value_type
    +
    + +IN: distance_combine(CombineFunction distance_weight_combine) +
    + This function is used to combine distances to compute the distance + of a path. The DistanceWeightCombineFunction 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.
    + + Default: boost::closed_plus<D> with + D=typename property_traits<DistanceMap>::value_type
    +
    + +IN: distance_inf(D distance_infinity) +
    + 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.
    + Default: std::numeric_limits<D>::max()
    +
    + +IN: distance_zero(D distance_zero) +
    + The distance_zero value must be the identity element for the + Monoid formed by the distance values + and the distance_weight_combine function object. + The type D is the value type of the DistanceMap.
    + Default: D()with + D=typename property_traits<DistanceMap>::value_type
    +
    + +OUT: visitor(DijkstraVisitor v) +
    + Use this to specify actions that you would like to happen + during certain event points within the algorithm. + The type DijkstraVisitor must be a model of the + Dijkstra Visitor concept. + The visitor object is passed by value [2].
    + Default: dijkstra_visitor<null_visitor>
    +
    + + +

    Complexity

    + +

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

    Visitor Event Points

    + +
      +
    • vis.initialize_vertex(u, g) + is invoked on each vertex in the graph before the start of the + algorithm. +
    • vis.examine_vertex(u, g) + is invoked on a vertex as it is removed from the priority queue + and added to set S. At this point we know that (p[u],u) + is a shortest-paths tree edge so + d[u] = delta(s,u) = d[p[u]] + w(p[u],u). Also, the distances + of the examined vertices is monotonically increasing + d[u1] <= d[u2] <= d[un]. +
    • vis.examine_edge(e, g) + is invoked on each out-edge of a vertex immediately after it has + been added to set S. +
    • vis.edge_relaxed(e, g) + is invoked on edge (u,v) if d[u] + w(u,v) < d[v]. + The edge (u,v) that participated in the last + relaxation for vertex v is an edge in the shortest paths tree. +
    • vis.discover_vertex(v, g) + is invoked on vertex v when the edge + (u,v) is examined and v has not yet been discovered (i.e. its distance was infinity before relaxation was attempted on the edge). This + is also when the vertex is inserted into the priority queue. +
    • vis.edge_not_relaxed(e, g) + is invoked if the edge is not relaxed (see above). +
    • vis.finish_vertex(u, g) + is invoked on a vertex after all of its out edges have + been examined. +
    + +

    Example

    + +

    +See +example/dijkstra-no-color-map-example.cpp for an example of using Dijkstra's algorithm. + +

    Notes

    + +

    Based on the documentation for dijkstra_shortest_paths. + +

    [1] +The algorithm used here saves a little space by not putting all V - +S vertices in the priority queue at once, but instead only those +vertices in V - S that are discovered and therefore have a +distance less than infinity. + +

    [2] + 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. + +

    [3] + The algorithm will not work correctly if any of the edge weights are equal to infinity since the infinite distance value is used to determine if a vertex has been discovered. + +
    +


    + + +
    Copyright © 2009 +Trustees of Indiana University
    + + + diff --git a/doc/table_of_contents.html b/doc/table_of_contents.html index a0026bdb..9d6bc333 100644 --- a/doc/table_of_contents.html +++ b/doc/table_of_contents.html @@ -141,6 +141,7 @@
  • Shortest Paths Algorithms
    1. dijkstra_shortest_paths +
    2. dijkstra_shortest_paths_no_color_map
    3. bellman_ford_shortest_paths
    4. dag_shortest_paths
    5. +#include +#include + +#include +#include +#include + +using namespace boost; + +int +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; + enum nodes { A, B, C, D, E }; + char name[] = "ABCDE"; + Edge edge_array[] = { Edge(A, C), Edge(B, B), Edge(B, D), Edge(B, E), + Edge(C, B), Edge(C, D), Edge(D, E), Edge(E, A), Edge(E, B) + }; + 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; + 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 + + std::cout << "distances and parents:" << std::endl; + graph_traits < graph_t >::vertex_iterator vi, vend; + for (tie(vi, vend) = vertices(g); vi != vend; ++vi) { + std::cout << "distance(" << name[*vi] << ") = " << d[*vi] << ", "; + std::cout << "parent(" << name[*vi] << ") = " << name[p[*vi]] << std:: + endl; + } + std::cout << std::endl; + + std::ofstream dot_file("figs/dijkstra-no-color-map-eg.dot"); + + dot_file << "digraph D {\n" + << " rankdir=LR\n" + << " size=\"4,3\"\n" + << " ratio=\"fill\"\n" + << " edge[style=\"bold\"]\n" << " node[shape=\"circle\"]\n"; + + graph_traits < graph_t >::edge_iterator ei, ei_end; + for (tie(ei, ei_end) = edges(g); ei != ei_end; ++ei) { + graph_traits < graph_t >::edge_descriptor e = *ei; + graph_traits < graph_t >::vertex_descriptor + u = source(e, g), v = target(e, g); + dot_file << name[u] << " -> " << name[v] + << "[label=\"" << get(weightmap, e) << "\""; + if (p[v] == u) + dot_file << ", color=\"black\""; + else + dot_file << ", color=\"grey\""; + dot_file << "]"; + } + dot_file << "}"; + return EXIT_SUCCESS; +} 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 9e6307b2..22eb22c8 100644 --- a/include/boost/graph/dijkstra_shortest_paths_no_color_map.hpp +++ b/include/boost/graph/dijkstra_shortest_paths_no_color_map.hpp @@ -20,127 +20,230 @@ namespace boost { -template -void dijkstra_shortest_paths_no_color_map - (const Graph& graph, - typename graph_traits::vertex_descriptor start_vertex, - PredecessorMap predecessor_map, - DistanceMap distance_map, - WeightMap weight_map, - VertexIndexMap vertex_index_map, - DistanceCompare distance_compare, - DistanceWeightCombine distance_weight_combine, - DistanceInfinity distance_infinity, - DistanceZero distance_zero, - DijkstraVisitor visitor) -{ - typedef typename graph_traits::vertex_descriptor Vertex; - typedef typename property_traits::value_type Distance; - typedef typename property_traits::value_type Weight; + // Full init version + template + void dijkstra_shortest_paths_no_color_map + (const Graph& graph, + typename graph_traits::vertex_descriptor start_vertex, + PredecessorMap predecessor_map, + DistanceMap distance_map, + WeightMap weight_map, + VertexIndexMap index_map, + DistanceCompare distance_compare, + DistanceWeightCombine distance_weight_combine, + DistanceInfinity distance_infinity, + DistanceZero distance_zero, + DijkstraVisitor visitor) + { + // Initialize vertices + BGL_FORALL_VERTICES_T(current_vertex, graph, Graph) { + visitor.initialize_vertex(current_vertex, graph); + + // Default all distances to infinity + put(distance_map, current_vertex, distance_infinity); - typedef indirect_cmp DistanceIndirectCompare; - DistanceIndirectCompare - distance_indirect_compare(distance_map, distance_compare); - - // Choose vertex queue type -#if BOOST_GRAPH_DIJKSTRA_USE_RELAXED_HEAP - typedef relaxed_heap - VertexQueue; - VertexQueue vertex_queue(num_vertices(graph), - distance_indirect_compare, - vertex_index_map); -#else - // Default - use d-ary heap (d = 4) - typedef - detail::vertex_property_map_generator - IndexInHeapMapHelper; - typedef typename IndexInHeapMapHelper::type IndexInHeapMap; - typedef - d_ary_heap_indirect - VertexQueue; - - boost::scoped_array index_in_heap_map_holder; - IndexInHeapMap index_in_heap = - IndexInHeapMapHelper::build(graph, vertex_index_map, - index_in_heap_map_holder); - VertexQueue vertex_queue(distance_map, index_in_heap, distance_compare); -#endif - - // Initialize vertices - BGL_FORALL_VERTICES_T(current_vertex, graph, Graph) { - visitor.initialize_vertex(current_vertex, graph); - - // Default all distances to infinity - put(distance_map, current_vertex, distance_infinity); - - // Default all vertex predecessors to the vertex itself - put(predecessor_map, current_vertex, current_vertex); + // Default all vertex predecessors to the vertex itself + put(predecessor_map, current_vertex, current_vertex); + } + + // Set distance for start_vertex to zero + put(distance_map, start_vertex, distance_zero); + + // Pass everything on to the no_init version + dijkstra_shortest_paths_no_color_map_no_init(graph, + start_vertex, predecessor_map, distance_map, weight_map, + index_map, distance_compare, distance_weight_combine, + distance_infinity, distance_zero, visitor); } - // Set distance for start_vertex to zero - put(distance_map, start_vertex, distance_zero); - - // Add vertex to the queue - vertex_queue.push(start_vertex); - - // Starting vertex will always be the first discovered vertex - visitor.discover_vertex(start_vertex, graph); - - while (!vertex_queue.empty()) { - Vertex min_vertex = vertex_queue.top(); - vertex_queue.pop(); + // No init version + template + void dijkstra_shortest_paths_no_color_map_no_init + (const Graph& graph, + typename graph_traits::vertex_descriptor start_vertex, + PredecessorMap predecessor_map, + DistanceMap distance_map, + WeightMap weight_map, + VertexIndexMap index_map, + DistanceCompare distance_compare, + DistanceWeightCombine distance_weight_combine, + DistanceInfinity distance_infinity, + DistanceZero distance_zero, + DijkstraVisitor visitor) + { + typedef typename graph_traits::vertex_descriptor Vertex; + typedef typename property_traits::value_type Distance; + typedef typename property_traits::value_type Weight; - visitor.examine_vertex(min_vertex, graph); + typedef indirect_cmp DistanceIndirectCompare; + DistanceIndirectCompare + distance_indirect_compare(distance_map, distance_compare); + + // Choose vertex queue type + #if BOOST_GRAPH_DIJKSTRA_USE_RELAXED_HEAP + typedef relaxed_heap + VertexQueue; + VertexQueue vertex_queue(num_vertices(graph), + distance_indirect_compare, + index_map); + #else + // Default - use d-ary heap (d = 4) + typedef + detail::vertex_property_map_generator + IndexInHeapMapHelper; + typedef typename IndexInHeapMapHelper::type IndexInHeapMap; + typedef + d_ary_heap_indirect + VertexQueue; + + boost::scoped_array index_in_heap_map_holder; + IndexInHeapMap index_in_heap = + IndexInHeapMapHelper::build(graph, index_map, + index_in_heap_map_holder); + VertexQueue vertex_queue(distance_map, index_in_heap, distance_compare); + #endif + + // Add vertex to the queue + vertex_queue.push(start_vertex); + + // Starting vertex will always be the first discovered vertex + visitor.discover_vertex(start_vertex, graph); + + while (!vertex_queue.empty()) { + Vertex min_vertex = vertex_queue.top(); + vertex_queue.pop(); + + visitor.examine_vertex(min_vertex, graph); + + // Check if any other vertices can be reached + Distance min_vertex_distance = get(distance_map, min_vertex); + + if (!distance_compare(min_vertex_distance, distance_infinity)) { + // This is the minimum vertex, so all other vertices are unreachable + return; + } + + // Examine neighbors of min_vertex + typedef typename graph_traits::edge_descriptor Edge; + typename graph_traits::out_edge_iterator edge_iter, edge_iter_end; + BGL_FORALL_OUTEDGES_T(min_vertex, current_edge, graph, Graph) { + visitor.examine_edge(current_edge, graph); + + // Check if the edge has a negative weight + if (distance_compare(get(weight_map, current_edge), distance_zero)) { + boost::throw_exception(negative_edge()); + } + + // Extract the neighboring vertex and get its distance + Vertex neighbor_vertex = target(current_edge, graph); + Distance neighbor_vertex_distance = get(distance_map, neighbor_vertex); + bool is_neighbor_undiscovered = + !distance_compare(neighbor_vertex_distance, distance_infinity); + + // Attempt to relax the edge + bool was_edge_relaxed = relax(current_edge, graph, weight_map, + predecessor_map, distance_map, + distance_weight_combine, distance_compare); + + if (was_edge_relaxed) { + vertex_queue.update(neighbor_vertex); + visitor.edge_relaxed(current_edge, graph); + } 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); + } // end while queue not empty + } - // Check if any other vertices can be reached - Distance min_vertex_distance = get(distance_map, min_vertex); - - if (!distance_compare(min_vertex_distance, distance_infinity)) { - // This is the minimum vertex, so all other vertices are unreachable - return; + namespace detail { + + // Handle defaults for PredecessorMap, DistanceCompare, + // DistanceWeightCombine, DistanceInfinity and DistanceZero + template + inline void + dijkstra_no_color_map_dispatch2 + (const Graph& graph, + typename graph_traits::vertex_descriptor start_vertex, + DistanceMap distance_map, WeightMap weight_map, + VertexIndexMap index_map, const Params& params) + { + // Default for predecessor map + dummy_property_map predecessor_map; + + typedef typename property_traits::value_type DistanceType; + dijkstra_shortest_paths_no_color_map + (graph, start_vertex, + choose_param(get_param(params, vertex_predecessor), predecessor_map), + distance_map, weight_map, index_map, + 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_zero_t()), + DistanceType()), + choose_param(get_param(params, graph_visitor), + make_dijkstra_visitor(null_visitor()))); } - // Examine neighbors of min_vertex - typedef typename graph_traits::edge_descriptor Edge; - typename graph_traits::out_edge_iterator edge_iter, edge_iter_end; - BGL_FORALL_OUTEDGES_T(min_vertex, current_edge, graph, Graph) { - visitor.examine_edge(current_edge, graph); - - // Check if the edge has a negative weight - if (distance_compare(get(weight_map, current_edge), distance_zero)) { - boost::throw_exception(negative_edge()); - } - - Vertex neighbor_vertex = target(current_edge, graph); - Distance neighbor_vertex_distance = get(distance_map, neighbor_vertex); - bool is_neighbor_undiscovered = - !distance_compare(neighbor_vertex_distance, distance_infinity); + template + inline void + dijkstra_no_color_map_dispatch1 + (const Graph& graph, + typename graph_traits::vertex_descriptor start_vertex, + DistanceMap distance_map, WeightMap weight_map, + IndexMap index_map, const Params& params) + { + // Default for distance map + typedef typename property_traits::value_type DistanceType; + typename std::vector::size_type + vertex_count = is_default_param(distance_map) ? num_vertices(graph) : 1; + + std::vector default_distance_map(vertex_count); - // Attempt to relax the edge - bool was_edge_relaxed = relax(current_edge, graph, weight_map, - predecessor_map, distance_map, - distance_weight_combine, distance_compare); + detail::dijkstra_no_color_map_dispatch2 + (graph, start_vertex, choose_param(distance_map, + make_iterator_property_map(default_distance_map.begin(), index_map, + default_distance_map[0])), + weight_map, index_map, params); + } + } // namespace detail - if (was_edge_relaxed) { - vertex_queue.update(neighbor_vertex); - visitor.edge_relaxed(current_edge, graph); - } 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); - } // end while queue not empty -} + // Named parameter version + template + inline void + dijkstra_shortest_paths_no_color_map + (const Graph& graph, + typename graph_traits::vertex_descriptor start_vertex, + const bgl_named_params& params) + { + // Default for edge weight and vertex index map is to ask for them + // from the graph. Default for the visitor is null_visitor. + detail::dijkstra_no_color_map_dispatch1 + (graph, start_vertex, + get_param(params, vertex_distance), + choose_const_pmap(get_param(params, edge_weight), graph, edge_weight), + choose_const_pmap(get_param(params, vertex_index), graph, vertex_index), + params); + } } // namespace boost diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index b1a8776c..affd4b93 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -49,6 +49,7 @@ test-suite graph_test : [ compile dfs_cc.cpp ] [ compile dijkstra_cc.cpp ] [ run dijkstra_heap_performance.cpp : 10000 ] + [ run dijkstra_no_color_map_compare.cpp : 10000 ] [ run dominator_tree_test.cpp ] [ run relaxed_heap_test.cpp : 5000 15000 ] [ compile edge_list_cc.cpp ] diff --git a/test/dijkstra_no_color_map_compare.cpp b/test/dijkstra_no_color_map_compare.cpp new file mode 100644 index 00000000..7dd8c82a --- /dev/null +++ b/test/dijkstra_no_color_map_compare.cpp @@ -0,0 +1,124 @@ +//======================================================================= +// Copyright 2009 Trustees of Indiana University. +// Authors: Michael Hansen +// +// 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 + +#define INITIALIZE_VERTEX 0 +#define DISCOVER_VERTEX 1 +#define EXAMINE_VERTEX 2 +#define EXAMINE_EDGE 3 +#define EDGE_RELAXED 4 +#define EDGE_NOT_RELAXED 5 +#define FINISH_VERTEX 6 + +template +void run_dijkstra_test(const Graph& graph) +{ + using namespace boost; + + // Set up property maps + typedef typename graph_traits::vertex_descriptor vertex_t; + + typedef typename std::map vertex_map_t; + typedef associative_property_map predecessor_map_t; + vertex_map_t default_vertex_map, no_color_map_vertex_map; + predecessor_map_t default_predecessor_map(default_vertex_map), + no_color_map_predecessor_map(no_color_map_vertex_map); + + typedef typename std::map vertex_double_map_t; + typedef associative_property_map distance_map_t; + vertex_double_map_t default_vertex_double_map, no_color_map_vertex_double_map; + distance_map_t default_distance_map(default_vertex_double_map), + no_color_map_distance_map(no_color_map_vertex_double_map); + + // Run dijkstra algoirthms + dijkstra_shortest_paths(graph, vertex(0, graph), + predecessor_map(default_predecessor_map) + .distance_map(default_distance_map)); + + dijkstra_shortest_paths_no_color_map(graph, vertex(0, graph), + predecessor_map(no_color_map_predecessor_map) + .distance_map(no_color_map_distance_map)); + + // Verify that predecessor maps are equal + BOOST_CHECK(std::equal(default_vertex_map.begin(), default_vertex_map.end(), + no_color_map_vertex_map.begin())); + + // Verify that distance maps are equal + BOOST_CHECK(std::equal(default_vertex_double_map.begin(), default_vertex_double_map.end(), + no_color_map_vertex_double_map.begin())); +} + +int test_main(int argc, char* argv[]) +{ + using namespace boost; + + int vertices_to_create = 10; + int edges_to_create = 500; + std::size_t random_seed = time(0); + + if (argc > 1) { + vertices_to_create = lexical_cast(argv[1]); + } + + if (argc > 2) { + edges_to_create = lexical_cast(argv[2]); + } + + if (argc > 3) { + random_seed = lexical_cast(argv[3]); + } + + minstd_rand generator(random_seed); + + // Set up graph + typedef adjacency_list, + 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); + + // Set up property maps + typedef property_map::type index_map_t; + index_map_t index_map = get(vertex_index, graph); + int vertex_index = 0; + + BGL_FORALL_VERTICES(current_vertex, graph, graph_t) { + 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 + std::cout << "Running dijkstra shortest paths test with " << num_vertices(graph) << + " vertices and " << num_edges(graph) << " edges " << std::endl; + + run_dijkstra_test(graph); + + return 0; +} + From dfb88dedb47ed695a61b35d4dfed31c588968055 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Wed, 27 May 2009 22:37:56 +0000 Subject: [PATCH 210/224] Fixed conversion of parameters after end-of-list marker, as used in strong_components [SVN r53329] --- include/boost/graph/named_function_params.hpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/include/boost/graph/named_function_params.hpp b/include/boost/graph/named_function_params.hpp index ec567efb..b8f29700 100644 --- a/include/boost/graph/named_function_params.hpp +++ b/include/boost/graph/named_function_params.hpp @@ -341,6 +341,15 @@ BOOST_BGL_DECLARE_NAMED_PARAMS } }; + template + struct convert_bgl_params_to_boost_parameter > { + 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); + } + }; + template <> struct convert_bgl_params_to_boost_parameter { typedef boost::parameter::aux::empty_arg_list type; From f789831ba9b1bee1633f631d648ecd661db6c6fb Mon Sep 17 00:00:00 2001 From: Andrew Sutton Date: Thu, 28 May 2009 11:35:12 +0000 Subject: [PATCH 211/224] Removing subgraph props from build. [SVN r53341] --- test/Jamfile.v2 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index affd4b93..51bd07ce 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -75,7 +75,7 @@ test-suite graph_test : # TODO: Merge these into a single test framework. [ run subgraph.cpp ../../test/build//boost_test_exec_monitor ] [ run subgraph_bundled.cpp ] - [ run subgraph_props.cpp ] + # [ run subgraph_props.cpp ] [ run isomorphism.cpp ../../test/build//boost_test_exec_monitor ] [ run adjacency_matrix_test.cpp ] From 1a184e4e2ed828e09c137b912265e04df9a1078b Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Thu, 28 May 2009 17:17:49 +0000 Subject: [PATCH 212/224] Added more changes from Michael Hansen [SVN r53349] --- doc/dijkstra_shortest_paths.html | 4 +- doc/dijkstra_shortest_paths_no_color_map.html | 21 +- .../dijkstra_shortest_paths_no_color_map.hpp | 222 +++++++++--------- 3 files changed, 124 insertions(+), 123 deletions(-) diff --git a/doc/dijkstra_shortest_paths.html b/doc/dijkstra_shortest_paths.html index c9a8bda0..af05cfaf 100644 --- a/doc/dijkstra_shortest_paths.html +++ b/doc/dijkstra_shortest_paths.html @@ -19,8 +19,6 @@ dijkstra_shortest_paths -

      See also dijkstra_shortest_paths_no_color_map -

       // named parameter version
      @@ -431,6 +429,8 @@ See 
       example/dijkstra-example.cpp for an example of using Dijkstra's
       algorithm.
       
      +

      See also

      dijkstra_shortest_paths_no_color_map for a version of dijkstra's shortest path that does not use a color map. +

      Notes

      [1] diff --git a/doc/dijkstra_shortest_paths_no_color_map.html b/doc/dijkstra_shortest_paths_no_color_map.html index e7358a1c..1efba2a1 100644 --- a/doc/dijkstra_shortest_paths_no_color_map.html +++ b/doc/dijkstra_shortest_paths_no_color_map.html @@ -19,8 +19,6 @@ dijkstra_shortest_paths_no_color_map -

      See also dijkstra_shortest_paths -

       // named parameter version
      @@ -70,6 +68,10 @@ HREF="graph_theory_review.html#sec:shortest-paths-algorithms">Shortest-Paths
       Algorithms for some background to the shortest-path problem.
       

      +

      + 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. +

      +

      There are two main options for obtaining output from the dijkstra_shortest_paths_no_color_map() function. If you provide a @@ -82,7 +84,7 @@ the shortest paths tree (unless p[u] = u, in which case u is either the source or a vertex unreachable from the source). In addition to these two options, the user can provide their own custom-made visitor that takes actions during any of the -algorithm's event points.

      +algorithm's event points [4].

      Dijkstra's algorithm finds all the shortest paths from the source @@ -100,12 +102,6 @@ reduced. The algorithm then loops back, processing the next vertex at the top of the priority queue. The algorithm finishes when the priority queue is empty.

      -

      -The algorithm uses the distance map to keep -track of which set each vertex is in. Vertices with a non-infinite distance are in -S. Vertices with an infinite distance are in V-S and have -not yet been discovered. -

      The following is the pseudo-code for Dijkstra's single-source shortest paths algorithm. w is the edge weight, d is the distance label, @@ -193,7 +189,7 @@ IN: vertex_descriptor start_vertex IN: weight_map(WeightMap weight_map)

      The weight or ``length'' of each edge in the graph. The weights - must all be non-negative and non-infinite. The algorithm will throw a + must all be non-negative and non-infinite [3]. The algorithm will throw a negative_edge exception is one of the edges is negative. The type WeightMap must be a model of @@ -366,6 +362,8 @@ The time complexity is O(V log V). See example/dijkstra-no-color-map-example.cpp for an example of using Dijkstra's algorithm. +

      See also

      dijkstra_shortest_paths for a version of dijkstra's shortest path that uses a color map. +

      Notes

      Based on the documentation for dijkstra_shortest_paths. @@ -385,6 +383,9 @@ distance less than infinity.

      [3] The algorithm will not work correctly if any of the edge weights are equal to infinity since the infinite distance value is used to determine if a vertex has been discovered. + +

      [4] + Calls to the visitor events occur in the same order as dijkstra_shortest_paths (i.e. discover_vertex(u) will always be called after examine_vertex(u) for an undiscovered vertex u). However, the vertices of the graph given to dijkstra_shortest_paths_no_color_map will not necessarily be visited in the same order as dijkstra_shortest_paths.


      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 22eb22c8..8b7b3aa1 100644 --- a/include/boost/graph/dijkstra_shortest_paths_no_color_map.hpp +++ b/include/boost/graph/dijkstra_shortest_paths_no_color_map.hpp @@ -20,6 +20,116 @@ namespace boost { + // No init version + template + void dijkstra_shortest_paths_no_color_map_no_init + (const Graph& graph, + typename graph_traits::vertex_descriptor start_vertex, + PredecessorMap predecessor_map, + DistanceMap distance_map, + WeightMap weight_map, + VertexIndexMap index_map, + DistanceCompare distance_compare, + DistanceWeightCombine distance_weight_combine, + DistanceInfinity distance_infinity, + DistanceZero distance_zero, + DijkstraVisitor visitor) + { + 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 + distance_indirect_compare(distance_map, distance_compare); + + // Choose vertex queue type +#if BOOST_GRAPH_DIJKSTRA_USE_RELAXED_HEAP + typedef relaxed_heap + VertexQueue; + VertexQueue vertex_queue(num_vertices(graph), + distance_indirect_compare, + index_map); +#else + // Default - use d-ary heap (d = 4) + typedef + detail::vertex_property_map_generator + IndexInHeapMapHelper; + typedef typename IndexInHeapMapHelper::type IndexInHeapMap; + typedef + d_ary_heap_indirect + VertexQueue; + + boost::scoped_array index_in_heap_map_holder; + IndexInHeapMap index_in_heap = + IndexInHeapMapHelper::build(graph, index_map, + index_in_heap_map_holder); + VertexQueue vertex_queue(distance_map, index_in_heap, distance_compare); +#endif + + // Add vertex to the queue + vertex_queue.push(start_vertex); + + // Starting vertex will always be the first discovered vertex + visitor.discover_vertex(start_vertex, graph); + + while (!vertex_queue.empty()) { + Vertex min_vertex = vertex_queue.top(); + vertex_queue.pop(); + + visitor.examine_vertex(min_vertex, graph); + + // Check if any other vertices can be reached + Distance min_vertex_distance = get(distance_map, min_vertex); + + if (!distance_compare(min_vertex_distance, distance_infinity)) { + // This is the minimum vertex, so all other vertices are unreachable + return; + } + + // Examine neighbors of min_vertex + typedef typename graph_traits::edge_descriptor Edge; + typename graph_traits::out_edge_iterator edge_iter, edge_iter_end; + BGL_FORALL_OUTEDGES_T(min_vertex, current_edge, graph, Graph) { + visitor.examine_edge(current_edge, graph); + + // Check if the edge has a negative weight + if (distance_compare(get(weight_map, current_edge), distance_zero)) { + boost::throw_exception(negative_edge()); + } + + // Extract the neighboring vertex and get its distance + Vertex neighbor_vertex = target(current_edge, graph); + Distance neighbor_vertex_distance = get(distance_map, neighbor_vertex); + bool is_neighbor_undiscovered = + !distance_compare(neighbor_vertex_distance, distance_infinity); + + // Attempt to relax the edge + bool was_edge_relaxed = relax(current_edge, graph, weight_map, + predecessor_map, distance_map, + distance_weight_combine, distance_compare); + + if (was_edge_relaxed) { + vertex_queue.update(neighbor_vertex); + visitor.edge_relaxed(current_edge, graph); + } 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); + } // end while queue not empty + } + // Full init version template - void dijkstra_shortest_paths_no_color_map_no_init - (const Graph& graph, - typename graph_traits::vertex_descriptor start_vertex, - PredecessorMap predecessor_map, - DistanceMap distance_map, - WeightMap weight_map, - VertexIndexMap index_map, - DistanceCompare distance_compare, - DistanceWeightCombine distance_weight_combine, - DistanceInfinity distance_infinity, - DistanceZero distance_zero, - DijkstraVisitor visitor) - { - 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 - distance_indirect_compare(distance_map, distance_compare); - - // Choose vertex queue type - #if BOOST_GRAPH_DIJKSTRA_USE_RELAXED_HEAP - typedef relaxed_heap - VertexQueue; - VertexQueue vertex_queue(num_vertices(graph), - distance_indirect_compare, - index_map); - #else - // Default - use d-ary heap (d = 4) - typedef - detail::vertex_property_map_generator - IndexInHeapMapHelper; - typedef typename IndexInHeapMapHelper::type IndexInHeapMap; - typedef - d_ary_heap_indirect - VertexQueue; - - boost::scoped_array index_in_heap_map_holder; - IndexInHeapMap index_in_heap = - IndexInHeapMapHelper::build(graph, index_map, - index_in_heap_map_holder); - VertexQueue vertex_queue(distance_map, index_in_heap, distance_compare); - #endif - - // Add vertex to the queue - vertex_queue.push(start_vertex); - - // Starting vertex will always be the first discovered vertex - visitor.discover_vertex(start_vertex, graph); - - while (!vertex_queue.empty()) { - Vertex min_vertex = vertex_queue.top(); - vertex_queue.pop(); - - visitor.examine_vertex(min_vertex, graph); - - // Check if any other vertices can be reached - Distance min_vertex_distance = get(distance_map, min_vertex); - - if (!distance_compare(min_vertex_distance, distance_infinity)) { - // This is the minimum vertex, so all other vertices are unreachable - return; - } - - // Examine neighbors of min_vertex - typedef typename graph_traits::edge_descriptor Edge; - typename graph_traits::out_edge_iterator edge_iter, edge_iter_end; - BGL_FORALL_OUTEDGES_T(min_vertex, current_edge, graph, Graph) { - visitor.examine_edge(current_edge, graph); - - // Check if the edge has a negative weight - if (distance_compare(get(weight_map, current_edge), distance_zero)) { - boost::throw_exception(negative_edge()); - } - - // Extract the neighboring vertex and get its distance - Vertex neighbor_vertex = target(current_edge, graph); - Distance neighbor_vertex_distance = get(distance_map, neighbor_vertex); - bool is_neighbor_undiscovered = - !distance_compare(neighbor_vertex_distance, distance_infinity); - - // Attempt to relax the edge - bool was_edge_relaxed = relax(current_edge, graph, weight_map, - predecessor_map, distance_map, - distance_weight_combine, distance_compare); - - if (was_edge_relaxed) { - vertex_queue.update(neighbor_vertex); - visitor.edge_relaxed(current_edge, graph); - } 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); - } // end while queue not empty - } - namespace detail { // Handle defaults for PredecessorMap, DistanceCompare, @@ -233,7 +233,7 @@ namespace boost { dijkstra_shortest_paths_no_color_map (const Graph& graph, typename graph_traits::vertex_descriptor start_vertex, - const bgl_named_params& params) + const bgl_named_params& params) { // Default for edge weight and vertex index map is to ask for them // from the graph. Default for the visitor is null_visitor. From dafc6fbb2b1497b2fb68bba50be382054b27d6c2 Mon Sep 17 00:00:00 2001 From: Andrew Sutton Date: Thu, 28 May 2009 22:20:48 +0000 Subject: [PATCH 213/224] Finished basic support for local/global property references for old-style properties. Actually adding the test file today. [SVN r53369] --- include/boost/graph/subgraph.hpp | 299 ++++++++++++++++++++++++------- test/Jamfile.v2 | 2 +- test/subgraph_props.cpp | 136 ++++++++++++++ 3 files changed, 370 insertions(+), 67 deletions(-) create mode 100644 test/subgraph_props.cpp diff --git a/include/boost/graph/subgraph.hpp b/include/boost/graph/subgraph.hpp index 826b34e5..ba2405f1 100644 --- a/include/boost/graph/subgraph.hpp +++ b/include/boost/graph/subgraph.hpp @@ -32,27 +32,33 @@ struct subgraph_tag { }; /** @name Property Lookup * The local_property and global_property functions are used to create * structures that determine the lookup strategy for properties in subgraphs. + * Note that the nested kind member is used to help interoperate with actual + * Property types. */ //@{ template -struct local_subgraph_property { - local_subgraph_property(T x) : value(x) { } +struct local_property +{ + typedef T kind; + local_property(T x) : value(x) { } T value; }; template -inline local_subgraph_property local(T x) -{ return local_subgraph_property(x); } +inline local_property local(T x) +{ return local_property(x); } template -struct global_subgraph_property { - global_subgraph_property(T x) : value(x) { } +struct global_property +{ + typedef T kind; + global_property(T x) : value(x) { } T value; }; template -inline global_subgraph_property global(T x) -{ return global_subgraph_property(x); } +inline global_property global(T x) +{ return global_property(x); } //@} // Invariants of an induced subgraph: @@ -252,12 +258,12 @@ typedef typename Traits::traversal_category traversal_category; // Local property access returns the local property of the given descripor. template typename graph::detail::bundled_result::type& - operator[](local_subgraph_property x) + operator[](local_property x) { return m_graph[x.value]; } template typename graph::detail::bundled_result::type const& - operator[](local_subgraph_property x) const + operator[](local_property x) const { return m_graph[x.value]; } // Global property access returns the global property associated with the @@ -265,12 +271,12 @@ typedef typename Traits::traversal_category traversal_category; // access operations. template typename graph::detail::bundled_result::type& - operator[](global_subgraph_property x) + operator[](global_property x) { return (*this)[x.value]; } template typename graph::detail::bundled_result::type const& - operator[](global_subgraph_property x) const + operator[](global_property x) const { return (*this)[x.value]; } #endif // BOOST_GRAPH_NO_BUNDLED_PROPERTIES @@ -780,6 +786,9 @@ public: typedef typename Traits::key_type key_type; typedef typename Traits::reference reference; + typedef Tag tag; + typedef PropertyMap pmap; + subgraph_local_property_map() { } @@ -788,7 +797,8 @@ public: { } reference operator[](key_type e) const { - PropertyMap pmap = get(Tag(), *m_g); + // Get property map on the underlying graph. + PropertyMap pmap = get(Tag(), m_g->m_graph); return pmap[e]; } @@ -796,17 +806,30 @@ public: }; namespace detail { + // Extract the actual tags from local or global property maps so we don't + // try to find non-properties. + template struct extract_lg_tag { typedef P type; }; + template struct extract_lg_tag< local_property

      > { + typedef P type; + }; + template struct extract_lg_tag< global_property

      > { + typedef P type; + }; + + // NOTE: Mysterious Property template parameter unused in both metafunction + // classes. struct subgraph_global_pmap { template - class bind_ { + struct bind_ { typedef typename SubGraph::graph_type Graph; typedef SubGraph* SubGraphPtr; typedef const SubGraph* const_SubGraphPtr; - typedef typename property_map::type PMap; - typedef typename property_map::const_type const_PMap; + typedef typename extract_lg_tag::type TagType; + typedef typename property_map::type PMap; + typedef typename property_map::const_type const_PMap; public: - typedef subgraph_global_property_map type; - typedef subgraph_global_property_map + typedef subgraph_global_property_map type; + typedef subgraph_global_property_map const_type; }; }; @@ -817,29 +840,52 @@ namespace detail { typedef typename SubGraph::graph_type Graph; typedef SubGraph* SubGraphPtr; typedef const SubGraph* const_SubGraphPtr; - typedef typename property_map::type PMap; - typedef typename property_map::const_type const_PMap; + typedef typename extract_lg_tag::type TagType; + typedef typename property_map::type PMap; + typedef typename property_map::const_type const_PMap; public: - typedef subgraph_local_property_map type; - typedef subgraph_local_property_map + typedef subgraph_local_property_map type; + typedef subgraph_local_property_map const_type; }; }; // These metafunctions select the corresponding metafunctions above, and // are used by the choose_pmap metafunction below to specialize the choice - // of local/global property map. + // of local/global property map. By default, we defer to the global + // property. template struct subgraph_choose_pmap_helper { typedef subgraph_global_pmap type; }; + template + struct subgraph_choose_pmap_helper< local_property > { + typedef subgraph_local_pmap type; + }; + template + struct subgraph_choose_pmap_helper< global_property > { + typedef subgraph_global_pmap type; + }; + + // As above, unless we're requesting vertex_index_t. Then it's always a + // local property map. This enables the correct translation of descriptors + // between local and global layers. template <> struct subgraph_choose_pmap_helper { typedef subgraph_local_pmap type; }; + template <> + struct subgraph_choose_pmap_helper< local_property > { + typedef subgraph_local_pmap type; + }; + template <> + struct subgraph_choose_pmap_helper< global_property > { + typedef subgraph_local_pmap type; + }; // Determine the kind of property. If SameType, then // the property lookup is always local. Otherwise, the lookup is global. + // NOTE: Property parameter is basically unused. template struct subgraph_choose_pmap { typedef typename subgraph_choose_pmap_helper::type Helper; @@ -872,27 +918,37 @@ struct edge_property_selector { }; #ifndef BOOST_GRAPH_NO_BUNDLED_PROPERTIES -template -struct subgraph_local_bundle_property_map +/** @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_local_bundle_property_map + 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_local_bundle_property_map() + subgraph_lg_bundle_property_map() { } - subgraph_local_bundle_property_map(Graph* g, T Bundle::* p) + 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)[local(k)].*m_prop; } + { return (*m_g)[Wrap(k)].*m_prop; } private: Graph* m_g; @@ -903,35 +959,69 @@ private: // 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_subgraph_property > +struct property_map, local_property > + : graph_detail::bundled_subgraph_pmap_helper { private: - 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_c< - detail::is_vertex_bundle::value, - typename Traits::vertex_descriptor, - typename Traits::edge_descriptor - >::type Desc; - - // Deduce the bundled property type - typedef typename mpl::if_c< - detail::is_vertex_bundle::value, - VertBundled, - EdgeBundled - >::type Prop; + 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_local_bundle_property_map type; - typedef subgraph_local_bundle_property_map const_type; + 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) { @@ -956,7 +1046,62 @@ get(Property, const subgraph& g, const Key& k) { return pmap[k]; } +template +void put(Property, subgraph& g, const Key& k, const Value& val) { + typedef typename property_map< subgraph, Property>::type PMap; + PMap pmap(&g); + pmap[k] = val; +} + +// ================================================== +// get(global(p), g) +// NOTE: get(global(p), g, k) and put(global(p), g, k, v) not supported +// ================================================== +template +typename property_map, global_property >::type +get(global_property, subgraph& g) { + typedef typename property_map< + subgraph, global_property + >::type Map; + return Map(&g); +} + +template +typename property_map, global_property >::const_type +get(global_property, const subgraph& g) { + typedef typename property_map< + subgraph, global_property + >::const_type Map; + return Map(&g); +} + +// ================================================== +// get(local(p), g) +// NOTE: get(local(p), g, k) and put(local(p), g, k, v) not supported +// ================================================== +template +typename property_map, local_property >::type +get(local_property, subgraph& g) { + typedef typename property_map< + subgraph, local_property + >::type Map; + return Map(&g); +} + +template +typename property_map, local_property >::const_type +get(local_property, 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) { @@ -981,45 +1126,67 @@ inline void put(Type Bundle::* p, Graph& g, Key const& k, Value const& v) { put(get(p, g), k, v); } // ========================================================= -// Localized bundled, get +// Local bundled, get template inline typename property_map< - subgraph, local_subgraph_property + subgraph, local_property >::type -get(local_subgraph_property p, subgraph& g) { +get(local_property p, subgraph& g) { typedef typename property_map< - subgraph, local_subgraph_property + subgraph, local_property >::type Map; return Map(&g, p.value); } template inline typename property_map< - subgraph, local_subgraph_property + subgraph, local_property >::const_type -get(local_subgraph_property p, subgraph const& g) { +get(local_property p, subgraph const& g) { typedef typename property_map< - subgraph, local_subgraph_property + subgraph, local_property >::const_type Map; return Map(&g, p.value); } template -inline Type get(local_subgraph_property p, - subgraph const& g, +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 -void put(Property, subgraph& g, const Key& k, const Value& val) { - typedef typename property_map< subgraph, Property>::type PMap; - PMap pmap(&g); - pmap[k] = val; -} - template inline typename graph_property::type& get_property(subgraph& g, Tag tag) { diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 51bd07ce..affd4b93 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -75,7 +75,7 @@ test-suite graph_test : # TODO: Merge these into a single test framework. [ run subgraph.cpp ../../test/build//boost_test_exec_monitor ] [ run subgraph_bundled.cpp ] - # [ run subgraph_props.cpp ] + [ run subgraph_props.cpp ] [ run isomorphism.cpp ../../test/build//boost_test_exec_monitor ] [ run adjacency_matrix_test.cpp ] diff --git a/test/subgraph_props.cpp b/test/subgraph_props.cpp new file mode 100644 index 00000000..83fc1932 --- /dev/null +++ b/test/subgraph_props.cpp @@ -0,0 +1,136 @@ +// (C) Copyright Andrew Sutton 2009 +// 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 + +#if !defined(BOOST_NO_HASH) +# define BOOST_NO_HASH +#endif + +#include +#include +#include "typestr.hpp" + +using namespace boost; + +struct TestProps { + typedef property VertexProp; + typedef property EdgeName; + typedef property EdgeProp; + + typedef adjacency_list< + vecS, vecS, bidirectionalS, VertexProp, EdgeProp + > Graph; + + typedef subgraph Subgraph; + typedef graph_traits::vertex_descriptor Vertex; + typedef graph_traits::edge_descriptor Edge; + typedef graph_traits::vertex_iterator VertexIter; + typedef std::pair VertexRange; + + static void run() { + // Create a graph with some vertices. + Subgraph g(5); + VertexRange r = vertices(g); + + // Create a child subgraph and add some vertices. + Subgraph& sg = g.create_subgraph(); + Vertex v = add_vertex(*r.first, sg); + + typedef property_map::type DefaultMap; + DefaultMap map = get(vertex_name, g); + BOOST_ASSERT(get(map, v) == 0); + put(map, v, 5); + BOOST_ASSERT(get(map, v) == 5); + + typedef global_property GlobalProp; + typedef property_map::type GlobalVertMap; + GlobalVertMap groot = get(global(vertex_name), g); + GlobalVertMap gsub = get(global(vertex_name), sg); + BOOST_ASSERT(get(groot, v) == 5); + BOOST_ASSERT(get(gsub, v) == 5); + put(gsub, v, 10); + BOOST_ASSERT(get(groot, v) == 10); + BOOST_ASSERT(get(gsub, v) == 10); + BOOST_ASSERT(get(map, v) == 10); + + typedef local_property LocalProp; + typedef property_map::type LocalVertMap; + LocalVertMap lroot = get(local(vertex_name), g); // Actually global! + LocalVertMap lsub = get(local(vertex_name), sg); + BOOST_ASSERT(get(lroot, v) == 10); // Recall it's 10 from above! + BOOST_ASSERT(get(lsub, v) == 0); + put(lsub, v, 5); + BOOST_ASSERT(get(lsub, v) == 5); + BOOST_ASSERT(get(lroot, v) == 10); // Don't change the root prop + BOOST_ASSERT(get(map, v) == 10); // Don't change the root prop + +// typedef detail::subgraph_local_pmap::bind_ PM; +// std::cout << typestr() << "\n"; +// std::cout << typestr() << "\n"; + } +}; + +struct TestBundles { + struct Node { + Node() : value(-1) { } + int value; + }; + struct Arc { + Arc() : value(-1) { } + int value; + }; + typedef property EdgeProp; + + typedef adjacency_list< + vecS, vecS, bidirectionalS, Node, EdgeProp + > Graph; + + typedef subgraph Subgraph; + typedef graph_traits::vertex_descriptor Vertex; + typedef graph_traits::edge_descriptor Edge; + typedef graph_traits::vertex_iterator VertexIter; + typedef std::pair VertexRange; + + static void run() { + // Create a graph with some vertices. + Subgraph g(5); + VertexRange r = vertices(g); + + // Create a child subgraph and add some vertices. + Subgraph& sg = g.create_subgraph(); + Vertex v = add_vertex(*r.first, sg); + + sg[v].value = 1; + BOOST_ASSERT(sg[v].value == 1); + BOOST_ASSERT(sg[global(v)].value == 1); + BOOST_ASSERT(sg[local(v)].value == -1); + + sg[local(v)].value = 5; + BOOST_ASSERT(sg[local(v)].value == 5); + BOOST_ASSERT(sg[global(v)].value == 1); + BOOST_ASSERT(sg[v].value == 1); + + typedef property_map< + Subgraph, local_property + >::type LocalVertMap; + LocalVertMap lvm = get(local(&Node::value), sg); + BOOST_ASSERT(get(lvm, v) == 5); + + typedef property_map< + Subgraph, global_property + >::type GlobalVertMap; + GlobalVertMap gvm = get(global(&Node::value), sg); + BOOST_ASSERT(get(gvm, v) == 1); + } +}; + +int main(int argc, char* argv[]) +{ + TestProps::run(); + TestBundles::run(); + + return 0; +} From b35856b2f3b543f66d46622185011d73de038a13 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Fri, 29 May 2009 16:52:58 +0000 Subject: [PATCH 214/224] Added patch from Michael Hansen [SVN r53396] --- test/dijkstra_cc.cpp | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/test/dijkstra_cc.cpp b/test/dijkstra_cc.cpp index 59638387..89705174 100644 --- a/test/dijkstra_cc.cpp +++ b/test/dijkstra_cc.cpp @@ -10,6 +10,7 @@ #include #include #include +#include #include typedef boost::default_constructible_archetype< @@ -50,6 +51,11 @@ int main() vertex_index_map(index). weight_map(weight). distance_map(distance)); + + dijkstra_shortest_paths_no_color_map(g, s, + vertex_index_map(index). + weight_map(weight). + distance_map(distance)); } { typedef incidence_graph_archetype Date: Fri, 29 May 2009 16:53:09 +0000 Subject: [PATCH 215/224] Fixed warning by removing unused variables [SVN r53397] --- include/boost/graph/dijkstra_shortest_paths_no_color_map.hpp | 1 - 1 file changed, 1 deletion(-) 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 8b7b3aa1..443984ff 100644 --- a/include/boost/graph/dijkstra_shortest_paths_no_color_map.hpp +++ b/include/boost/graph/dijkstra_shortest_paths_no_color_map.hpp @@ -93,7 +93,6 @@ namespace boost { // Examine neighbors of min_vertex typedef typename graph_traits::edge_descriptor Edge; - typename graph_traits::out_edge_iterator edge_iter, edge_iter_end; BGL_FORALL_OUTEDGES_T(min_vertex, current_edge, graph, Graph) { visitor.examine_edge(current_edge, graph); From 360e769758150526ce4f5adc5e9326089a48c359 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Fri, 29 May 2009 17:20:15 +0000 Subject: [PATCH 216/224] Changed template parameter name to un-confuse VC 10 [SVN r53399] --- include/boost/graph/transitive_closure.hpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/include/boost/graph/transitive_closure.hpp b/include/boost/graph/transitive_closure.hpp index a4742ab1..378dacf5 100644 --- a/include/boost/graph/transitive_closure.hpp +++ b/include/boost/graph/transitive_closure.hpp @@ -38,13 +38,13 @@ namespace boost namespace detail { - template < typename Container, typename ST = std::size_t, - typename VT = typename Container::value_type > + template < typename TheContainer, typename ST = std::size_t, + typename VT = typename TheContainer::value_type > struct subscript_t:public std::unary_function < ST, VT > { typedef VT& result_type; - subscript_t(Container & c):container(&c) + subscript_t(TheContainer & c):container(&c) { } VT & operator() (const ST & i) const @@ -52,11 +52,11 @@ namespace boost return (*container)[i]; } protected: - Container * container; + TheContainer * container; }; - template < typename Container > - subscript_t < Container > subscript(Container & c) { - return subscript_t < Container > (c); + template < typename TheContainer > + subscript_t < TheContainer > subscript(TheContainer & c) { + return subscript_t < TheContainer > (c); } } // namespace detail From c9ac66d0d8d04c04a32566dd0306f663aa80dabb Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Fri, 29 May 2009 18:12:24 +0000 Subject: [PATCH 217/224] Fixed warnings [SVN r53404] --- src/read_graphviz_new.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/read_graphviz_new.cpp b/src/read_graphviz_new.cpp index 8c84b0c1..9d434386 100644 --- a/src/read_graphviz_new.cpp +++ b/src/read_graphviz_new.cpp @@ -159,8 +159,13 @@ namespace read_graphviz_detail { void skip() { boost::match_results results; - bool found = boost::regex_search(begin, end, results, stuff_to_skip); +#ifndef NDEBUG + bool found = +#endif + boost::regex_search(begin, end, results, stuff_to_skip); +#ifndef NDEBUG assert (found); +#endif boost::sub_match sm1 = results.suffix(); assert (sm1.second == end); begin = sm1.first; @@ -406,7 +411,7 @@ namespace read_graphviz_detail { void parse_graph(bool want_directed) { bool is_strict = false; - bool is_directed; + bool is_directed = false; std::string name; if (peek().type == token::kw_strict) {get(); is_strict = true;} switch (peek().type) { From 8b185359efc7a28212aade8f9ef09ce91b504cf5 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Sun, 31 May 2009 01:32:55 +0000 Subject: [PATCH 218/224] Fixed links to property_map library [SVN r53475] --- doc/AStarVisitor.html | 2 +- doc/AddEdgeVisitor.html | 2 +- doc/DijkstraVisitor.html | 4 ++-- doc/PlanarEmbedding.html | 2 +- doc/PropertyGraph.html | 4 ++-- doc/PropertyTag.html | 2 +- doc/adjacency_list.html | 6 ++--- doc/astar_search.html | 12 +++++----- doc/bc_clustering.html | 4 ++-- doc/bellman_ford_shortest.html | 6 ++--- doc/betweenness_centrality.html | 24 +++++++++---------- doc/biconnected_components.html | 16 ++++++------- doc/boyer_myrvold.html | 4 ++-- doc/breadth_first_search.html | 6 ++--- doc/breadth_first_visit.html | 2 +- doc/bundles.html | 2 +- doc/circle_layout.html | 2 +- doc/connected_components.html | 8 +++---- doc/constructing_algorithms.html | 4 ++-- doc/copy_graph.html | 4 ++-- doc/dag_shortest_paths.html | 14 +++++------ doc/depth_first_search.html | 6 ++--- doc/depth_first_visit.html | 2 +- doc/dijkstra_shortest_paths.html | 14 +++++------ doc/dijkstra_shortest_paths_no_color_map.html | 10 ++++---- doc/distance_recorder.html | 2 +- doc/edmonds_karp_max_flow.html | 16 ++++++------- doc/floyd_warshall_shortest.html | 2 +- doc/fruchterman_reingold.html | 4 ++-- doc/gursoy_atun_layout.html | 6 ++--- doc/howard_cycle_ratio.html | 2 +- doc/is_kuratowski_subgraph.html | 2 +- doc/is_straight_line_drawing.html | 4 ++-- doc/isomorphism.html | 8 +++---- doc/johnson_all_pairs_shortest.html | 8 +++---- doc/kamada_kawai_spring_layout.html | 6 ++--- doc/kevin_bacon.html | 2 +- doc/kolmogorov_max_flow.html | 14 +++++------ doc/kruskal_min_spanning_tree.html | 12 +++++----- doc/lengauer_tarjan_dominator.htm | 6 ++--- doc/make_biconnected_planar.html | 2 +- doc/make_connected.html | 2 +- doc/make_maximal_planar.html | 6 ++--- doc/maximum_matching.html | 6 ++--- doc/metric_tsp_approx.html | 4 ++-- doc/minimum_degree_ordering.html | 10 ++++---- doc/planar_canonical_ordering.html | 2 +- doc/planar_face_traversal.html | 2 +- doc/planar_graphs.html | 2 +- doc/predecessor_recorder.html | 2 +- doc/prim_minimum_spanning_tree.html | 14 +++++------ doc/property_map.html | 6 ++--- doc/property_writer.html | 2 +- doc/push_relabel_max_flow.html | 8 +++---- doc/quick_tour.html | 2 +- doc/r_c_shortest_paths.html | 4 ++-- doc/random_layout.html | 2 +- doc/read_dimacs.html | 4 ++-- doc/sequential_vertex_coloring.html | 2 +- doc/stanford_graph.html | 8 +++---- doc/straight_line_drawing.html | 6 ++--- doc/strong_components.html | 16 ++++++------- doc/table_of_contents.html | 2 +- doc/time_stamper.html | 2 +- doc/topological_sort.html | 6 ++--- doc/transitive_closure.html | 2 +- doc/transpose_graph.html | 4 ++-- doc/tsp_tour_len_visitor.html | 2 +- doc/undirected_dfs.html | 8 +++---- doc/using_property_maps.html | 2 +- doc/write-graphviz.html | 2 +- doc/write_dimacs.html | 4 ++-- 72 files changed, 201 insertions(+), 201 deletions(-) diff --git a/doc/AStarVisitor.html b/doc/AStarVisitor.html index 422ecb7a..1ffad8d2 100644 --- a/doc/AStarVisitor.html +++ b/doc/AStarVisitor.html @@ -70,7 +70,7 @@ taken during the graph search. WeightMap A type that is a model of Readable Property +href="../../property_map/doc/ReadablePropertyMap.html">Readable Property Map. diff --git a/doc/AddEdgeVisitor.html b/doc/AddEdgeVisitor.html index 50ba8967..7f924d2e 100644 --- a/doc/AddEdgeVisitor.html +++ b/doc/AddEdgeVisitor.html @@ -106,7 +106,7 @@ no arguments.visit_vertex_pair(u, v, g) is just a dispatch to add_edge(u, v, g).

    6. edge_index_update_visitor: The constructor of this class takes two arguments: the first, an EdgeIndexMap, -is a +is a ReadWritePropertyMap that maps each edge in the associated graph g to a distinct integer in the range [0, num_edges(g)). The second argument is the number of edges in the underlying graph, which diff --git a/doc/DijkstraVisitor.html b/doc/DijkstraVisitor.html index 36b2c7e2..80782228 100644 --- a/doc/DijkstraVisitor.html +++ b/doc/DijkstraVisitor.html @@ -65,7 +65,7 @@ the search. DistanceMap -A type that is a model of Read/Write Property Map. +A type that is a model of Read/Write Property Map. @@ -75,7 +75,7 @@ the search. WeightMap -A type that is a model of Readable Property Map. +A type that is a model of Readable Property Map. diff --git a/doc/PlanarEmbedding.html b/doc/PlanarEmbedding.html index aae9e14b..fb24b076 100644 --- a/doc/PlanarEmbedding.html +++ b/doc/PlanarEmbedding.html @@ -27,7 +27,7 @@ the graph, of all of the edges incident on that vertex in the order in which they are to be drawn around that vertex.

      A planar embedding is a refinement of -LValuePropertyMap that +LValuePropertyMap that places additional restrictions the value_type used in the property map. diff --git a/doc/PropertyGraph.html b/doc/PropertyGraph.html index fb6f7598..0308103b 100644 --- a/doc/PropertyGraph.html +++ b/doc/PropertyGraph.html @@ -90,7 +90,7 @@ function which returns a property map object.

      boost::property_map<G, PropertyTag>::type
      The type of the property map for the property specified by PropertyTag. This type must be a model of ReadWritePropertyMap +href="../../property_map/doc/ReadWritePropertyMap.html">ReadWritePropertyMap with a key type the same as the graph's vertex or edge descriptor type. @@ -99,7 +99,7 @@ with a key type the same as the graph's vertex or edge descriptor type.
      boost::property_map<G, PropertyTag>::const_type
      The type of the const property map for the property specified by PropertyTag. This type must be a model of ReadablePropertyMap +href="../../property_map/doc/ReadablePropertyMap.html">ReadablePropertyMap with a key type the same as the graph's vertex or edge descriptor type. diff --git a/doc/PropertyTag.html b/doc/PropertyTag.html index 549aa2db..0dc7d023 100644 --- a/doc/PropertyTag.html +++ b/doc/PropertyTag.html @@ -96,7 +96,7 @@ href="../../../boost/graph/properties.hpp">boost/graph/properties.hppPropertyGraph and -Property Map Concepts +Property Map Concepts

      Notes

      diff --git a/doc/adjacency_list.html b/doc/adjacency_list.html index 670e49e5..03c1e353 100644 --- a/doc/adjacency_list.html +++ b/doc/adjacency_list.html @@ -175,13 +175,13 @@ properties is described in Section Internal Properties . The property maps are objects that implement the interface defined in Section Property Map +HREF="../../property_map/doc/property_map.html">Property Map Concepts or may be bundled properties, which have a more succinct syntax. The types of all property values must be Copy Constructible, Assignable, and Default Constructible. The property maps obtained from the adjacency_list class are models of the Lvalue Property +href="../../property_map/doc/LvaluePropertyMap.html">Lvalue Property Map concept. If the adjacency_list is const, then the property map is constant, otherwise the property map is mutable. @@ -194,7 +194,7 @@ the vertex_index_t property. The indices fall in the range removed the indices are adjusted so that they retain these properties. Some care must be taken when using these indices to access exterior property storage. The property map for vertex index is a -model of Readable +model of Readable Property Map.

      diff --git a/doc/astar_search.html b/doc/astar_search.html index 2ea0a6af..8f9dc2fa 100644 --- a/doc/astar_search.html +++ b/doc/astar_search.html @@ -256,7 +256,7 @@ IN: weight_map(WeightMap w_map) href="./exception.html#negative_edge">negative_edge exception if one of the edges is negative. The type WeightMap must be a model of Readable + href="../../property_map/doc/ReadablePropertyMap.html">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 @@ -270,7 +270,7 @@ IN: vertex_index_map(VertexIndexMap i_map) num_vertices(g)). This is necessary for efficient updates of the heap data structure when an edge is relaxed. The type VertexIndexMap must be a model of Readable + href="../../property_map/doc/ReadablePropertyMap.html">Readable Property Map. The value type of the map must be an integer type. The vertex descriptor type of the graph needs to be usable as the key type of the map.
      @@ -291,7 +291,7 @@ OUT: predecessor_map(PredecessorMap p_map) p[u] = u then u is either the start vertex or a vertex that is not reachable from the start. The PredecessorMap type must be a Read/Write + href="../../property_map/doc/ReadWritePropertyMap.html">Read/Write Property Map with key and vertex types the same as the vertex descriptor type of the graph.
      @@ -305,7 +305,7 @@ UTIL/OUT: distance_map(DistanceMap d_map) 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 + href="../../property_map/doc/ReadWritePropertyMap.html">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 is the element type of a rank_map(CostMap c_map) the estimated cost (as returned by the heuristic function h) from the vertex to a goal. The type CostMap must be a model of Read/Write + href="../../property_map/doc/ReadWritePropertyMap.html">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 is the element type of a color_map(ColorMap c_map) reachable from the source vertex will have been colored black. All other vertices will still be white. The type ColorMap must be a model of Read/Write + href="../../property_map/doc/ReadWritePropertyMap.html">Read/Write Property Map. A vertex descriptor must be usable as the key type of the map, and the value type of the map must be a model of Color Value.
      diff --git a/doc/bc_clustering.html b/doc/bc_clustering.html index fc677b3c..14fefb4b 100644 --- a/doc/bc_clustering.html +++ b/doc/bc_clustering.html @@ -96,7 +96,7 @@ OUT/UTIL: EdgeCentralityMap edge_centrality_map This property map is used to accumulate the betweenness centrality of each edge, and is a secondary form of output for the algorithm. The type EdgeCentralityMap must be a model of Read/Write + href="../../property_map/doc/ReadWritePropertyMap.html">Read/Write Property Map, with the graph's edge descriptor type as its key type. The value type of this property map should be the same as the value type of the CentralityMap property map.
      @@ -114,7 +114,7 @@ IN: VertexIndexMap vertex_index num_vertices(g))
      . This is necessary for efficient updates of the heap data structure when an edge is relaxed. The type VertexIndexMap must be a model of - Readable Property Map. The value type of the map must be an + Readable Property Map. The value type of the map must be an integer type. The vertex descriptor type of the graph needs to be usable as the key type of the map.
      Default: get(vertex_index, g). diff --git a/doc/bellman_ford_shortest.html b/doc/bellman_ford_shortest.html index 89268b0d..0adc4bcf 100644 --- a/doc/bellman_ford_shortest.html +++ b/doc/bellman_ford_shortest.html @@ -201,7 +201,7 @@ 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 + href="../../property_map/doc/ReadablePropertyMap.html">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.
      @@ -219,7 +219,7 @@ OUT: predecessor_map(PredecessorMap p_map) u then u is either the source vertex or a vertex that is not reachable from the source. The PredecessorMap type must be a Read/Write + href="../../property_map/doc/ReadWritePropertyMap.html">Read/Write Property Map which key and vertex types the same as the vertex descriptor type of the graph.
      Default: dummy_property_map
      @@ -232,7 +232,7 @@ IN/OUT: distance_map(DistanceMap d) The shortest path weight from the source vertex to each vertex in the graph g is recorded in this property map. The type DistanceMap must be a model of Read/Write + href="../../property_map/doc/ReadWritePropertyMap.html">Read/Write Property Map. The key type of the property map must be the vertex descriptor type of the graph, and the value type of the distance map must be const Graph& g
      UTIL: IncomingMap incoming
      This property map records the set of edges incoming to each vertex that comprise a shortest path from a particular source vertex through this vertex, and is used internally by the algorithm.The IncomingMap type must be a Lvalue Property + href="../../property_map/doc/LvaluePropertyMap.html">Lvalue Property Map whose key type is the same as the vertex descriptor type of the graph and whose value type is a Sequence (e.g., an std::vector) containing edge descriptors.
      Default: + href="../../property_map/doc/iterator_property_map.html"> iterator_property_map created from a std::vector of std::vector<Edge>, where Edge is the edge descriptor type of the graph.
      @@ -161,14 +161,14 @@ UTIL: DistanceMap distance_map vertex in the graph g is recorded in this property map, but the result is only used internally. The type DistanceMap must be a model of Read/Write + href="../../property_map/doc/ReadWritePropertyMap.html">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 is the element type of a Monoid.
      Default: + href="../../property_map/doc/iterator_property_map.html"> iterator_property_map created from a std::vector of the WeightMap's value type (or the vertices_size_type of the graph when no weight map exists) @@ -182,14 +182,14 @@ UTIL: DependencyMap dependency
      Property map used internally to accumulate partial betweenness centrality results. The type DependencyMap must be a model - of Read/Write + of Read/Write Property Map. The vertex descriptor type of the graph needs to be usable as the key type of the dependency map. The value type of the dependency map must be compatible with the value type of the centrality map.
      Default: + href="../../property_map/doc/iterator_property_map.html"> iterator_property_map created from a std::vector of the CentralityMap's value type of size num_vertices(g) and using the vertex_index @@ -203,14 +203,14 @@ UTIL: PathCountMap path_count Property map used internally to accumulate the number of paths that pass through each particular vertex. The type PathCountMap must be a model of Read/Write + href="../../property_map/doc/ReadWritePropertyMap.html">Read/Write Property Map. The vertex descriptor type of the graph needs to be usable as the key type of the dependency map. The value type of the dependency map must be an integral type large enough to store the number of paths in the graph.
      Default: + href="../../property_map/doc/iterator_property_map.html"> iterator_property_map created from a std::vector of the degree_size_type of the graph of size num_vertices(g) and using the vertex_index @@ -225,7 +225,7 @@ OUT/UTIL: CentralityMap centrality_map This property map is used to accumulate the betweenness centrality of each vertex, and is the primary output of the algorithm. The type CentralityMap must be a model of Read/Write + href="../../property_map/doc/ReadWritePropertyMap.html">Read/Write Property Map, with the graph's vertex descriptor type as its key type. The value type of this property map should be a floating-point or rational type.
      @@ -242,7 +242,7 @@ OUT/UTIL: EdgeCentralityMap edge_centrality_map This property map is used to accumulate the betweenness centrality of each edge, and is a secondary form of output for the algorithm. The type EdgeCentralityMap must be a model of Read/Write + href="../../property_map/doc/ReadWritePropertyMap.html">Read/Write Property Map, with the graph's edge descriptor type as its key type. The value type of this property map should be the same as the value type of the CentralityMap property map.
      @@ -260,7 +260,7 @@ IN: vertex_index_map(VertexIndexMap vertex_index) num_vertices(g)). This is necessary for efficient updates of the heap data structure when an edge is relaxed. The type VertexIndexMap must be a model of - Readable Property Map. The value type of the map must be an + Readable Property Map. The value type of the map must be an integer type. The vertex descriptor type of the graph needs to be usable as the key type of the map.
      Default: get(vertex_index, g). @@ -278,7 +278,7 @@ IN: weight_map(WeightMap w_map) negative_edge exception is one of the edges is negative. The type WeightMap must be a model of - Readable Property Map. The edge descriptor type 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.
      diff --git a/doc/biconnected_components.html b/doc/biconnected_components.html index 74b34c3b..50612ecb 100644 --- a/doc/biconnected_components.html +++ b/doc/biconnected_components.html @@ -120,7 +120,7 @@ and assigning each component an integer label. The algorithm then records which component each edge in the graph belongs to by recording the component number in the component property map. The ComponentMap type must be a model of Writable Property +href="../../property_map/doc/WritablePropertyMap.html">Writable Property Map. The value type shouch be an integer type, preferably the same as the edges_size_type of the graph. The key type must be the graph's edge descriptor type.
      @@ -147,7 +147,7 @@ IN: vertex_index_map(VertexIndexMap i_map) This maps each vertex to an integer in the range [0, num_vertices(g)). The type VertexIndexMap must be a model of - Readable Property Map. The value type of the map must be an + Readable Property Map. The value type of the map must be an integer type. The vertex descriptor type of the graph needs to be usable as the key type of the map.
      Default: get(vertex_index, g)
      @@ -159,12 +159,12 @@ UTIL/OUT: discover_time_map(DiscoverTimeMap discover_time)
      The discovery time of each vertex in the depth-first search. The type DiscoverTimeMap must be a model of Read/Write + href="../../property_map/doc/ReadWritePropertyMap.html">Read/Write Property Map. The value type of the map must be an integer type. The vertex descriptor type of the graph needs to be usable as the key type of the map.
      Default: an + href="../../property_map/doc/iterator_property_map.html"> iterator_property_map created from a std::vector of vertices_size_type of size num_vertices(g) and using get(vertex_index, g) for @@ -178,12 +178,12 @@ UTIL/OUT: lowpoint_map(LowPointMap lowpt) The low point of each vertex in the depth-first search, which is the smallest vertex reachable from a given vertex with at most one back edge. The type LowPointMap must be a model of Read/Write + href="../../property_map/doc/ReadWritePropertyMap.html">Read/Write Property Map. The value type of the map must be an integer type. The vertex descriptor type of the graph needs to be usable as the key type of the map.
      Default: an + href="../../property_map/doc/iterator_property_map.html"> iterator_property_map created from a std::vector of vertices_size_type of size num_vertices(g) and using get(vertex_index, g) for @@ -197,11 +197,11 @@ UTIL/OUT: predecessor_map(PredecessorMap p_map) The predecessor map records the depth first search tree. The PredecessorMap type must be a Read/Write + href="../../property_map/doc/ReadWritePropertyMap.html">Read/Write Property Map whose key and value types are the same as the vertex descriptor type of the graph.
      Default: an + href="../../property_map/doc/iterator_property_map.html"> iterator_property_map created from a std::vector of vertex_descriptor of size num_vertices(g) and using get(vertex_index, g) for diff --git a/doc/boyer_myrvold.html b/doc/boyer_myrvold.html index fdefdb41..9a63f29c 100644 --- a/doc/boyer_myrvold.html +++ b/doc/boyer_myrvold.html @@ -191,7 +191,7 @@ An OutputIterator which accepts values of the type IN VertexIndexMap vm
      -A Readable Property Map +A Readable Property Map that maps vertices from g to distinct integers in the range [0, num_vertices(g) )
      Default: get(vertex_index,g)
      @@ -200,7 +200,7 @@ A Readable Property Map IN EdgeIndexMap em
      -A Readable Property Map +A Readable Property Map that maps edges from g to distinct integers in the range [0, num_edges(g) )
      Default: get(edge_index,g), but this parameter is only used if diff --git a/doc/breadth_first_search.html b/doc/breadth_first_search.html index 5560285e..990f475a 100644 --- a/doc/breadth_first_search.html +++ b/doc/breadth_first_search.html @@ -194,12 +194,12 @@ UTIL/OUT: color_map(ColorMap color) function and do your own color initialization.

      The type ColorMap must be a model of Read/Write + href="../../property_map/doc/ReadWritePropertyMap.html">Read/Write Property Map and its key type must be the graph's vertex descriptor type and the value type of the color map must model ColorValue.
      Default: an + href="../../property_map/doc/iterator_property_map.html"> iterator_property_map created from a std::vector of default_color_type of size num_vertices(g) and using the i_map for the index @@ -215,7 +215,7 @@ IN: vertex_index_map(VertexIndexMap i_map) num_vertices(g)). This parameter is only necessary when the default color property map is used. The type VertexIndexMap must be a model of Readable Property + href="../../property_map/doc/ReadablePropertyMap.html">Readable Property Map. The value type of the map must be an integer type. The vertex descriptor type of the graph needs to be usable as the key type of the map.
      diff --git a/doc/breadth_first_visit.html b/doc/breadth_first_visit.html index a7309f02..11009d20 100644 --- a/doc/breadth_first_visit.html +++ b/doc/breadth_first_visit.html @@ -87,7 +87,7 @@ UTIL/OUT: color_map(ColorMap color)

      This is used by the algorithm to keep track of its progress through the graph. The type ColorMap must be a model of Read/Write + href="../../property_map/doc/ReadWritePropertyMap.html">Read/Write Property Map and its key type must be the graph's vertex descriptor type and the value type of the color map must model ColorValue.
      diff --git a/doc/bundles.html b/doc/bundles.html index f73ba623..d3a2e470 100644 --- a/doc/bundles.html +++ b/doc/bundles.html @@ -147,7 +147,7 @@ dijkstra_shortest_paths(map, from,

      You may also access the entire vertex or edge bundle as a property map using the vertex_bundle or edge_bundle properties, respectively. For instance, the property map returned by get(vertex_bundle, map) is - an Lvalue Property Map providing access to the + an Lvalue Property Map providing access to the City values stored in each vertex.

      Getting the type of bundled properties

      diff --git a/doc/circle_layout.html b/doc/circle_layout.html index 31e5d470..c51aeb61 100644 --- a/doc/circle_layout.html +++ b/doc/circle_layout.html @@ -23,7 +23,7 @@ OUT: PositionMap position
      This property map is used to store the position of each vertex. The type PositionMap must be a model of Writable Property + href="../../property_map/doc/WritablePropertyMap.html">Writable Property Map, with the graph's edge descriptor type as its key type. The value type of this property map should be assignable from the type Radius.
      diff --git a/doc/connected_components.html b/doc/connected_components.html index 776cfc0e..e0975cd3 100644 --- a/doc/connected_components.html +++ b/doc/connected_components.html @@ -74,7 +74,7 @@ and assigning each component an integer label. The algorithm then records which component each vertex in the graph belongs to by recording the component number in the component property map. The ComponentMap type must be a model of Writable Property +href="../../property_map/doc/WritablePropertyMap.html">Writable Property Map. The value type shouch be an integer type, preferably the same as the vertices_size_type of the graph. The key type must be the graph's vertex descriptor type.
      @@ -89,12 +89,12 @@ UTIL: color_map(ColorMap color)
      This is used by the algorithm to keep track of its progress through the graph. The type ColorMap must be a model of Read/Write + href="../../property_map/doc/ReadWritePropertyMap.html">Read/Write Property Map and its key type must be the graph's vertex descriptor type and the value type of the color map must model ColorValue.
      Default: an + href="../../property_map/doc/iterator_property_map.html"> iterator_property_map created from a std::vector of default_color_type of size num_vertices(g) and using the i_map for the index @@ -109,7 +109,7 @@ IN: vertex_index_map(VertexIndexMap i_map) num_vertices(g)). This parameter is only necessary when the default color property map is used. The type VertexIndexMap must be a model of Readable Property + href="../../property_map/doc/ReadablePropertyMap.html">Readable Property Map. The value type of the map must be an integer type. The vertex descriptor type of the graph needs to be usable as the key type of the map.
      diff --git a/doc/constructing_algorithms.html b/doc/constructing_algorithms.html index 79322828..82bd2d47 100644 --- a/doc/constructing_algorithms.html +++ b/doc/constructing_algorithms.html @@ -91,12 +91,12 @@ use the propery map interface. This gives the user of the algorithm the ability to decide how they want to store the properties. Since we will need to both read and write the colors we specify the requirements as ReadWritePropertyMap. The +href="../../property_map/doc/ReadWritePropertyMap.html">ReadWritePropertyMap. The key_type of the color map must be the vertex_descriptor from the graph, and the value_type must be some kind of integer. We also specify the interface for the order parameter as a property map, in this case a ReadablePropertyMap. For +href="../../property_map/doc/ReadablePropertyMap.html">ReadablePropertyMap. For order, the key_type is an integer offset and the value_type is a vertex_descriptor. Again we enforce these requirements with concept checks. The return value of this diff --git a/doc/copy_graph.html b/doc/copy_graph.html index 72912d6b..93e56478 100644 --- a/doc/copy_graph.html +++ b/doc/copy_graph.html @@ -73,7 +73,7 @@ map from the graph. IN: vertex_index_map(VertexIndexMap i_map)
      The vertex index map type must be a model of Readable Property +href="../../property_map/doc/ReadablePropertyMap.html">Readable Property Map and must map the vertex descriptors of G to the integers in the half-open range [0,num_vertices(G)).
      @@ -90,7 +90,7 @@ UTIL/OUT: orig_to_copy(Orig2CopyMap c) This maps vertices in the original graph to vertices in the copy. Default: an + href="../../property_map/doc/iterator_property_map.html"> iterator_property_map created from a std::vector of the output graph's vertex descriptor type of size num_vertices(g) and using the i_map for the index diff --git a/doc/dag_shortest_paths.html b/doc/dag_shortest_paths.html index b3844e3f..89cdff46 100644 --- a/doc/dag_shortest_paths.html +++ b/doc/dag_shortest_paths.html @@ -96,7 +96,7 @@ IN: weight_map(WeightMap w_map)
      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 + 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.
      @@ -112,7 +112,7 @@ IN: vertex_index_map(VertexIndexMap i_map) num_vertices(g)). This is necessary for efficient updates of the heap data structure when an edge is relaxed. The type VertexIndexMap must be a model of - Readable Property Map. The value type of the map must be an + Readable Property Map. The value type of the map must be an integer type. The vertex descriptor type of the graph needs to be usable as the key type of the map.
      Default: get(vertex_index, g). @@ -132,7 +132,7 @@ OUT: predecessor_map(PredecessorMap p_map) u then u is either the source vertex or a vertex that is not reachable from the source. The PredecessorMap type must be a Read/Write + href="../../property_map/doc/ReadWritePropertyMap.html">Read/Write Property Map which key and vertex types the same as the vertex descriptor type of the graph.
      Default: dummy_property_map
      @@ -145,7 +145,7 @@ UTIL/OUT: distance_map(DistanceMap d_map) 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 + href="../../property_map/doc/ReadWritePropertyMap.html">Read/Write Property Map. The vertex descriptor type of the graph needs to be usable as the key type of the distance map. @@ -157,7 +157,7 @@ UTIL/OUT: distance_map(DistanceMap d_map) StrictWeakOrdering provided by the compare function object.
      Default: + href="../../property_map/doc/iterator_property_map.html"> 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 @@ -228,12 +228,12 @@ UTIL/OUT: color_map(ColorMap c_map) from the queue. At the end of the algorithm, vertices reachable from the source vertex will have been colored black. All other vertices will still be white. The type ColorMap must be a model of - Read/Write + Read/Write Property Map. A vertex descriptor must be usable as the key type of the map, and the value type of the map must be a model of Color Value.
      Default: an + href="../../property_map/doc/iterator_property_map.html"> iterator_property_map created from a std::vector of default_color_type of size num_vertices(g) and using the i_map for the index map.
      diff --git a/doc/depth_first_search.html b/doc/depth_first_search.html index d60e78c8..aacc2e7d 100644 --- a/doc/depth_first_search.html +++ b/doc/depth_first_search.html @@ -185,12 +185,12 @@ UTIL/OUT: color_map(ColorMap color)
      This is used by the algorithm to keep track of its progress through the graph. The type ColorMap must be a model of Read/Write + href="../../property_map/doc/ReadWritePropertyMap.html">Read/Write Property Map and its key type must be the graph's vertex descriptor type and the value type of the color map must model ColorValue.
      Default: an + href="../../property_map/doc/iterator_property_map.html"> iterator_property_map created from a std::vector of default_color_type of size num_vertices(g) and using the i_map for the index @@ -215,7 +215,7 @@ IN: vertex_index_map(VertexIndexMap i_map) num_vertices(g)). This parameter is only necessary when the default color property map is used. The type VertexIndexMap must be a model of Readable Property + href="../../property_map/doc/ReadablePropertyMap.html">Readable Property Map. The value type of the map must be an integer type. The vertex descriptor type of the graph needs to be usable as the key type of the map.
      diff --git a/doc/depth_first_visit.html b/doc/depth_first_visit.html index e192cc18..597f5fc5 100644 --- a/doc/depth_first_visit.html +++ b/doc/depth_first_visit.html @@ -96,7 +96,7 @@ UTIL: ColorMap color
      This is used by the algorithm to keep track of its progress through the graph. The type ColorMap must be a model of Read/Write + href="../../property_map/doc/ReadWritePropertyMap.html">Read/Write Property Map and its key type must be the graph's vertex descriptor type and the value type of the color map map must model Color Value.
      diff --git a/doc/dijkstra_shortest_paths.html b/doc/dijkstra_shortest_paths.html index af05cfaf..2d10220b 100644 --- a/doc/dijkstra_shortest_paths.html +++ b/doc/dijkstra_shortest_paths.html @@ -215,7 +215,7 @@ IN: weight_map(WeightMap w_map) negative_edge exception is one of the edges is negative. The type WeightMap must be a model of - Readable Property Map. The edge descriptor type 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.
      @@ -233,7 +233,7 @@ IN: vertex_index_map(VertexIndexMap i_map) HREF="bibliography.html#driscoll88">61] when an edge is relaxed. The type VertexIndexMap must be a model of - Readable Property Map. The value type of the map must be an + Readable Property Map. The value type of the map must be an integer type. The vertex descriptor type of the graph needs to be usable as the key type of the map.
      Default: get(vertex_index, g). @@ -254,7 +254,7 @@ OUT: predecessor_map(PredecessorMap p_map) u
      then u is either the source vertex or a vertex that is not reachable from the source. The PredecessorMap type must be a Read/Write + href="../../property_map/doc/ReadWritePropertyMap.html">Read/Write Property Map whose key and value types are the same as the vertex descriptor type of the graph.
      Default: dummy_property_map
      @@ -268,7 +268,7 @@ UTIL/OUT: distance_map(DistanceMap d_map) 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 + href="../../property_map/doc/ReadWritePropertyMap.html">Read/Write Property Map. The vertex descriptor type of the graph needs to be usable as the key type of the distance map. @@ -280,7 +280,7 @@ UTIL/OUT: distance_map(DistanceMap d_map) StrictWeakOrdering provided by the compare function object.
      Default: + href="../../property_map/doc/iterator_property_map.html"> 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 @@ -352,12 +352,12 @@ UTIL/OUT: color_map(ColorMap c_map) from the queue. At the end of the algorithm, vertices reachable from the source vertex will have been colored black. All other vertices will still be white. The type ColorMap must be a model of - Read/Write + Read/Write Property Map. A vertex descriptor must be usable as the key type of the map, and the value type of the map must be a model of Color Value.
      Default: an + href="../../property_map/doc/iterator_property_map.html"> iterator_property_map created from a std::vector of default_color_type of size num_vertices(g) and using the i_map for the index map.
      diff --git a/doc/dijkstra_shortest_paths_no_color_map.html b/doc/dijkstra_shortest_paths_no_color_map.html index 1efba2a1..097f204b 100644 --- a/doc/dijkstra_shortest_paths_no_color_map.html +++ b/doc/dijkstra_shortest_paths_no_color_map.html @@ -193,7 +193,7 @@ IN: weight_map(WeightMap weight_map) negative_edge exception is one of the edges is negative. The type WeightMap must be a model of - Readable Property Map. The edge descriptor type 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.
      @@ -208,7 +208,7 @@ IN: index_map(VertexIndexMap index_map) HREF="bibliography.html#driscoll88">61] when an edge is relaxed. The type VertexIndexMap must be a model of - Readable Property Map. The value type of the map must be an + Readable Property Map. The value type of the map must be an integer type. The vertex descriptor type of the graph needs to be usable as the key type of the map.
      Default: get(vertex_index, graph). @@ -227,7 +227,7 @@ OUT: predecessor_map(PredecessorMap predecessor_map) u then u is either the source vertex or a vertex that is not reachable from the source. The PredecessorMap type must be a Read/Write + href="../../property_map/doc/ReadWritePropertyMap.html">Read/Write Property Map whose key and value types are the same as the vertex descriptor type of the graph.
      Default: dummy_property_map
      @@ -241,7 +241,7 @@ UTIL/OUT: distance_map(DistanceMap distance_map) vertex in the graph graph 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 + href="../../property_map/doc/ReadWritePropertyMap.html">Read/Write Property Map. The vertex descriptor type of the graph needs to be usable as the key type of the distance map. @@ -253,7 +253,7 @@ UTIL/OUT: distance_map(DistanceMap distance_map) StrictWeakOrdering provided by the distance_compare function object.
      Default: + href="../../property_map/doc/iterator_property_map.html"> iterator_property_map created from a std::vector of the WeightMap's value type of size num_vertices(graph) and using the index_map for the index diff --git a/doc/distance_recorder.html b/doc/distance_recorder.html index 2555c324..235b3445 100644 --- a/doc/distance_recorder.html +++ b/doc/distance_recorder.html @@ -64,7 +64,7 @@ See the example for bfs_visitor. DistanceMap A WritablePropertyMap, +href="../../property_map/doc/WritablePropertyMap.html">WritablePropertyMap, where the key type and the value type are the vertex descriptor type of the graph. diff --git a/doc/edmonds_karp_max_flow.html b/doc/edmonds_karp_max_flow.html index 69389534..7d8a28f8 100644 --- a/doc/edmonds_karp_max_flow.html +++ b/doc/edmonds_karp_max_flow.html @@ -125,7 +125,7 @@ IN: capacity_map(CapacityEdgeMap cap)
      The edge capacity property map. The type must be a model of a constant Lvalue Property Map. The + href="../../property_map/doc/LvaluePropertyMap.html">Lvalue Property Map. The key type of the map must be the graph's edge descriptor type.
      Default: get(edge_capacity, g)
      @@ -134,7 +134,7 @@ OUT: residual_capacity_map(ResidualCapacityEdgeMap res)
      This maps edges to their residual capacity. The type must be a model of a mutable Lvalue Property + href="../../property_map/doc/LvaluePropertyMap.html">Lvalue Property Map. The key type of the map must be the graph's edge descriptor type.
      Default: get(edge_residual_capacity, g) @@ -144,7 +144,7 @@ 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 + constant Lvalue Property Map. The key type of the map must be the graph's edge descriptor type.
      Default: get(edge_reverse, g) @@ -156,13 +156,13 @@ UTIL: color_map(ColorMap color) breadth-first search stage. At the end of the algorithm, the white vertices define the minimum cut set. The map must be a model of mutable Lvalue Property Map. + href="../../property_map/doc/LvaluePropertyMap.html">Lvalue Property Map. The key type of the map should be the graph's vertex descriptor type, and the value type must be a model of ColorValue.
      Default: an + href="../../property_map/doc/iterator_property_map.html"> iterator_property_map created from a std::vector of default_color_type of size num_vertices(g) and using the i_map for the index map. @@ -172,12 +172,12 @@ UTIL: predecessor_map(PredEdgeMap pred)
      Use by the algorithm to store augmenting paths. The map must be a model of mutable Lvalue Property Map. + href="../../property_map/doc/LvaluePropertyMap.html">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 + href="../../property_map/doc/iterator_property_map.html"> 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. @@ -189,7 +189,7 @@ IN: vertex_index_map(VertexIndexMap i_map) [0, num_vertices(g)). This property map is only needed if the default for the color or predecessor map is used. The vertex index map must be a model of Readable Property + href="../../property_map/doc/ReadablePropertyMap.html">Readable Property Map. The key type of the map must be the graph's vertex descriptor type.
      Default: get(vertex_index, g) diff --git a/doc/floyd_warshall_shortest.html b/doc/floyd_warshall_shortest.html index f4a22a28..b7ca894f 100644 --- a/doc/floyd_warshall_shortest.html +++ b/doc/floyd_warshall_shortest.html @@ -101,7 +101,7 @@ matrix will be initialized for the user. IN: weight_map(WeightMap w)
      The weight of length of each edge in the graph. The WeightMap -must be a model of Readable Property +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 of the weight map must be the type of the diff --git a/doc/fruchterman_reingold.html b/doc/fruchterman_reingold.html index 4b890dc2..d08fab05 100644 --- a/doc/fruchterman_reingold.html +++ b/doc/fruchterman_reingold.html @@ -96,7 +96,7 @@ IN/OUT: PositionMap position typically be initialized with the vertices at random locations (use random_graph_layout). The type PositionMap must be a model of Lvalue Property + href="../../property_map/doc/LvaluePropertyMap.html">Lvalue Property Map such that the vertex descriptor type of Graph is convertible to its key type. Its value type must be a structure with fields x and y, representing the coordinates @@ -197,7 +197,7 @@ IN: vertex_index_map(VertexIndexMap i_map) num_vertices(g)). This is only necessary when no displacement map is provided. The type VertexIndexMap must be a model of Readable Property + href="../../property_map/doc/ReadablePropertyMap.html">Readable Property Map. The value type of the map must be an integer type. The vertex descriptor type of the graph needs to be usable as the key type of the map.
      diff --git a/doc/gursoy_atun_layout.html b/doc/gursoy_atun_layout.html index c927fd1b..f73c26af 100644 --- a/doc/gursoy_atun_layout.html +++ b/doc/gursoy_atun_layout.html @@ -126,7 +126,7 @@ OUT: PositionMap position
      The property map that stores the position of each vertex. The type PositionMap must be a model of Lvalue Property + href="../../property_map/doc/LvaluePropertyMap.html">Lvalue Property Map such that the vertex descriptor type of Graph is convertible to its key type. Its value type must be the type of a point in the topology. @@ -180,7 +180,7 @@ IN: VertexIndexMap vertex_index_map This maps each vertex to an integer in the range [0, num_vertices(g)). The type VertexIndexMap must be a model of Readable Property + href="../../property_map/doc/ReadablePropertyMap.html">Readable Property Map. The value type of the map must be an integer type. The vertex descriptor type of the graph needs to be usable as the key type of the map.
      @@ -197,7 +197,7 @@ IN: EdgeWeightMap weight num_vertices(g)). This is only necessary when no displacement map is provided. The type EdgeWeightMap must be a model of Readable Property + href="../../property_map/doc/ReadablePropertyMap.html">Readable Property Map. The value type of the map must be an floating-point type compatible with double. The edge descriptor type of the graph needs to be usable as the key type of the map. When this map diff --git a/doc/howard_cycle_ratio.html b/doc/howard_cycle_ratio.html index 1deb6317..bccd55f7 100644 --- a/doc/howard_cycle_ratio.html +++ b/doc/howard_cycle_ratio.html @@ -147,7 +147,7 @@ in the range [0, num_edges(g)). < boost::graph_traits<TGraph>::edge_descriptor>* pcc

      An edge descriptors of one critical cycle will be stored in the corresponding std::vector. Default value is 0.
      -The all maps must be a models of Readable +The all maps must be a models of Readable Property Map

      Complexity

      There is no known precise upper bound for the time complexity of the diff --git a/doc/is_kuratowski_subgraph.html b/doc/is_kuratowski_subgraph.html index 381c1d30..310adeb3 100644 --- a/doc/is_kuratowski_subgraph.html +++ b/doc/is_kuratowski_subgraph.html @@ -98,7 +98,7 @@ A ForwardIterator with value_type IN: VertexIndexMap vm

      -A Readable Property Map +A Readable Property Map that maps vertices from g to distinct integers in the range [0, num_vertices(g) )
      Default: get(vertex_index,g)
      diff --git a/doc/is_straight_line_drawing.html b/doc/is_straight_line_drawing.html index e55f489a..1f7cca0a 100644 --- a/doc/is_straight_line_drawing.html +++ b/doc/is_straight_line_drawing.html @@ -56,7 +56,7 @@ href="EdgeListGraph.html">Edge List Graph IN: PositionMap
      -A Readable LValue Property +A Readable LValue Property Map that models the Position Map concept. The Position Map concept requires that the value mapped to be an object that has members x and y. For example, if p models PositionMap and v @@ -68,7 +68,7 @@ convertable to std::size_t. IN: VertexIndexMap vm
      -A Readable Property Map that maps vertices from g to distinct integers in the range [0, num_vertices(g) )
      +A Readable Property Map that maps vertices from g to distinct integers in the range [0, num_vertices(g) )
      Default: get(vertex_index,g)
      diff --git a/doc/isomorphism.html b/doc/isomorphism.html index 14cca9e4..7a8a3d81 100644 --- a/doc/isomorphism.html +++ b/doc/isomorphism.html @@ -93,9 +93,9 @@ href="./VertexListGraph.html">Vertex List Graph. OUT: isomorphism_map(IsoMap f)
      The mapping from vertices in graph 1 to vertices in graph 2. This must -be a Read/Write +be a Read/Write Property Map.
      Default: an iterator_property_map +href="../../property_map/doc/iterator_property_map.html">iterator_property_map constructed from a std::vector of graph 2's vertex descriptor type and the vertex index map for graph 1.
      Python: Must be a vertex_vertex_map for the first graph. @@ -147,7 +147,7 @@ This maps each vertex to an integer in the range [0, num_vertices(g)). This is necessary for efficient updates of the heap data structure when an edge is relaxed. The type VertexIndex1Map must be a model of Readable Property +href="../../property_map/doc/ReadablePropertyMap.html">Readable Property Map. The value type of the map must be an integer type. The vertex descriptor type of graph 1 needs to be usable as the key type of the map.
      @@ -166,7 +166,7 @@ This maps each vertex to an integer in the range [0, num_vertices(g)). This is necessary for efficient updates of the heap data structure when an edge is relaxed. The type VertexIndex2Map must be a model of Readable Property +href="../../property_map/doc/ReadablePropertyMap.html">Readable Property Map. The value type of the map must be an integer type. The vertex descriptor type of graph 2 needs to be usable as the key type of the map.
      diff --git a/doc/johnson_all_pairs_shortest.html b/doc/johnson_all_pairs_shortest.html index 190b4c6f..d41e6b81 100644 --- a/doc/johnson_all_pairs_shortest.html +++ b/doc/johnson_all_pairs_shortest.html @@ -88,7 +88,7 @@ IN: weight_map(WeightMap w_map)
      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 + 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.
      @@ -106,7 +106,7 @@ IN: vertex_index_map(VertexIndexMap i_map) num_vertices(g))
      . This is necessary for efficient updates of the heap data structure in the internal call to Dijkstra's algorithm. The type VertexIndexMap must be a model of - Readable Property Map. The value type of the map must be an + Readable Property Map. The value type of the map must be an integer type. The vertex descriptor type of the graph needs to be usable as the key type of the map.
      Default: get(vertex_index, g) @@ -172,12 +172,12 @@ UTIL/OUT: color_map(ColorMap c_map) from the queue. At the end of the algorithm, vertices reachable from the source vertex will have been colored black. All other vertices will still be white. The type ColorMap must be a model of - Read/Write + Read/Write Property Map. A vertex descriptor must be usable as the key type of the map, and the value type of the map must be a model of Color Value.
      Default: an + href="../../property_map/doc/iterator_property_map.html"> iterator_property_map created from a std::vector of default_color_type of size num_vertices(g) and using the i_map for the index map. diff --git a/doc/kamada_kawai_spring_layout.html b/doc/kamada_kawai_spring_layout.html index e5e5ee04..674253a9 100644 --- a/doc/kamada_kawai_spring_layout.html +++ b/doc/kamada_kawai_spring_layout.html @@ -157,7 +157,7 @@ OUT: PositionMap position
      This property map is used to store the position of each vertex. The type PositionMap must be a model of Writable Property + href="../../property_map/doc/WritablePropertyMap.html">Writable Property Map, with the graph's vertex descriptor type as its key type.
      Python: The position map must be a vertex_point2d_map for @@ -172,7 +172,7 @@ IN: weight_map(WeightMap w_map) negative_edge exception is one of the edges is negative. The type WeightMap must be a model of - Readable Property Map. The edge descriptor type 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.
      @@ -260,7 +260,7 @@ UTIL: PartialDerivativeMap partial_derivatives A property map that will be used to store the partial derivates of each vertex with respect to the x and y coordinates. This must be a -Read/Write +Read/Write Property Map whose value type is a pair with both types equivalent to the value type of the weight map. The default is an iterator property map.
      diff --git a/doc/kevin_bacon.html b/doc/kevin_bacon.html index 0a62638a..8b2670bd 100644 --- a/doc/kevin_bacon.html +++ b/doc/kevin_bacon.html @@ -281,7 +281,7 @@ with the adjacency_list class with VertexList=vecS, but not with other variations of adjacency_list. A more generic way to index based on vertices is to use the ID property map (vertex_index_t) in coordination with the iterator_property_map. +HREF="../../property_map/doc/iterator_property_map.html">iterator_property_map.

      Here are some excepts from the output of the program. diff --git a/doc/kolmogorov_max_flow.html b/doc/kolmogorov_max_flow.html index d5437ac7..f57a5762 100644 --- a/doc/kolmogorov_max_flow.html +++ b/doc/kolmogorov_max_flow.html @@ -230,14 +230,14 @@ must also be in the graph.

      IN: edge_capacity(EdgeCapacityMap cap)

      The edge capacity property map. The type must be a model -of a constant Lvalue +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 +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) @@ -246,14 +246,14 @@ g)

      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 +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 +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)
      @@ -263,7 +263,7 @@ descriptor type.
      Default: get(vertex_predecessor, g) 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 +Lvalue Property Map. The key type of the map must be the graph's vertex descriptor type.
      Default: get(vertex_color, g)
      @@ -271,7 +271,7 @@ descriptor type.
      Default: get(vertex_color, g)

      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 +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)
      @@ -279,7 +279,7 @@ descriptor type.
      Default: get(vertex_distance, g)

      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. +constant LvaluePropertyMap. The key type of the map must be the graph's vertex descriptor type.
      Default: get(vertex_index, g)
      diff --git a/doc/kruskal_min_spanning_tree.html b/doc/kruskal_min_spanning_tree.html index 37d11270..7b7277d4 100644 --- a/doc/kruskal_min_spanning_tree.html +++ b/doc/kruskal_min_spanning_tree.html @@ -106,7 +106,7 @@ IN: weight_map(WeightMap w_map)
      The weight or ``length'' of each edge in the graph. The WeightMap type must be a model - of Readable + of Readable Property Map and its value type must be Less Than Comparable. The key type of this map needs to be the graph's @@ -120,12 +120,12 @@ UTIL: rank_map(RankMap r_map)
      This is used by the disjoint sets data structure. The type RankMap must be a model of Read/Write + href="../../property_map/doc/ReadWritePropertyMap.html">Read/Write Property Map. The vertex descriptor type of the graph needs to be usable as the key type of the rank map. The value type of the rank map must be an integer type.
      Default: an + href="../../property_map/doc/iterator_property_map.html"> iterator_property_map created from a std::vector of the integers of size num_vertices(g) and using the i_map for the index @@ -140,11 +140,11 @@ UTIL: predecessor_map(PredecessorMap p_map) used for storing predecessors in the spanning tree. The predecessors of the spanning tree can be obtained from the spanning tree edges output. The type PredecessorMap must be a model of Read/Write + href="../../property_map/doc/ReadWritePropertyMap.html">Read/Write Property Map. The key type value types of the predecessor map must be the vertex descriptor type of the graph.
      Default: an + href="../../property_map/doc/iterator_property_map.html"> iterator_property_map created from a std::vector of vertex descriptors of size num_vertices(g) and using the i_map for the index @@ -159,7 +159,7 @@ IN: vertex_index_map(VertexIndexMap i_map) num_vertices(g)). This is only necessary if the default is used for the rank or predecessor maps. The type VertexIndexMap must be a model of Readable Property + href="../../property_map/doc/ReadablePropertyMap.html">Readable Property Map. The value type of the map must be an integer type. The vertex descriptor type of the graph needs to be usable as the key type of the map.
      diff --git a/doc/lengauer_tarjan_dominator.htm b/doc/lengauer_tarjan_dominator.htm index e6e70ff6..23a00963 100644 --- a/doc/lengauer_tarjan_dominator.htm +++ b/doc/lengauer_tarjan_dominator.htm @@ -133,19 +133,19 @@ IN: IndexMap indexMap This maps each vertex to an integer in the range [0, num_vertices(g)). The type VertexIndexMap must be a model of - Readable Property Map. The value type of the map must be an + Readable Property Map. The value type of the map must be an integer type. The vertex descriptor type of the graph needs to be usable as the key type of the map.
      IN/OUT: TimeMap dfnumMap
      - The sequence number of depth first search. The type TimeMap 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 TimeMap. + The sequence number of depth first search. The type TimeMap 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 TimeMap.
      IN/OUT: PredMap parentMap
      - The predecessor map records the parent of the depth first search tree. The PredMap type must be a Read/Write Property Map whose key and value types are the same as the vertex descriptor type of the graph. + The predecessor map records the parent of the depth first search tree. The PredMap type must be a Read/Write Property Map whose key and value types are the same as the vertex descriptor type of the graph.
      IN/OUT: VertexVector verticesByDFNum diff --git a/doc/make_biconnected_planar.html b/doc/make_biconnected_planar.html index e2796998..53c4ff82 100644 --- a/doc/make_biconnected_planar.html +++ b/doc/make_biconnected_planar.html @@ -77,7 +77,7 @@ A model of PlanarEmbedding. IN: EdgeIndexMap vm
      -A Readable Property Map +A Readable Property Map that maps edges from g to distinct integers in the range [0, num_edges(g) )
      Default: get(edge_index,g)
      diff --git a/doc/make_connected.html b/doc/make_connected.html index eeb046fd..d757ca02 100644 --- a/doc/make_connected.html +++ b/doc/make_connected.html @@ -74,7 +74,7 @@ a Mutable Graph
      IN: VertexIndexMap vm
      -A Readable Property Map +A Readable Property Map that maps vertices from g to distinct integers in the range [0, num_vertices(g) )
      Default: get(vertex_index,g)
      diff --git a/doc/make_maximal_planar.html b/doc/make_maximal_planar.html index e284590e..944e3b56 100644 --- a/doc/make_maximal_planar.html +++ b/doc/make_maximal_planar.html @@ -72,7 +72,7 @@ a Mutable Graph
      IN: PlanarEmbedding embedding
      -A Readable Property Map +A Readable Property Map that models the PlanarEmbedding concept.
      @@ -80,7 +80,7 @@ concept. IN: VertexIndexMap vm
      -A Readable Property Map +A Readable Property Map that maps vertices from g to distinct integers in the range [0, num_vertices(g) )
      Default: get(vertex_index,g)
      @@ -89,7 +89,7 @@ A Readable Property Map IN: EdgeIndexMap vm
      -A Readable Property Map +A Readable Property Map that maps edges from g to distinct integers in the range [0, num_edges(g) )
      Default: get(edge_index,g)
      diff --git a/doc/maximum_matching.html b/doc/maximum_matching.html index 221dd403..e16c87fb 100644 --- a/doc/maximum_matching.html +++ b/doc/maximum_matching.html @@ -50,7 +50,7 @@ Both edmonds_maximum_cardinality_matching and checked_edmonds_maximum_cardinality_matching find the maximum cardinality matching in any undirected graph. The matching is returned in a MateMap, which is a -ReadWritePropertyMap +ReadWritePropertyMap that maps vertices to vertices. In the mapping returned, each vertex is either mapped to the vertex it's matched to, or to graph_traits<Graph>::null_vertex() if it doesn't participate in the matching. If no VertexIndexMap is provided, both functions @@ -238,12 +238,12 @@ An undirected graph. The graph type must be a model of IN: VertexIndexMap vm
      -Must be a model of ReadablePropertyMap, mapping vertices to integer indices. +Must be a model of ReadablePropertyMap, mapping vertices to integer indices.
      OUT: MateMap mate
      -Must be a model of ReadWritePropertyMap, mapping +Must be a model of ReadWritePropertyMap, mapping vertices to vertices. For any vertex v in the graph, get(mate,v) will be the vertex that v is matched to, or graph_traits::null_vertex() if v isn't matched.
      diff --git a/doc/metric_tsp_approx.html b/doc/metric_tsp_approx.html index 11dde904..ad6b9b4d 100644 --- a/doc/metric_tsp_approx.html +++ b/doc/metric_tsp_approx.html @@ -125,7 +125,7 @@ IN: WeightMap weightmap
      The weight of each edge in the graph. The type WeightMap must be a model of - Readable Property Map. The edge descriptor type of + Readable Property Map. The edge descriptor type of the graph needs to be usable as the key type for the weight map.
      Default: get(edge_weight, g)
      @@ -137,7 +137,7 @@ IN: VertexIndexMap indexmap num_vertices(g)). This is necessary for efficient updates of the heap data structure when an edge is relaxed. The type VertexIndexMap must be a model of - Readable Property Map. The value type of the map must be an + Readable Property Map. The value type of the map must be an integer type. The vertex descriptor type of the graph needs to be usable as the key type of the map.
      Default: get(vertex_index, g) diff --git a/doc/minimum_degree_ordering.html b/doc/minimum_degree_ordering.html index 0343b922..4b92662d 100644 --- a/doc/minimum_degree_ordering.html +++ b/doc/minimum_degree_ordering.html @@ -92,7 +92,7 @@ The output of the algorithm are the vertices in the new ordering.
    7. OutDegreeMap outdegree  (WORK)
      This is used internally to store the out degree of vertices. This - must be a + must be a LvaluePropertyMap with key type the same as the vertex descriptor type of the graph, and with a value type that is an integer type. @@ -100,19 +100,19 @@ The output of the algorithm are the vertices in the new ordering.
    8. InversePermutationMap inverse_perm  (OUT)
      The new vertex ordering, given as the mapping from the new indices to the old indices (an inverse permutation). - This must be an + This must be an LvaluePropertyMap with a value type and key type a signed integer.
    9. PermutationMap perm  (OUT)
      The new vertex ordering, given as the mapping from the old indices to the new indices (a permutation). - This must be an + This must be an LvaluePropertyMap with a value type and key type a signed integer.
    10. SuperNodeSizeMap supernode_size  (WORK/OUT)
      This is used internally to record the size of supernodes and is also useful information to have. This is a + href="../../property_map/doc/LvaluePropertyMap.html"> LvaluePropertyMap with an unsigned integer value type and key type of vertex descriptor. @@ -124,7 +124,7 @@ The output of the algorithm are the vertices in the new ordering.
    11. VertexIndexMap id  (IN)
      Used internally to map vertices to their indices. This must be a Readable + href="../../property_map/doc/ReadablePropertyMap.html"> Readable Property Map with key type the same as the vertex descriptor of the graph and a value type that is some unsigned integer type. diff --git a/doc/planar_canonical_ordering.html b/doc/planar_canonical_ordering.html index 046a1ff8..c5311d17 100644 --- a/doc/planar_canonical_ordering.html +++ b/doc/planar_canonical_ordering.html @@ -101,7 +101,7 @@ will be written to this iterator. IN: VertexIndexMap vm
      -A Readable Property Map +A Readable Property Map that maps vertices from g to distinct integers in the range [0, num_vertices(g) )
      Default: get(vertex_index,g)
      diff --git a/doc/planar_face_traversal.html b/doc/planar_face_traversal.html index eeb20e71..684e30d8 100644 --- a/doc/planar_face_traversal.html +++ b/doc/planar_face_traversal.html @@ -173,7 +173,7 @@ A model of PlanarFaceVisitor. IN: EdgeIndexMap vm
      -A Readable Property Map +A Readable Property Map that maps edges from g to distinct integers in the range [0, num_edges(g) )
      Default: get(edge_index,g)
      diff --git a/doc/planar_graphs.html b/doc/planar_graphs.html index e2a54733..db56c0e3 100644 --- a/doc/planar_graphs.html +++ b/doc/planar_graphs.html @@ -119,7 +119,7 @@ In the Boost Graph Library, a planar embedding is a model of the models PlanarEmbedding can be passed into the planarity test and populated if the input graph is planar. All other "back end" planar graph algorithms accept this populated PlanarEmbedding as an input. Conceptually, a type that models -PlanarEmbedding is a property +PlanarEmbedding is a property map that maps each vertex to a sequence of edges, where the sequence of edges has a similar interface to a standard C++ container. The sequence of edges each vertex maps to represents the ordering diff --git a/doc/predecessor_recorder.html b/doc/predecessor_recorder.html index 285de2f6..74ac53b5 100644 --- a/doc/predecessor_recorder.html +++ b/doc/predecessor_recorder.html @@ -74,7 +74,7 @@ See the example for bfs_visitor. PredecessorMap A WritablePropertyMap, +href="../../property_map/doc/WritablePropertyMap.html">WritablePropertyMap, where the key type and the value type are the vertex descriptor type of the graph. diff --git a/doc/prim_minimum_spanning_tree.html b/doc/prim_minimum_spanning_tree.html index 7076cc37..e6be7b2e 100644 --- a/doc/prim_minimum_spanning_tree.html +++ b/doc/prim_minimum_spanning_tree.html @@ -144,7 +144,7 @@ OUT: PredecessorMap p_map tree. If p[u] = u then u is either the root of the tree or is a vertex that is not reachable from the root. The PredecessorMap type must be a Read/Write + href="../../property_map/doc/ReadWritePropertyMap.html">Read/Write Property Map with key and vertex types the same as the vertex descriptor type of the graph.
      @@ -165,7 +165,7 @@ IN: weight_map(WeightMap w_map)
      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 + 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.
      @@ -180,7 +180,7 @@ IN: vertex_index_map(VertexIndexMap i_map) num_vertices(g)). This is necessary for efficient updates of the heap data structure when an edge is relaxed. The type VertexIndexMap must be a model of - Readable Property Map. The value type of the map must be an + Readable Property Map. The value type of the map must be an integer type. The vertex descriptor type of the graph needs to be usable as the key type of the map.
      Default: get(vertex_index, g) @@ -199,13 +199,13 @@ UTIL/OUT: distance_map(DistanceMap d_map) shortest path weight is the sum of the edge weights along the shortest path. The type DistanceMap must be a model of Read/Write + href="../../property_map/doc/ReadWritePropertyMap.html">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.
      - Default: + 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 @@ -222,12 +222,12 @@ UTIL/OUT: color_map(ColorMap c_map) from the queue. At the end of the algorithm, vertices reachable from the source vertex will have been colored black. All other vertices will still be white. The type ColorMap must be a model of - Read/Write + Read/Write Property Map. A vertex descriptor must be usable as the key type of the map, and the value type of the map must be a model of Color Value.
      Default: an + href="../../property_map/doc/iterator_property_map.html"> iterator_property_map created from a std::vector of default_color_type of size num_vertices(g) and using the i_map for the index map.
      diff --git a/doc/property_map.html b/doc/property_map.html index 47f4001d..80571e77 100644 --- a/doc/property_map.html +++ b/doc/property_map.html @@ -24,7 +24,7 @@ property_map<PropertyGraph, property map object +href="../../property_map/doc/property_map.html">property map object for a particular graph type. The property is specified by the PropertyTag template parameter. Graph classes must specialize this traits class to provide their own implementation @@ -53,7 +53,7 @@ for property maps. The (mutable) property map type for mapping vertex or edge desriptors of the graph to their associated property values, where the property is specified by PropertyTag. This type is a property map. +href="../../property_map/doc/property_map.html">property map. @@ -63,7 +63,7 @@ href="../../property_map/property_map.html">property map. The (non-mutable) property map type for mapping vertex or edge desriptors of the graph to their associated property values, where the property is specified by PropertyTag. This type is a property map. +href="../../property_map/doc/property_map.html">property map. diff --git a/doc/property_writer.html b/doc/property_writer.html index b7315fbb..33c36ae5 100644 --- a/doc/property_writer.html +++ b/doc/property_writer.html @@ -74,7 +74,7 @@ href="../example/dave.cpp">examples/dave.cpp. PropertyMap A ReadablePropertyMap, +href="../../property_map/doc/ReadablePropertyMap.html">ReadablePropertyMap, where the key_type is the vertex descriptor type or edge descriptor of the graph (depending on the kind of event tag), and the value_type of the property is convertible diff --git a/doc/push_relabel_max_flow.html b/doc/push_relabel_max_flow.html index c597cce0..3a53b482 100644 --- a/doc/push_relabel_max_flow.html +++ b/doc/push_relabel_max_flow.html @@ -108,7 +108,7 @@ IN: capacity_map(EdgeCapacityMap cap)
      The edge capacity property map. The type must be a model of a constant Lvalue Property Map. The + href="../../property_map/doc/LvaluePropertyMap.html">Lvalue Property Map. The key type of the map must be the graph's edge descriptor type.
      Default: get(edge_capacity, g)
      @@ -117,7 +117,7 @@ OUT: residual_capacity_map(ResidualCapacityEdgeMap res)
      The edge residual capacity property map. The type must be a model of a mutable Lvalue Property Map. The + href="../../property_map/doc/LvaluePropertyMap.html">Lvalue Property Map. The key type of the map must be the graph's edge descriptor type.
      Default: get(edge_residual_capacity, g)
      @@ -127,7 +127,7 @@ 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 + href="../../property_map/doc/LvaluePropertyMap.html">Lvalue Property Map. The key type of the map must be the graph's edge descriptor type.
      Default: get(edge_reverse, g)
      @@ -136,7 +136,7 @@ IN: vertex_index_map(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 + href="../../property_map/doc/LvaluePropertyMap.html">LvaluePropertyMap. 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 diff --git a/doc/quick_tour.html b/doc/quick_tour.html index bdd8759c..dc300d62 100644 --- a/doc/quick_tour.html +++ b/doc/quick_tour.html @@ -502,7 +502,7 @@ and use of the predecessor recorder. Since we will be using the Dijkstra Visitor.

      The functionality of the record_predecessors visitor is separated into two parts. For the storage and access of the predecessor property, we will -use a property map. The +use a property map. The predecessor visitor will then only be responsible for what parent to record. To implement this, we create a record_predecessors class and template it on the predecessor property map PredecessorMap. Since this visitor will diff --git a/doc/r_c_shortest_paths.html b/doc/r_c_shortest_paths.html index 7b110b1a..f17c744f 100755 --- a/doc/r_c_shortest_paths.html +++ b/doc/r_c_shortest_paths.html @@ -420,11 +420,11 @@ The graph object on which the algorithm is applied. The type Graph must

      IN: const VertexIndexMap& vertex_index_map
      -A ReadablePropertyMap mapping vertex descriptors to integers in [0, num_vertices(g)). +A ReadablePropertyMap mapping vertex descriptors to integers in [0, num_vertices(g)).
      IN: const EdgeIndexMap& edge_index_map
      -A ReadablePropertyMap mapping edge descriptors to integers in [0, num_edges(g)). +A ReadablePropertyMap mapping edge descriptors to integers in [0, num_edges(g)).
      IN: typename graph_traits<Graph>::vertex_descriptor s
      diff --git a/doc/random_layout.html b/doc/random_layout.html index c9cf2e77..667d8d01 100644 --- a/doc/random_layout.html +++ b/doc/random_layout.html @@ -51,7 +51,7 @@ IN/OUT: PositionMap position
      The property map that stores the position of each vertex. The type PositionMap must be a model of Lvalue Property + href="../../property_map/doc/LvaluePropertyMap.html">Lvalue Property Map such that the vertex descriptor type of Graph is convertible to its key type. Its value type must be a structure with fields x and y, representing the coordinates of diff --git a/doc/read_dimacs.html b/doc/read_dimacs.html index 1410b3f8..50f01358 100644 --- a/doc/read_dimacs.html +++ b/doc/read_dimacs.html @@ -73,12 +73,12 @@ file an additional reverse_edge is added and set in the reverse_edge map. Source OUT: CapacityMap capacity
      - A property map that models mutable Lvalue Property Map whose key type is the edge descriptor of the graph.
      + A property map that models mutable Lvalue Property Map whose key type is the edge descriptor of the graph.
      OUT: ReverseEdgeMap reverse_edge
      - A property map that models mutable Lvalue Property Map whose key and value type is the edge descriptor of the graph. This map stores the corresponding reverse edge for each each in Graph g.
      + A property map that models mutable Lvalue Property Map whose key and value type is the edge descriptor of the graph. This map stores the corresponding reverse edge for each each in Graph g.
      IN: std::istream& in diff --git a/doc/sequential_vertex_coloring.html b/doc/sequential_vertex_coloring.html index bd866e17..e0298627 100644 --- a/doc/sequential_vertex_coloring.html +++ b/doc/sequential_vertex_coloring.html @@ -57,7 +57,7 @@ OUT: ColorMap color
      This property map records the colors of each vertex. It must be a model of - Writeable + Writeable Property Map whose key type is the same as the vertex descriptor type of the graph and whose value type is an integral type that can store all values of the graph's vertices_size_type.
      diff --git a/doc/stanford_graph.html b/doc/stanford_graph.html index f040163b..b6ea21f9 100644 --- a/doc/stanford_graph.html +++ b/doc/stanford_graph.html @@ -384,7 +384,7 @@ the described below. The SGB Vertex and Arc structures provide "utility" fields for storing extra information. We provide BGL wrappers that provide access to these fields through property maps. In +href="../../property_map/doc/property_map.html">property maps. In addition, vertex index and edge length maps are provided. A property map object can be obtained from a SGB Graph* using the get() function described in the util union declared in the SGB header gb_graph.h, which are Vertex*, Arc*, Graph*, char*, and long. The property maps for the utility fields are models of Lvalue Property +href="../../property_map/doc/LvaluePropertyMap.html">Lvalue Property Map.

      The property map for vertex indices can be obtained using the vertex_index_t tag, and this property map is a Readable Property +href="../../property_map/doc/ReadablePropertyMap.html">Readable Property Map. A property map for edge length's can be obtained using the edge_length_t tag, and this property map is a Lvalue Property +href="../../property_map/doc/LvaluePropertyMap.html">Lvalue Property Map whose value type is long.

      diff --git a/doc/straight_line_drawing.html b/doc/straight_line_drawing.html index 4c4f2424..a00d35e8 100644 --- a/doc/straight_line_drawing.html +++ b/doc/straight_line_drawing.html @@ -95,7 +95,7 @@ href="VertexListGraph.html">Vertex List Graph IN PlanarEmbedding embedding
      -A Readable Property Map +A Readable Property Map that models the PlanarEmbedding concept.
      @@ -110,7 +110,7 @@ A ForwardIterator that has value_type equal to OUT: PositionMap
      -A Writable LValue Property +A Writable LValue Property Map that models the Position Map concept. The Position Map concept requires that the value mapped to be an object that has members x and y. For example, if p models PositionMap and v @@ -122,7 +122,7 @@ convertable to std::size_t. IN: VertexIndexMap vm
      -A Readable Property Map +A Readable Property Map that maps vertices from g to distinct integers in the range [0, num_vertices(g) )
      Default: get(vertex_index,g)
      diff --git a/doc/strong_components.html b/doc/strong_components.html index f6d94977..dada464b 100644 --- a/doc/strong_components.html +++ b/doc/strong_components.html @@ -83,7 +83,7 @@ and assigning each component an integer label. The algorithm then records which component each vertex in the graph belongs to by recording the component number in the component property map. The ComponentMap type must be a model of Writable Property +href="../../property_map/doc/WritablePropertyMap.html">Writable Property Map. The value type shouch be an integer type, preferably the same as the vertices_size_type of the graph. The key type must be the graph's vertex descriptor type.
      @@ -102,12 +102,12 @@ UTIL: root_map(RootMap r_map) for each component and get(r_map, v) returns the root vertex for whichever component vertex v is a member. The RootMap must be a + href="../../property_map/doc/ReadWritePropertyMap.html"> Read/Write Property Map, where the key type and the value type are the vertex descriptor type of the graph.
      Default: an + href="../../property_map/doc/iterator_property_map.html"> iterator_property_map created from a std::vector of vertex descriptors of size num_vertices(g) and using the i_map for the index @@ -119,11 +119,11 @@ UTIL: discover_time_map(TimeMap t_map)
      This is used by the algorithm to keep track of the DFS ordering of the vertices. The TimeMap must be a model - of Read/Write + of Read/Write Property Map and its value type must be an integer type. The key type must be the vertex descriptor type of the graph.
      Default:an + href="../../property_map/doc/iterator_property_map.html"> iterator_property_map created from a std::vector of integers with size num_vertices(g) and using the i_map for the index @@ -135,12 +135,12 @@ UTIL: color_map(ColorMap c_map)
      This is used by the algorithm to keep track of its progress through the graph. The type ColorMap must be a model of Read/Write + href="../../property_map/doc/ReadWritePropertyMap.html">Read/Write Property Map and its key type must be the graph's vertex descriptor type and the value type of the color map must model ColorValue.
      Default: an + href="../../property_map/doc/iterator_property_map.html"> iterator_property_map created from a std::vector of default_color_type of size num_vertices(g) and using the i_map for the index @@ -154,7 +154,7 @@ IN: vertex_index_map(VertexIndexMap i_map) num_vertices(g)). This parameter is only necessary when a default is used for one of the other named parameters. The type VertexIndexMap must be a model of Readable Property + href="../../property_map/doc/ReadablePropertyMap.html">Readable Property Map. The value type of the map must be an integer type. The vertex descriptor type of the graph needs to be usable as the key type of the map.
      diff --git a/doc/table_of_contents.html b/doc/table_of_contents.html index 9d6bc333..2e2c9fff 100644 --- a/doc/table_of_contents.html +++ b/doc/table_of_contents.html @@ -62,7 +62,7 @@
    12. Property Graph
    13. Mutable Property Graph
    -
  • The Property Map Library (technically not part of the graph library, but used a lot here) +
  • The Property Map Library (technically not part of the graph library, but used a lot here)
  • (Python)Python bindings
  • Visitor Concepts
      diff --git a/doc/time_stamper.html b/doc/time_stamper.html index 057b781d..338719fc 100644 --- a/doc/time_stamper.html +++ b/doc/time_stamper.html @@ -74,7 +74,7 @@ The following example shows the usage of the time_stamper. TimeMap A WritablePropertyMap, +href="../../property_map/doc/WritablePropertyMap.html">WritablePropertyMap, where the key_type is the vertex descriptor type or edge descriptor of the graph (depending on the kind of event tag), and where the TimeT type is convertible to the diff --git a/doc/topological_sort.html b/doc/topological_sort.html index e5f5448d..7ec5b145 100644 --- a/doc/topological_sort.html +++ b/doc/topological_sort.html @@ -72,12 +72,12 @@ UTIL/OUT: color_map(ColorMap color)
      This is used by the algorithm to keep track of its progress through the graph. The type ColorMap must be a model of Read/Write + href="../../property_map/doc/ReadWritePropertyMap.html">Read/Write Property Map and its key type must be the graph's vertex descriptor type and the value type of the color map must model ColorValue.
      Default: an + href="../../property_map/doc/iterator_property_map.html"> iterator_property_map created from a std::vector of default_color_type of size num_vertices(g) and using the i_map for the index @@ -93,7 +93,7 @@ IN: vertex_index_map(VertexIndexMap i_map) num_vertices(g)). This parameter is only necessary when the default color property map is used. The type VertexIndexMap must be a model of Readable Property + href="../../property_map/doc/ReadablePropertyMap.html">Readable Property Map. The value type of the map must be an integer type. The vertex descriptor type of the graph needs to be usable as the key type of the map.
      diff --git a/doc/transitive_closure.html b/doc/transitive_closure.html index 2cc98c69..809913a9 100644 --- a/doc/transitive_closure.html +++ b/doc/transitive_closure.html @@ -88,7 +88,7 @@ IN: vertex_index_map(VertexIndexMap& index_map) num_vertices(g)). This parameter is only necessary when the default color property map is used. The type VertexIndexMap must be a model of Readable Property + href="../../property_map/doc/ReadablePropertyMap.html">Readable Property Map. The value type of the map must be an integer type. The vertex descriptor type of the graph needs to be usable as the key type of the map.
      diff --git a/doc/transpose_graph.html b/doc/transpose_graph.html index 3e3378eb..908d8409 100644 --- a/doc/transpose_graph.html +++ b/doc/transpose_graph.html @@ -84,7 +84,7 @@ map from the graph. IN: vertex_index_map(VertexIndexMap i_map)
      The vertex index map type must be a model of Readable Property +href="../../property_map/doc/ReadablePropertyMap.html">Readable Property Map and must map the vertex descriptors of G to the integers from 0 to num_vertices(G).
      @@ -101,7 +101,7 @@ UTIL/OUT: orig_to_copy(Orig2CopyMap c) This maps vertices in the original graph to vertices in the copy. Default: an + href="../../property_map/doc/iterator_property_map.html"> iterator_property_map created from a std::vector of the output graph's vertex descriptor type of size num_vertices(g) and using the i_map for the index diff --git a/doc/tsp_tour_len_visitor.html b/doc/tsp_tour_len_visitor.html index d972e9d3..389156a1 100644 --- a/doc/tsp_tour_len_visitor.html +++ b/doc/tsp_tour_len_visitor.html @@ -57,7 +57,7 @@ The graph type The weight of each edge in the graph. The type WeightMap must be a model of -Readable Property Map. +Readable Property Map. The edge descriptor type of the graph needs to be usable as the key type for the weight map. None diff --git a/doc/undirected_dfs.html b/doc/undirected_dfs.html index b8beefa8..9ac0bc4f 100644 --- a/doc/undirected_dfs.html +++ b/doc/undirected_dfs.html @@ -198,12 +198,12 @@ UTIL/OUT: vertex_color_map(VertexColorMap vertex_color)
      This is used by the algorithm to keep track of its progress through the graph. The type VertexColorMap must be a model of Read/Write + href="../../property_map/doc/ReadWritePropertyMap.html">Read/Write Property Map and its key type must be the graph's vertex descriptor type and the value type of the color map must model ColorValue.
      Default: an + href="../../property_map/doc/iterator_property_map.html"> iterator_property_map created from a std::vector of default_color_type of size num_vertices(g) and using the i_map for the index @@ -217,7 +217,7 @@ UTIL: edge_color_map(EdgeColorMap edge_color)
      This is used by the algorithm to keep track of which edges have been visited. The type EdgeColorMap must be a model of Read/Write + href="../../property_map/doc/ReadWritePropertyMap.html">Read/Write Property Map and its key type must be the graph's edge descriptor type and the value type of the color map must model ColorValue.
      @@ -242,7 +242,7 @@ IN: vertex_index_map(VertexIndexMap i_map) num_vertices(g)). This parameter is only necessary when the default color property map is used. The type VertexIndexMap must be a model of Readable Property + href="../../property_map/doc/ReadablePropertyMap.html">Readable Property Map. The value type of the map must be an integer type. The vertex descriptor type of the graph needs to be usable as the key type of the map.
      diff --git a/doc/using_property_maps.html b/doc/using_property_maps.html index 38a342cc..5a83f555 100644 --- a/doc/using_property_maps.html +++ b/doc/using_property_maps.html @@ -29,7 +29,7 @@ properties to graph in terms of data-structure implementation, but graph algorithms should not have to deal with the implementation details of the properties. The property map interface defined in Section Property +HREF="../../property_map/doc/property_map.html">Property Map Concepts provides a generic method for accessing properties from graphs. This is the interface used in the BGL algorithms to access properties. diff --git a/doc/write-graphviz.html b/doc/write-graphviz.html index 52f4010a..db6d0eae 100644 --- a/doc/write-graphviz.html +++ b/doc/write-graphviz.html @@ -221,7 +221,7 @@ IN: const std::string& node_id 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).
      + 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.

      diff --git a/doc/write_dimacs.html b/doc/write_dimacs.html index 636177f0..e362876d 100644 --- a/doc/write_dimacs.html +++ b/doc/write_dimacs.html @@ -76,12 +76,12 @@ The output can be read in again using the Readable Property Map whose key type is the edge descriptor of the graph and whose value type can be written to a stream.
      + A property map that models Readable Property Map whose key type is the edge descriptor of the graph and whose value type can be written to a stream.

      IN: IndexMap epw
      - 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.
      + 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.
      OUT: std::ostream& out From ee35a986a748d0730b28650b0b4f9716afadeec8 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Sun, 31 May 2009 04:20:52 +0000 Subject: [PATCH 219/224] Changed new-style named parameter code for BGL to use shared_array_property_map, greatly simplifying interface [SVN r53481] --- include/boost/graph/depth_first_search.hpp | 3 +- include/boost/graph/named_function_params.hpp | 46 +++++++------------ 2 files changed, 17 insertions(+), 32 deletions(-) diff --git a/include/boost/graph/depth_first_search.hpp b/include/boost/graph/depth_first_search.hpp index 5e2ba34c..ebfc16c7 100644 --- a/include/boost/graph/depth_first_search.hpp +++ b/include/boost/graph/depth_first_search.hpp @@ -289,11 +289,10 @@ namespace boost { using namespace boost::graph::keywords; typedef bgl_named_params params_type; BOOST_GRAPH_DECLARE_CONVERTED_PARAMETERS(params_type, params) - BOOST_GRAPH_MAKE_COLOR_MAP_IF_NEEDED(VertexListGraph, arg_pack_type, g, arg_pack, color_map); depth_first_search (g, arg_pack[_visitor | make_dfs_visitor(null_visitor())], - color_map, + boost::detail::color_map_maker::make_map(g, arg_pack), arg_pack[_root_vertex | *vertices(g).first] ); } diff --git a/include/boost/graph/named_function_params.hpp b/include/boost/graph/named_function_params.hpp index b8f29700..d42b40eb 100644 --- a/include/boost/graph/named_function_params.hpp +++ b/include/boost/graph/named_function_params.hpp @@ -18,6 +18,8 @@ #include #include #include +#include +#include namespace boost { @@ -436,15 +438,9 @@ BOOST_BGL_DECLARE_NAMED_PARAMS template struct color_map_maker_helper { - typedef int data_type; typedef PM map_type; - typedef std::pair pm_pair_type; - static void make_pm_pair(const Graph&, - Value, - const PM& pm, - const ArgPack&, - pm_pair_type& result) { - result.second = pm; + static PM make_map(const Graph&, Value, const PM& pm, const ArgPack&) { + return pm; } }; @@ -459,24 +455,20 @@ BOOST_BGL_DECLARE_NAMED_PARAMS boost::detail::parameter_exists< ArgPack, boost::graph::keywords::tag::vertex_index_map>::value >::result_type>::type vi_map_type; - typedef std::vector data_type; typedef - boost::iterator_property_map + boost::shared_array_property_map map_type; - typedef std::pair pm_pair_type; - static void make_pm_pair(const Graph& g, + static map_type make_map(const Graph& g, Value v, const PM&, - const ArgPack& ap, - pm_pair_type& result) { - result.first.clear(); - result.first.resize(num_vertices(g), v); - result.second = map_type( - result.first.begin(), - override_const_property( - ap, - boost::graph::keywords::_vertex_index_map, - g, vertex_index)); + const ArgPack& ap) { + return make_shared_array_property_map( + num_vertices(g), + v, + override_const_property( + ap, + boost::graph::keywords::_vertex_index_map, + g, vertex_index)); } }; @@ -496,17 +488,11 @@ BOOST_BGL_DECLARE_NAMED_PARAMS >::type >::type> helper; typedef typename helper::map_type map_type; - typedef typename helper::pm_pair_type pm_pair_type; - static void make_pm_pair(const Graph& g, const ArgPack& ap, pm_pair_type& result) { - helper::make_pm_pair(g, white_color, ap[boost::graph::keywords::_color_map | 0], ap, result); + static map_type make_map(const Graph& g, const ArgPack& ap) { + return helper::make_map(g, white_color, ap[boost::graph::keywords::_color_map | 0], ap); } }; -#define BOOST_GRAPH_MAKE_COLOR_MAP_IF_NEEDED(GraphT, ArgPackT, graph, arg_pack, color_map) \ - typename boost::detail::color_map_maker::pm_pair_type BOOST_PP_CAT(cm_pair_, __LINE__); \ - boost::detail::color_map_maker::make_pm_pair(graph, arg_pack, BOOST_PP_CAT(cm_pair_, __LINE__)); \ - typename boost::detail::color_map_maker::map_type& color_map = BOOST_PP_CAT(cm_pair_, __LINE__).second; - } } // namespace boost From 3d07d486b204c015fecb44cc9c2660e425fb0a5f Mon Sep 17 00:00:00 2001 From: Andrew Sutton Date: Mon, 1 Jun 2009 21:44:35 +0000 Subject: [PATCH 220/224] Re-added the exterior property labeling framework under a different name [SVN r53556] --- .../detail/hashed_property_container.hpp | 108 ++++++++++ .../detail/indexed_property_container.hpp | 102 ++++++++++ include/boost/graph/shared_properties.hpp | 192 ++++++++++++++++++ 3 files changed, 402 insertions(+) create mode 100644 include/boost/graph/detail/hashed_property_container.hpp create mode 100644 include/boost/graph/detail/indexed_property_container.hpp create mode 100644 include/boost/graph/shared_properties.hpp diff --git a/include/boost/graph/detail/hashed_property_container.hpp b/include/boost/graph/detail/hashed_property_container.hpp new file mode 100644 index 00000000..80705a81 --- /dev/null +++ b/include/boost/graph/detail/hashed_property_container.hpp @@ -0,0 +1,108 @@ +// (C) Copyright Andrew Sutton 2008-2009 +// 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_HASHED_PROPERTIES_HPP +#define BOOST_GRAPH_DETAIL_HASHED_PROPERTIES_HPP + +#include +#include +#include + +namespace boost { namespace graph_detail { + +/** + * Wrap an iterator with a default value so that it generates default values + * over a range of keys. + */ +template +struct key_value_iterator +{ + typedef typename std::forward_iterator_tag iterator_category; + typedef typename std::size_t difference_type; + + typedef std::pair value_type; + typedef value_type reference; + typedef value_type pointer; + + key_value_iterator(Iter i, Prop const& p) + : iter(i), value(p) + { } + + key_value_iterator& operator++() + { ++iter; return *this; } + + reference operator*() + { return make_pair(*iter, value); } + + bool operator==(key_value_iterator const& x) const + { return iter == x.iter; } + + bool operator!=(key_value_iterator const& x) const + { return iter != x.iter; } + + Iter iter; + Prop value; +}; + +template +inline key_value_iterator +make_key_value_iterator(Iter i, Prop const& x) +{ return key_value_iterator(i, x); } + +/** + * A simple wrapper around an unordered map, this is used to map descriptors + * to arbitrary property values. Note that the property type must be default + * constructible. + * + * This may seem a little odd because we're passing an iterator and not the key + * type. However, the key type is always the iterator's value type. + */ +template +class hashed_property_container +{ +public: + typedef Property value_type; + typedef Descriptor key_type; + typedef std::tr1::unordered_map> container_type; + + /** + * Construct the hashtable over n buckets. This may not actually allocate + * n buckets, so we can't necessarily guarantee that memory will actually + * be allocated for each element, much less what those default values would + * actually be. + */ + hashed_property_container(std::size_t n) + : data(n) + { } + + /** + * Construct the hashtable over the keys in the iterator range [f, l) with + * the default value x. + */ + template + hashed_property_container(Iter f, Iter l, value_type const& x) + : data(detail::make_key_value_iterator(f, x), + detail::make_key_value_iterator(l, value_type())) + { } + + template + hashed_property_container(Range rng, value_type const& x) + : data(detail::make_key_value_iterator(rng.first, x), + detail::make_key_value_iterator(rng.second, value_type())) + { } + + inline value_type& operator[](key_type const& k) + { return data[k]; } + + inline value_type const& operator[](key_type const& k) const + { return data[k]; } + + container_type data; +}; + +} } // namespace boost::graph_detail + + +#endif diff --git a/include/boost/graph/detail/indexed_property_container.hpp b/include/boost/graph/detail/indexed_property_container.hpp new file mode 100644 index 00000000..3b41b48e --- /dev/null +++ b/include/boost/graph/detail/indexed_property_container.hpp @@ -0,0 +1,102 @@ +// (C) Copyright Andrew Sutton 2008-2009 +// 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_INDEXED_PROPERTIES_HPP +#define BOOST_GRAPH_DETAIL_INDEXED_PROPERTIES_HPP + +#include +#include + +namespace boost { namespace graph_detail { + +/** + * Wrap an iterator with a default value so that it generates default values + * over a range of keys. This maintains the defalt value as an object to + * prevent multiple constructions if the object is "heavy". + */ +template +struct default_value_iterator + : iterator_facade< + default_value_iterator, Prop, std::forward_iterator_tag, + Prop const& + > +{ + typedef typename std::forward_iterator_tag iterator_category; + typedef std::size_t difference_type; + + typedef Prop value_type; + typedef value_type const& reference; + typedef value_type const* pointer; + + default_value_iterator(Iter i, Prop const& p) + : iter(i), value(p) + { } + + void advance() + { ++iter; } + + bool equal(default_value_iterator const& x) const + { return iter == x.iter; } + + Prop const& dereference() const + { return value; } + + Iter iter; + Prop value; +}; + +template +inline default_value_iterator +make_default_value_iterator(Iter i, Prop const& p) +{ return default_value_iterator(i, p); } + +/** + * A simple wrapper around a vector. Because the "key" to this vector is + * actually given as a descriptor, we have to get the underlying index that + * allows us to map this value to a property. + * + * @todo If the underlying container is shared, then this can act as both + * the property map and the container. Or we could have the property map + * be a shared_ptr to this (or other) containers. + */ +template +struct indexed_property_container +{ + typedef Property value_type; + typedef Descriptor key_type; + typedef std::vector container_type; + + inline indexed_property_container(std::size_t n) + : data(n) + { } + + /** + * Construct the hashtable over the keys in the iterator range [f, l) with + * the default value x. + */ + template + inline indexed_property_container(Iter f, Iter l, value_type const& x) + : data(detail::make_default_value_iterator(f, x), + detail::make_default_value_iterator(l, value_type())) + { } + + template + inline indexed_property_container(Range rng, value_type const& x) + : data(detail::make_default_value_iterator(rng.first, x), + detail::make_default_value_iterator(rng.second, value_type())) + { } + + inline value_type& operator[](key_type const& k) + { return data[k.value]; } + + inline value_type const& operator[](key_type const& k) const + { return data[k.value]; } + + container_type data; +}; + +} } // namespace boost::graph_detail + +#endif diff --git a/include/boost/graph/shared_properties.hpp b/include/boost/graph/shared_properties.hpp new file mode 100644 index 00000000..07f59f29 --- /dev/null +++ b/include/boost/graph/shared_properties.hpp @@ -0,0 +1,192 @@ +// (C) Copyright Andrew Sutton 2008-2009 +// 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_SHARED_PROPERTIES_HPP +#define BOOST_GRAPH_SHARED_PROPERTIES_HPP + +#include + +#include +#include + +namespace boost { +namespace graph_detail { + // Define the mapping strategy based on the type of descriptor. By default, + // we prefer to use hashing since the number of data structures that + // actually index their vertices is tiny. + struct index_mapping { }; + struct hash_mapping { }; + + /** @internal @name Descriptor Mapping */ + //@{ + template + struct descriptor_mapping + { typedef hash_mapping strategy; }; + + // If the descriptor is an unsigned int, then we can use a vector. + template <> + struct descriptor_mapping + { typedef index_mapping strategy; }; + //@} + + // Select the type of container based on the underlying store selector. + // Noe that these have to wrap the underlying containers so that a common + // interface exists between the two. + template + struct choose_container + : typename mpl::if_< + is_same< + typename descriptor_mapping::strategy, hash_mapping + >, + hashed_property_container, + indexed_property_container + >::type type; + { }; + + /** @internal @name Get Range + * Return a range over the set of vertices or edges. Note that this is + * going to be truly problematic if is_same. + */ + template + inline typename Graph::vertex_range + get_range(Graph const& g, typename Graph::vertex_descriptor) + { return g.vertices(); } + + template + inline typename Graph::edge_range + get_range(Graph const& g, typename Graph::edge_descriptor) + { return g.edges(); } +} // namespace graph_detail + +// TODO: Work in progress. + +/** + * The label type allows the definition of exterior properties that + * can maintain either their own internal store (via shared pointers) or be + * constructed over an exterioir store. This is useful in algorithms that + * can provide default exterior properties or allow the user to provide their + * own. + * + * The use of this type incurs a slight overhead due to an additional level of + * indirection. + */ +template +struct label { + // Select the container and map type for the self-wrapping property. + typedef typename detail::choose_container< + Descriptor, Label + >::type Container; + + typedef typename Label value_type; + typedef typename Label& reference; + typedef typename Descriptor key_type; + + // By default, the optional property contains no property. This should + // probably never be used. + label() + : data() + { } + + // Allocate a label and build a property map over it. + label(Graph const& g, value_type const& x = value_type()) + : container(new Container(detail::get_range(g, Descriptor()), x)) + { } + + // Construct the optional property over the given map, without allocating + // an exterior label. + label(Container& cont) + : container(&cont) + { } + + value_type& operator()(key_type const& key) + { return map(key); } + + void operator()(key_type const& key, value_type const& value) const + { return map(key, value); } + + optional_label& swap(optional_label& x) { + using std::swap; + swap(container, x.container); // Should overload to constant time op. + swap(map, x.map); + return *this; + } + + shared_ptr data; +}; + +/** + * The optional vertex map allows a user-provided property map or a self- + * contained exterior property to be passed to a generic function. The user + * provided property map is not required to be constructed over an exterior + * property. + */ +template +struct vertex_label + : label +{ + typedef label Base; + typedef typename Base::Container Container; + + vertex_label() : Base() { } + vertex_label(Graph const& g, Label const& x = Label()) : Base(g, x) { } + vertex_label(Container& cont) : Base(cost) { } +}; + +/** + * The optional edge map allows a user-provided property map or a self- + * contained exterior property to be passed to a generic function. The user + * provided property map is not required to be constructed over an exterior + * property. + */ +template +struct edge_label + : label +{ + typedef label base_type; + typedef typename Base::Container Container; + + edge_label() : Base() { } + edge_label(Graph const& g, Label const& x = Label()) : Base(g, x) { } + edge_label(Container& cont) : Base(cont) { } +}; + +namespace detail +{ + // Optionally initialize the container, but not if the map is already + // initialized. + template + void optional_init(Graph const& g, Map& map, typename Map::value_type x) + { + if(!map.data) { + Map tmp(g, x); + map.swap(tmp); + } + } +} + +/** @name Initialize Property Map + * Delayed initialization of optional property maps. The default solution + * is to do nothing (i.e,. the map is already initialized). Specialized + * variants simply swap the given map with one that's actually initialized. + */ +//@{ +/* +template +void initialize(Graph const&, Map&, typename Map::value_type) +{ throw 0; } +*/ + +template +void initialize(Graph const& g, optional_vertex_label& map, Label const& x) +{ detail::optional_init(g, map, x); } + +template +void initialize(Graph const g, optional_edge_label& map, Label const& x) +{ detail::optional_init(g, map, x); } +//@} + +} // namespace boost + +#endif From 77b148e6db4cc79420f77a95d1b8d37e6274f537 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Fri, 5 Jun 2009 01:47:37 +0000 Subject: [PATCH 221/224] Applied patches from ticket #900; fixes #900 [SVN r53650] --- doc/read_graphml.html | 137 +++++++++++------------ doc/read_graphml.rst | 47 ++++---- doc/write_graphml.html | 100 ++++++++--------- doc/write_graphml.rst | 17 ++- include/boost/graph/graphml.hpp | 3 +- src/graphml.cpp | 192 +++++++++++++++++--------------- 6 files changed, 250 insertions(+), 246 deletions(-) diff --git a/doc/read_graphml.html b/doc/read_graphml.html index 188f3266..1d5c7f3c 100644 --- a/doc/read_graphml.html +++ b/doc/read_graphml.html @@ -1,72 +1,70 @@ - - - + Boost read_graphml - + -

      Boost read_graphml

      +

      Boost read_graphml

      + +
       void read_graphml(std::istream& in, MutableGraph& graph,
                         dynamic_properties& dp);
       
      -

      The read_graphml function interprets a graph described using the -graphml format and builds a BGL graph that captures that +

      The read_graphml function interprets a graph described using the +GraphML format and builds a BGL graph that captures that description. Using this function, you can initialize a graph using data stored as text.

      -

      The graphml format can specify both directed and undirected graphs, and -read_graphml differentiates between the two. One must pass -read_graphml an undirected graph when reading an undirected graph; -the same is true for directed graphs. Furthermore, read_graphml +

      The GraphML format can specify both directed and undirected graphs, and +read_graphml differentiates between the two. One must pass +read_graphml an undirected graph when reading an undirected graph; +the same is true for directed graphs. Furthermore, read_graphml will throw an exception if it encounters parallel edges and cannot add them to the graph.

      -

      To handle attributes expressed in the graphml format, read_graphml -takes a dynamic_properties object and operates on its collection of +

      To handle attributes expressed in the GraphML format, read_graphml +takes a dynamic_properties object and operates on its collection of property maps. The reader passes all the properties encountered to -this object, using the graphml attribute names as the property keys, -and with the appropriate C++ type based on the graphml attribute type -definition.

      -
      +this object, using the GraphML attribute names as the property names, +and with the appropriate C++ value type based on the GraphML attribute type +definition. Graph properties are also set with the same +dynamic_properties object, where the key type is the type of the graph itself.

      +
      Requirements:
      -

      Where Defined

      -

      <boost/graph/graphml.hpp>

      +

      Where Defined

      +

      <boost/graph/graphml.hpp>

      -

      Exceptions

      +

      Exceptions

       struct graph_exception : public std::exception {
         virtual ~graph_exception() throw();
      @@ -97,44 +95,46 @@ struct parse_error : public graph_exception {
         virtual ~parse_error() throw() {}
         virtual const char* what() const throw();
         std::string statement;
      +  std::string error;
       };
       
      -

      Under certain circumstances, read_graphml will throw one of the +

      Under certain circumstances, read_graphml will throw one of the above exceptions. The three concrete exceptions can all be caught -using the general graph_exception moniker when greater precision +using the general graph_exception moniker when greater precision is not needed. In addition, all of the above exceptions derive from -the standard std::exception for even more generalized error +the standard std::exception for even more generalized error handling.

      -

      The bad_parallel_edge exception is thrown when an attempt to add a -parallel edge to the supplied MutableGraph fails. The graphml format +

      The bad_parallel_edge exception is thrown when an attempt to add a +parallel edge to the supplied MutableGraph fails. The GraphML format supports parallel edges, but some BGL-compatible graph types do not. -One example of such a graph is boost::adjacency_list<setS,vecS>, +One example of such a graph is boost::adjacency_list<setS,vecS>, which allows at most one edge can between any two vertices.

      -

      The directed_graph_error exception occurs when an undirected graph -type is passed to read_graph but the textual representation of the -graph is directed, as indicated by the edgedefault="directed" -graph attribute in the graphml format.

      -

      The undirected_graph_error exception occurs when a directed graph -type is passed to read_graph but the textual representation of the -graph is undirected, as indicated by the edgedefault="undirected" -graph attribute in the graphml format.

      +

      The directed_graph_error exception occurs when an undirected graph +type is passed to read_graph, but the graph defined in the GraphML +file contains at least one directed edge.

      +

      The undirected_graph_error exception occurs when a directed graph +type is passed to read_graph, but the graph defined in the GraphML +file contains at least one undirected edge.

      +

      The parse_error exception occurs when a syntax error is +encountered in the GraphML file. The error string will contain the +line and column where the error was encountered.

      -

      Building the graphml reader

      -

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

      +

      Building the GraphML reader

      +

      To use the GraphML reader, 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.

      -

      Notes

      +

      Notes

      • On successful reading of a graph, every vertex and edge will have an associated value for every respective edge and vertex property encountered while interpreting the graph. These values will be set -using the dynamic_properties object. Some properties may be -put multiple times during the course of reading in order to -ensure the graphml semantics. Those edges and vertices that are +using the dynamic_properties object. Some properties may be +put multiple times during the course of reading in order to +ensure the GraphML semantics. Those edges and vertices that are not explicitly given a value for a property (and that property has no default) will be given the default constructed value of the value type. Be sure that property map value types are default @@ -150,22 +150,15 @@ graph.
      -
      -

      Future Work

      -
      -
        -
      • Better expat error detection.
      • -
      -
      +

      See Also

      +

      write_graphml

      - diff --git a/doc/read_graphml.rst b/doc/read_graphml.rst index 29fcdc94..c61156d8 100644 --- a/doc/read_graphml.rst +++ b/doc/read_graphml.rst @@ -23,23 +23,24 @@ __ ../../../index.htm The ``read_graphml`` function interprets a graph described using the -graphml_ format and builds a BGL graph that captures that +GraphML_ format and builds a BGL graph that captures that description. Using this function, you can initialize a graph using data stored as text. -The graphml format can specify both directed and undirected graphs, and +The GraphML format can specify both directed and undirected graphs, and ``read_graphml`` differentiates between the two. One must pass ``read_graphml`` an undirected graph when reading an undirected graph; the same is true for directed graphs. Furthermore, ``read_graphml`` will throw an exception if it encounters parallel edges and cannot add them to the graph. -To handle attributes expressed in the graphml format, ``read_graphml`` +To handle attributes expressed in the GraphML format, ``read_graphml`` takes a dynamic_properties_ object and operates on its collection of property maps. The reader passes all the properties encountered to -this object, using the graphml attribute names as the property keys, -and with the appropriate C++ type based on the graphml attribute type -definition. +this object, using the GraphML attribute names as the property names, +and with the appropriate C++ value type based on the GraphML attribute type +definition. Graph properties are also set with the same +dynamic_properties_ object, where the key type is the type of the graph itself. Requirements: - The type of the graph must model the `Mutable Graph`_ concept. @@ -88,6 +89,7 @@ Exceptions virtual ~parse_error() throw() {} virtual const char* what() const throw(); std::string statement; + std::string error; }; Under certain circumstances, ``read_graphml`` will throw one of the @@ -98,27 +100,29 @@ the standard ``std::exception`` for even more generalized error handling. The ``bad_parallel_edge`` exception is thrown when an attempt to add a -parallel edge to the supplied MutableGraph fails. The graphml format +parallel edge to the supplied MutableGraph fails. The GraphML format supports parallel edges, but some BGL-compatible graph types do not. One example of such a graph is ``boost::adjacency_list``, which allows at most one edge can between any two vertices. The ``directed_graph_error`` exception occurs when an undirected graph -type is passed to ``read_graph`` but the textual representation of the -graph is directed, as indicated by the ``edgedefault="directed"`` -graph attribute in the graphml format. +type is passed to ``read_graph``, but the graph defined in the GraphML +file contains at least one directed edge. The ``undirected_graph_error`` exception occurs when a directed graph -type is passed to ``read_graph`` but the textual representation of the -graph is undirected, as indicated by the ``edgedefault="undirected"`` -graph attribute in the graphml format. +type is passed to ``read_graph``, but the graph defined in the GraphML +file contains at least one undirected edge. + +The ``parse_error`` exception occurs when a syntax error is +encountered in the GraphML file. The error string will contain the +line and column where the error was encountered. -Building the graphml reader +Building the GraphML reader ----------------------------- -To use the graphml reader, you will need to build and link against -the "bgl-graphml" library. The library can be built by following the +To use the GraphML reader, 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``. @@ -130,7 +134,7 @@ Notes encountered while interpreting the graph. These values will be set using the ``dynamic_properties`` object. Some properties may be ``put`` multiple times during the course of reading in order to - ensure the graphml semantics. Those edges and vertices that are + ensure the GraphML semantics. Those edges and vertices that are not explicitly given a value for a property (and that property has no default) will be given the default constructed value of the value type. **Be sure that property map value types are default @@ -151,14 +155,7 @@ See Also write_graphml_ -Future Work ------------ - - - Better expat error detection. - - -.. _Graphml: http://graphml.graphdrawing.org/ - +.. _GraphML: http://graphml.graphdrawing.org/ .. _`Mutable Graph`: MutableGraph.html .. _`Multi-Pass Iterator`: ../../iterator/index.html .. _dynamic_properties: ../../property_map/doc/dynamic_property_map.html diff --git a/doc/write_graphml.html b/doc/write_graphml.html index 1dbd1863..7e98fcab 100644 --- a/doc/write_graphml.html +++ b/doc/write_graphml.html @@ -1,28 +1,27 @@ - - + Boost write_graphml - + -

      Boost write_graphml

      +

      Boost write_graphml

      + +
       template<typename Graph>
       void
      -write_graphml(std::ostream& out, const Graph& g, const dynamic_properties& dp, 
      +write_graphml(std::ostream& out, const Graph& g, const dynamic_properties& dp,
                     bool ordered_vertices=false);
       
       template<typename Graph, typename VertexIndexMap>
      @@ -31,53 +30,53 @@ write_graphml(std::ostream& out, const Graph& g, VertexIndexMap vertex_i
                     const dynamic_properties& dp, bool ordered_vertices=false);
       

      This is to write a BGL graph object into an output stream in the -graphml format. Both overloads of write_graphml will emit all of -the properties stored in the dynamic_properties object, thereby +GraphML format. Both overloads of write_graphml will emit all of +the properties stored in the dynamic_properties object, thereby retaining the properties that have been read in through the dual -function read_graphml. The second overload must be used when the +function read_graphml. The second overload must be used when the graph doesn't have an internal vertex index map, which must then be supplied with the appropriate parameter.

      -

      Where Defined

      -

      <boost/graph/graphml.hpp>

      +

      Where Defined

      +

      <boost/graph/graphml.hpp>

      -

      Parameters

      -
      -
      OUT: std::ostream& out
      -
      A standard std::ostream object.
      -
      IN: VertexListGraph& g
      +

      Parameters

      +
      +
      OUT: std::ostream& out
      +
      A standard std::ostream object.
      +
      IN: VertexListGraph& g
      A directed or undirected graph. The -graph's type must be a model of VertexListGraph. If the graph -doesn't have an internal vertex_index property map, one +graph's type must be a model of VertexListGraph. If the graph +doesn't have an internal vertex_index property map, one must be supplied with the vertex_index parameter.
      -
      IN: VertexIndexMap vertex_index
      +
      IN: VertexIndexMap vertex_index
      A vertex property map containing the indexes in the range [0,num_vertices(g)].
      -
      IN: dynamic_properties& dp
      -
      Contains all of the vertex and edge properties that should be -emitted by the graphml writer.
      -
      IN: bool ordered_vertices
      +
      IN: dynamic_properties& dp
      +
      Contains all of the vertex, edge, and graph properties that should be +emitted by the GraphML writer.
      +
      IN: bool ordered_vertices
      This tells whether or not the order of the vertices from vertices(g) -matches the order of the indexes. If true, the parse.nodeids -graph attribute will be set to canonical. Otherwise it will be -set to free.
      +matches the order of the indexes. If true, the parse.nodeids +graph attribute will be set to canonical. Otherwise it will be +set to free.
      -

      Example

      -

      This example demonstrates using BGL-graphml interface to write -a BGL graph into a graphml format file.

      +

      Example

      +

      This example demonstrates using BGL-GraphML interface to write +a BGL graph into a GraphML format file.

       enum files_e { dax_h, yow_h, boz_h, zow_h, foo_cpp,
                      foo_o, bar_cpp, bar_o, libfoobar_a,
      @@ -134,7 +133,7 @@ int main(int,char*[])
       

      The output will be:

       <?xml version="1.0" encoding="UTF-8"?>
      -<graphml xmlns="http://graphml.graphdrawing.org/xmlns/graphml" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://graphml.graphdrawing.org/xmlns/graphml http://graphml.graphdrawing.org/xmlns/graphml/graphml-attributes-1.0rc.xsd">
      +<graphml xmlns="http://graphml.graphdrawing.org/xmlns/graphml"  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://graphml.graphdrawing.org/xmlns/graphml http://graphml.graphdrawing.org/xmlns/graphml/graphml-attributes-1.0rc.xsd">
         <key id="key0" for="node" attr.name="name" attr.type="string" />
         <key id="key1" for="edge" attr.name="weight" attr.type="int" />
         <graph id="G" edgedefault="directed" parse.nodeids="canonical" parse.edgeids="canonical" parse.order="nodesfirst">
      @@ -245,23 +244,24 @@ int main(int,char*[])
       
      -

      See Also

      +

      See Also

      _read_graphml

      -

      Notes

      +

      Notes

        -
      • Note that you can use graphml file write facilities without linking -against the boost_graph library.
      • +
      • Note that you can use GraphML file write facilities without linking +against the boost_graph library.
      - diff --git a/doc/write_graphml.rst b/doc/write_graphml.rst index e01c79f7..00e68b7d 100644 --- a/doc/write_graphml.rst +++ b/doc/write_graphml.rst @@ -29,7 +29,7 @@ __ ../../../index.htm const dynamic_properties& dp, bool ordered_vertices=false); This is to write a BGL graph object into an output stream in the -graphml_ format. Both overloads of ``write_graphml`` will emit all of +GraphML_ format. Both overloads of ``write_graphml`` will emit all of the properties stored in the dynamic_properties_ object, thereby retaining the properties that have been read in through the dual function read_graphml_. The second overload must be used when the @@ -60,8 +60,8 @@ IN: ``VertexIndexMap vertex_index`` IN: ``dynamic_properties& dp`` - Contains all of the vertex and edge properties that should be - emitted by the graphml writer. + Contains all of the vertex, edge, and graph properties that should be + emitted by the GraphML writer. IN: ``bool ordered_vertices`` This tells whether or not the order of the vertices from vertices(g) @@ -74,8 +74,8 @@ IN: ``bool ordered_vertices`` Example ------- -This example demonstrates using BGL-graphml interface to write -a BGL graph into a graphml format file. +This example demonstrates using BGL-GraphML interface to write +a BGL graph into a GraphML format file. :: @@ -137,7 +137,7 @@ The output will be: :: - + @@ -254,11 +254,10 @@ _read_graphml Notes ----- - - Note that you can use graphml file write facilities without linking + - Note that you can use GraphML file write facilities without linking against the ``boost_graph`` library. -.. _graphml: http://graphml.graphdrawing.org/ - +.. _GraphML: http://graphml.graphdrawing.org/ .. _dynamic_properties: ../../property_map/doc/dynamic_property_map.html .. _read_graphml: read_graphml.html .. _VertexListGraph: VertexListGraph.html diff --git a/include/boost/graph/graphml.hpp b/include/boost/graph/graphml.hpp index 9e367d12..cb292ca4 100644 --- a/include/boost/graph/graphml.hpp +++ b/include/boost/graph/graphml.hpp @@ -34,10 +34,11 @@ namespace boost ///////////////////////////////////////////////////////////////////////////// struct parse_error: public graph_exception { - parse_error(const std::string& error) {statement = "parse error: " + error;} + parse_error(const std::string& err) {error = err; statement = "parse error: " + error;} virtual ~parse_error() throw() {} virtual const char* what() const throw() {return statement.c_str();} std::string statement; + std::string error; }; diff --git a/src/graphml.cpp b/src/graphml.cpp index b219103f..df1ec16b 100644 --- a/src/graphml.cpp +++ b/src/graphml.cpp @@ -12,7 +12,7 @@ #include #include #include -#include +#include using namespace boost; @@ -25,31 +25,29 @@ public: void run(std::istream& in) { const int buffer_size = 4096; - XML_Parser parser = XML_ParserCreateNS(0,'|'); - XML_SetElementHandler(parser, &on_start_element, &on_end_element); - XML_SetCharacterDataHandler(parser, &on_character_data); - XML_SetUserData(parser, this); + m_parser = XML_ParserCreateNS(0,'|'); + XML_SetElementHandler(m_parser, &on_start_element, &on_end_element); + XML_SetCharacterDataHandler(m_parser, &on_character_data); + XML_SetUserData(m_parser, this); char buffer[buffer_size]; bool okay = true; do { - in.read(buffer, buffer_size); - - okay = XML_Parse(parser, buffer, in.gcount(), in.gcount() == 0); + in.read(buffer, buffer_size); + okay = XML_Parse(m_parser, buffer, in.gcount(), in.gcount() == 0); } while (okay && in.good()); if (!okay) { std::stringstream s; - s << "Parse error: " << XML_ErrorString(XML_GetErrorCode(parser)) - << " on line " << XML_GetCurrentLineNumber(parser) - <<", column " << XML_GetCurrentColumnNumber(parser); - XML_ParserFree(parser); + s << "on line " << XML_GetCurrentLineNumber(m_parser) + <<", column " << XML_GetCurrentColumnNumber(m_parser) + << ": " << XML_ErrorString(XML_GetErrorCode(m_parser)); throw parse_error(s.str()); } - XML_ParserFree(parser); + XML_ParserFree(m_parser); } private: @@ -71,62 +69,9 @@ private: graphml_reader* self = static_cast(user_data); std::string name(c_name); - std::string::size_type pos = name.find('|'); - if (pos != std::string::npos) - name.erase(0, pos+1); - - if (name == "key") - { - std::string id; - std::string key_name; - std::string key_type; - key_kind kind = all_key; - - while (*atts) - { - std::string name = *atts++; - std::string value = *atts++; - - if (name == "id") id = value; - else if (name == "attr.name") key_name = value; - else if (name == "attr.type") key_type = value; - else if (name == "for") - { - if (value == "graph") kind = graph_key; - else if (value == "node") kind = node_key; - else if (value == "edge") kind = edge_key; - else if (value == "hyperedge") kind = hyperedge_key; - else if (value == "port") kind = port_key; - else if (value == "endpoint") kind = endpoint_key; - else if (value == "all") kind = all_key; - else - { - throw parse_error("unrecognized key kind '" + value + "'"); - } - } - } - - self->m_keys[id] = kind; - self->m_key_name[id] = key_name; - self->m_key_type[id] = key_type; - self->m_active_key = id; - } - else if (name == "node") - { - std::string id; - - while (*atts) - { - std::string name = *atts++; - std::string value = *atts++; - - if (name == "id") id = value; - } - - self->handle_vertex(id); - self->m_active_descriptor = id; - } - else if (name == "edge") + replace_first(name, "http://graphml.graphdrawing.org/xmlns|", ""); + + if (name == "edge") { std::string id; std::string source, target; @@ -153,6 +98,71 @@ private: self->m_active_descriptor = self->m_edge.size(); self->handle_edge(source, target); + } + else if (name == "node") + { + std::string id; + + while (*atts) + { + std::string name = *atts++; + std::string value = *atts++; + + if (name == "id") id = value; + } + + self->handle_vertex(id); + self->m_active_descriptor = id; + } + else if (name == "data") + { + while (*atts) + { + std::string name = *atts++; + std::string value = *atts++; + + if (name == "key") self->m_active_key = value; + } + } + else if (name == "key") + { + std::string id; + std::string key_name; + std::string key_type; + key_kind kind = all_key; + + while (*atts) + { + std::string name = *atts++; + std::string value = *atts++; + + if (name == "id") id = value; + else if (name == "attr.name") key_name = value; + else if (name == "attr.type") key_type = value; + else if (name == "for") + { + if (value == "graph") kind = graph_key; + else if (value == "node") kind = node_key; + else if (value == "edge") kind = edge_key; + else if (value == "hyperedge") kind = hyperedge_key; + else if (value == "port") kind = port_key; + else if (value == "endpoint") kind = endpoint_key; + else if (value == "all") kind = all_key; + else + { + std::stringstream s; + s << "on line " << XML_GetCurrentLineNumber(self->m_parser) + << ", column " << XML_GetCurrentColumnNumber(self->m_parser) + << ": unrecognized key kind '" << value << "'"; + throw parse_error(s.str()); + } + } + } + + self->m_keys[id] = kind; + self->m_key_name[id] = key_name; + self->m_key_type[id] = key_type; + self->m_active_key = id; } else if (name == "graph") { @@ -179,16 +189,6 @@ private: } self->m_active_descriptor = ""; } - else if (name == "data") - { - while (*atts) - { - std::string name = *atts++; - std::string value = *atts++; - - if (name == "key") self->m_active_key = value; - } - } self->m_character_data.clear(); } @@ -199,9 +199,7 @@ private: graphml_reader* self = static_cast(user_data); std::string name(c_name); - std::string::size_type pos = name.find('|'); - if (pos != std::string::npos) - name.erase(0, pos+1); + replace_first(name, "http://graphml.graphdrawing.org/xmlns|", ""); if (name == "data") { @@ -237,7 +235,11 @@ private: } catch (bad_lexical_cast) { - throw parse_error("invalid vertex: " + v); + std::stringstream s; + s << "on line " << XML_GetCurrentLineNumber(m_parser) + << ", column " << XML_GetCurrentColumnNumber(m_parser) + << ": invalid vertex: " << v; + throw parse_error(s.str()); } while(id >= m_canonical_vertex.size()) @@ -310,16 +312,27 @@ private: void handle_property(const std::string& key_id, const variant& descriptor, const std::string& value) { - if (get(&descriptor)) + try { - if (get(descriptor) == "") - m_g.set_graph_property(m_key_name[key_id], value, m_key_type[key_id]); + if (get(&descriptor)) + { + if (get(descriptor) == "") + m_g.set_graph_property(m_key_name[key_id], value, m_key_type[key_id]); + else + m_g.set_vertex_property(m_key_name[key_id], get_vertex_descriptor(get(descriptor)), value, m_key_type[key_id]); + } else - m_g.set_vertex_property(m_key_name[key_id], get_vertex_descriptor(get(descriptor)), value, m_key_type[key_id]); + { + m_g.set_edge_property(m_key_name[key_id], get_edge_descriptor(get(descriptor)), value, m_key_type[key_id]); + } } - else + catch (parse_error &e) { - m_g.set_edge_property(m_key_name[key_id], get_edge_descriptor(get(descriptor)), value, m_key_type[key_id]); + std::stringstream s; + s << "on line " << XML_GetCurrentLineNumber(m_parser) + << ", column " << XML_GetCurrentColumnNumber(m_parser) + << ": " << e.error; + throw parse_error(s.str()); } } @@ -342,6 +355,7 @@ private: std::string m_character_data; bool m_canonical_vertices; bool m_canonical_edges; + XML_Parser m_parser; }; namespace boost From 43b99f3fbe0408ff31b20988c41386aab232b06e Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Fri, 5 Jun 2009 18:21:42 +0000 Subject: [PATCH 222/224] Reverted old version of CSR graph for compatibility, with a #define to switch between the modes; cleaned up interface of new CSR graph; fixed tests and docs accordingly [SVN r53655] --- doc/compressed_sparse_row.html | 119 +++++++-- .../graph/compressed_sparse_row_graph.hpp | 235 ++++++++++++++++-- test/csr_graph_test.cpp | 28 ++- 3 files changed, 338 insertions(+), 44 deletions(-) diff --git a/doc/compressed_sparse_row.html b/doc/compressed_sparse_row.html index 5401e063..750fef61 100644 --- a/doc/compressed_sparse_row.html +++ b/doc/compressed_sparse_row.html @@ -1,7 +1,7 @@