diff --git a/build/Jamfile.v2 b/build/Jamfile.v2 index 19cb65f19..6bf7f5bde 100644 --- a/build/Jamfile.v2 +++ b/build/Jamfile.v2 @@ -21,6 +21,7 @@ lib boost_graph # Without these flags, MSVC 7.1 and 8.0 crash # User reports that VC++ 8.0 does not fail anymore, so that is removed msvc-7.1:-GR- + sun:no : : ; diff --git a/doc/AStarHeuristic.html b/doc/AStarHeuristic.html index 5d0c1aeb3..62257be8b 100644 --- a/doc/AStarHeuristic.html +++ b/doc/AStarHeuristic.html @@ -116,7 +116,7 @@

Concept Checking Class

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

Concept Checking Class

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

Concept Checking Class

typedef typename boost::graph_traits<G>::in_edge_iterator in_edge_iterator; void constraints() { - function_requires< IncidenceGraphConcept<G> >(); - function_requires< MultiPassInputIteratorConcept<in_edge_iterator> >(); + BOOST_CONCEPT_ASSERT(( IncidenceGraphConcept<G> )); + BOOST_CONCEPT_ASSERT(( MultiPassInputIteratorConcept<in_edge_iterator> )); p = in_edges(v, g); e = *p.first; diff --git a/doc/DFSVisitor.html b/doc/DFSVisitor.html index f81f616fb..a018257b2 100644 --- a/doc/DFSVisitor.html +++ b/doc/DFSVisitor.html @@ -150,6 +150,15 @@

Valid Expressions

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

Notation

w -An object of type DistanceMap. +An object of type WeightMap. diff --git a/doc/EdgeListGraph.html b/doc/EdgeListGraph.html index cb87cdb06..fc62539c0 100644 --- a/doc/EdgeListGraph.html +++ b/doc/EdgeListGraph.html @@ -146,8 +146,8 @@

Concept Checking Class

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

Concept Checking Class

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

Concept Checking Class

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

Concept Checking Class

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

Concept Checking Class

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

Concept Checking Class

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

Concept Checking Class

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

Concept Checking Class

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

Concept Checking Class

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

Concept Checking Class

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

Concept Checking Class

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

Concept Checking Class

typedef typename boost::graph_traits<G>::vertex_iterator vertex_iterator; void constraints() { - function_requires< IncidenceGraphConcept<G> >(); - function_requires< AdjacencyGraphConcept<G> >(); - function_requires< MultiPassInputIteratorConcept<vertex_iterator> >(); + BOOST_CONCEPT_ASSERT(( IncidenceGraphConcept<G> )); + BOOST_CONCEPT_ASSERT(( AdjacencyGraphConcept<G> )); + BOOST_CONCEPT_ASSERT(( MultiPassInputIteratorConcept<vertex_iterator> )); p = vertices(g); V = num_vertices(g); diff --git a/doc/adjacency_list.html b/doc/adjacency_list.html index 3e53f9f75..10cc75f13 100644 --- a/doc/adjacency_list.html +++ b/doc/adjacency_list.html @@ -214,12 +214,12 @@

Iterator and Descriptor Stability/Invalidation

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

Iterator and Descriptor Stability/Invalidation

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

Iterator and Descriptor Stability/Invalidation

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

- +
Figure 1: Adjacency Matrix Representation of an Undirected Graph.Figure 2: Adjacency Matrix Representation of an Undirected Graph.
diff --git a/doc/astar_search.html b/doc/astar_search.html index 22b17d7d7..e1828ff5f 100644 --- a/doc/astar_search.html +++ b/doc/astar_search.html @@ -37,10 +37,28 @@

typename P, typename T, typename R> void astar_search_no_init + (const IncidenceGraph &g, + typename graph_traits<VertexListGraph>::vertex_descriptor s, + AStarHeuristic h, const bgl_named_params<P, T, R>& params); + +template <typename VertexListGraph, + typename AStarHeuristic, + typename P, typename T, typename R> +void +astar_search_tree (const VertexListGraph &g, typename graph_traits<VertexListGraph>::vertex_descriptor s, AStarHeuristic h, const bgl_named_params<P, T, R>& params); +template <typename VertexListGraph, + typename AStarHeuristic, + typename P, typename T, typename R> +void +astar_search_no_init_tree + (const IncidenceGraph &g, + typename graph_traits<VertexListGraph>::vertex_descriptor s, + AStarHeuristic h, const bgl_named_params<P, T, R>& params); + // Non-named parameter interface template <typename VertexListGraph, typename AStarHeuristic, typename AStarVisitor, typename PredecessorMap, @@ -60,7 +78,23 @@

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 CompareFunction, typename CombineFunction, + typename CostInf, typename CostZero> +inline void +astar_search_tree + (const VertexListGraph &g, + typename graph_traits<VertexListGraph>::vertex_descriptor s, + AStarHeuristic h, AStarVisitor vis, + PredecessorMap predecessor, CostMap cost, + DistanceMap distance, WeightMap weight, + CompareFunction compare, CombineFunction combine, + CostInf inf, CostZero zero); + +// Versions that do not initialize property maps (used for implicit graphs) template <typename IncidenceGraph, typename AStarHeuristic, typename AStarVisitor, typename PredecessorMap, typename CostMap, typename DistanceMap, @@ -82,6 +116,22 @@

Note that the index_map and color parameters are swapped in astar_search_no_init() relative to astar_search(); the named parameter interfaces are not affected. + +template <typename IncidenceGraph, typename AStarHeuristic, + typename AStarVisitor, typename PredecessorMap, + typename CostMap, typename DistanceMap, + typename WeightMap, + typename CompareFunction, typename CombineFunction, + typename CostInf, typename CostZero> +inline void +astar_search_no_init_tree + (const IncidenceGraph &g, + typename graph_traits<IncidenceGraph>::vertex_descriptor s, + AStarHeuristic h, AStarVisitor vis, + PredecessorMap predecessor, CostMap cost, + DistanceMap distance, WeightMap weight, + CompareFunction compare, CombineFunction combine, + CostInf inf, CostZero zero);

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

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

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

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

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

Named Parameters

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

Named Parameters

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

Named Parameters

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

Named Parameters

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

Named Parameters

UTIL/OUT: color_map(ColorMap c_map)
- This is used during the execution of the algorithm to mark the + This is used during the execution of non-tree versions of the algorithm to + mark the vertices, indicating whether they are on the OPEN or CLOSED lists. The vertices start out white and become gray when they are inserted into the OPEN list. They then turn black when they are examined and diff --git a/doc/bandwidth.html b/doc/bandwidth.html index b02f770d9..93c2d20b2 100644 --- a/doc/bandwidth.html +++ b/doc/bandwidth.html @@ -31,10 +31,10 @@

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

diff --git a/doc/biconnected_components.w b/doc/biconnected_components.w index 97ba5dc85..d2eb21ffd 100644 --- a/doc/biconnected_components.w +++ b/doc/biconnected_components.w @@ -156,11 +156,11 @@ template. @d Concept checking of type parameters @{ -function_requires< VertexListGraphConcept >(); -function_requires< IncidenceGraphConcept >(); -function_requires< WritablePropertyMapConcept >(); -function_requires< ReadWritePropertyMapConcept >(); -function_requires< ReadWritePropertyMapConcept >(); +BOOST_CONCEPT_ASSERT(( VertexListGraphConcept )); +BOOST_CONCEPT_ASSERT(( IncidenceGraphConcept )); +BOOST_CONCEPT_ASSERT(( WritablePropertyMapConcept )); +BOOST_CONCEPT_ASSERT(( ReadWritePropertyMapConcept )); +BOOST_CONCEPT_ASSERT(( ReadWritePropertyMapConcept )); @} The first step of the algorithm is to initialize the discover times of @@ -286,6 +286,7 @@ S.pop(); #include #include #include +#include namespace boost { @ diff --git a/doc/boykov_kolmogorov_max_flow.html b/doc/boykov_kolmogorov_max_flow.html index 1a5b0312c..ecaaf5ca3 100644 --- a/doc/boykov_kolmogorov_max_flow.html +++ b/doc/boykov_kolmogorov_max_flow.html @@ -338,8 +338,8 @@

Example

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

Example: Route planning

boost::property<zipcodes_t, std::vector<int> > > >, // Edge properties boost::property<boost::edge_name_t, std::string, - boost::property<boost::edge_length_t, double, + boost::property<boost::edge_weight_t, double, boost::property<edge_speed_limit_t, int, boost::property<edge_lanes_t, int, boost::property<edge_divided, bool> > > > > > @@ -143,7 +143,7 @@

Accessing bundled properties

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

Properties maps from bundled properties

get(vertex_index, map)))); -

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

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

You may also access the entire vertex or edge bundle as a property map diff --git a/doc/compressed_sparse_row.html b/doc/compressed_sparse_row.html index 8850822de..976e76b90 100644 --- a/doc/compressed_sparse_row.html +++ b/doc/compressed_sparse_row.html @@ -101,8 +101,8 @@

Compressed Sparse Row Graph

 namespace boost {
 
-template<typename Directed = directedS, typename VertexProperty = void, 
-         typename EdgeProperty = void, typename GraphProperty = no_property, 
+template<typename Directed = directedS, typename VertexProperty = no_property, 
+         typename EdgeProperty = no_property, typename GraphProperty = no_property, 
          typename Vertex = std::size_t, typename EdgeIndex = Vertex>
 class compressed_sparse_row_graph
 {
diff --git a/doc/constructing_algorithms.html b/doc/constructing_algorithms.html
index 0067ee3e5..4c9e96e25 100644
--- a/doc/constructing_algorithms.html
+++ b/doc/constructing_algorithms.html
@@ -79,7 +79,7 @@ 

Constructing graph algorithms with BGL

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

Constructing graph algorithms with BGL

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

@@ -122,11 +122,11 @@ 

Constructing graph algorithms with BGL

typedef typename property_traits<Color>::value_type ColorType; typedef typename property_traits<Order>::value_type OrderType; - function_requires< VertexListGraphConcept<VertexListGraph> >(); - function_requires< ReadWritePropertyMapConcept<Color, vertex_descriptor> >(); - function_requires< IntegerConcept<ColorType> >(); - function_requires< size_type, ReadablePropertyMapConcept<Order> >(); - typedef typename same_type<OrderType, vertex_descriptor>::type req_same; + BOOST_CONCEPT_ASSERT(( VertexListGraphConcept<VertexListGraph> )); + BOOST_CONCEPT_ASSERT(( ReadWritePropertyMapConcept<Color, vertex_descriptor> )); + BOOST_CONCEPT_ASSERT(( IntegerConcept<ColorType> )); + BOOST_CONCEPT_ASSERT(( ReadablePropertyMapConcept<Order, size_type> )); + BOOST_STATIC_ASSERT((is_same<OrderType, vertex_descriptor>::value)); size_type max_color = 0; const size_type V = num_vertices(G); @@ -134,7 +134,7 @@

Constructing graph algorithms with BGL

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

Constructing graph algorithms with BGL

// mark all the colors of the adjacent vertices typename GraphTraits::adjacency_iterator ai, aend; - for (tie(ai, aend) = adjacent_vertices(current, G); ai != aend; ++ai) + for (boost::tie(ai, aend) = adjacent_vertices(current, G); ai != aend; ++ai) mark[color[*ai]] = i; // find the smallest color unused by the adjacent vertices diff --git a/doc/cycle_canceling.html b/doc/cycle_canceling.html new file mode 100644 index 000000000..63cecf050 --- /dev/null +++ b/doc/cycle_canceling.html @@ -0,0 +1,223 @@ + + + +Boost Graph Library: Cycle Canceling for Min Cost Max Flow + +C++ Boost + +
+ +

+cycle_canceling +

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

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

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

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

+The algorithm is described in Network Flows. + +

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

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

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

Where Defined

+ +

+boost/graph/successive_shortest_path_nonnegative_weights.hpp + +

+ +

Parameters

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

Named Parameters

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

Complexity

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

Example

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

See Also

+ +successive_shortest_path_nonnegative_weights()
+find_flow_cost(). + +
+
+ + +
Copyright © 2013 +Piotr Wygocki, University of Warsaw (wygos at mimuw.edu.pl) +
+ + + + + + + + + + + + diff --git a/doc/depth_first_search.html b/doc/depth_first_search.html index e217972ae..b0057f7d7 100644 --- a/doc/depth_first_search.html +++ b/doc/depth_first_search.html @@ -107,6 +107,7 @@

(Python
       <i>...</i>
     <b>else if</b> (<i>color[v] =</i> BLACK) 
       <i>...</i>
+    <i>...</i>
   <b>end for</b>
   <i>color[u] :=</i> BLACK
   <i>f_time[u] := time := time + 1</i> 
@@ -140,6 +141,8 @@ <H1><A NAME=(Python
 -
 <i>(u,v)</i> is a cross or forward edge
 -
+finish edge <i>(u,v)</i>
+-
 finish vertex <i>u</i>
 -
 </pre>
@@ -266,6 +269,9 @@ <h3>Visitor Event Points</h3>
 <li><b><tt>vis.forward_or_cross_edge(e, g)</tt></b> is invoked on
   forward or cross edges in the graph. In an undirected graph this
   method is never called.
+
+<li><b><tt>vis.finish_edge(e, g)</tt></b> is invoked on the non-tree edges in 
+  the graph as well as on each tree edge after its target vertex is finished. 
   
 <li><b><tt>vis.finish_vertex(u, g)</tt></b> is invoked on a vertex after
   all of its out edges have been added to the search tree and all of
diff --git a/doc/dijkstra_shortest_paths.html b/doc/dijkstra_shortest_paths.html
index ac991c794..369e78a0d 100644
--- a/doc/dijkstra_shortest_paths.html
+++ b/doc/dijkstra_shortest_paths.html
@@ -248,9 +248,13 @@ <h3>Named Parameters</h3>
 
 OUT: <tt>predecessor_map(PredecessorMap p_map)</tt> 
 <blockquote>
-  The predecessor map records the edges in the minimum spanning
-  tree. Upon completion of the algorithm, the edges <i>(p[u],u)</i>
-  for all <i>u in V</i> are in the minimum spanning tree. If <i>p[u] =
+  The predecessor map records the edges in the shortest path tree, the tree computed
+  by the traversal of the graph. Upon completion of the algorithm, the edges 
+  <i>(p[u],u)</i> for all <i>u in V</i> are in the tree.  The shortest path
+  from vertex <i>s</i> to each vertex <i>v</i> in the graph consists of the
+  vertices <i>v</i>, <i>p[v]</i>, <i>p[p[v]]</i>, and so on until <i>s</i> is
+  reached, in reverse order.  The
+  tree is not guaranteed to be a minimum spanning tree. If <i>p[u] =
   u</i> then <i>u</i> is either the source vertex or a vertex that is
   not reachable from the source.  The <tt>PredecessorMap</tt> type
   must be a <a
@@ -326,7 +330,9 @@ <h3>Named Parameters</h3>
 <blockquote>
   The <tt>inf</tt> object must be the greatest value of any <tt>D</tt> object.
   That is, <tt>compare(d, inf) == true</tt> for any <tt>d != inf</tt>.
-  The type <tt>D</tt> is the value type of the <tt>DistanceMap</tt>.<br>
+  The type <tt>D</tt> is the value type of the <tt>DistanceMap</tt>.  Edges
+  are assumed to have a weight less than (using <tt>distance_compare</tt> for
+  comparison) this value.<br>
   <b>Default:</b> <tt>std::numeric_limits<D>::max()</tt><br>
 
   <b>Python</b>: Unsupported parameter.
@@ -386,7 +392,7 @@ <h3>Named Parameters</h3>
 <H3>Complexity</H3>
 
 <P>
-The time complexity is <i>O(V log V)</i>.
+The time complexity is <i>O(V log V + E)</i>.
 
 
 <h3>Visitor Event Points</h3>
diff --git a/doc/dijkstra_shortest_paths_no_color_map.html b/doc/dijkstra_shortest_paths_no_color_map.html
index c08cc57e0..c7202b68a 100644
--- a/doc/dijkstra_shortest_paths_no_color_map.html
+++ b/doc/dijkstra_shortest_paths_no_color_map.html
@@ -69,7 +69,7 @@ <H1><A NAME=

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

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

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

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

 
-initialize vertex u
-
-
-
 
 discover vertex s
 
@@ -154,10 +147,11 @@ 

edge (u,v) relaxed +discover vertex v + edge (u,v) not relaxed -discover vertex v finish vertex u

@@ -293,7 +287,9 @@

Named Parameters

The distance_infinity object must be the greatest value of any D object. That is, distance_compare(d, distance_infinity) == true for any d != distance_infinity. - The type D is the value type of the DistanceMap.
+ The type D is the value type of the DistanceMap. All edges + are assumed to have weight less than (by distance_compare) this + value.
Default: std::numeric_limits<D>::max()
@@ -322,7 +318,7 @@

Named Parameters

Complexity

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

Visitor Event Points

diff --git a/doc/directed_graph.html b/doc/directed_graph.html new file mode 100644 index 000000000..227a3fa30 --- /dev/null +++ b/doc/directed_graph.html @@ -0,0 +1,96 @@ + + + +Boost Graph Library: Directed Graph + +C++ Boost + +
+ +

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

+ + +

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

Example

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

+ + +

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

Template Parameters

+ +

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

+ +

Where Defined

+ +

+boost/graph/directed_graph.hpp + +

+ +
+


+ + +
Copyright © 2000-2001 +Jeremy Siek, +Indiana University (jsiek@osl.iu.edu)
+Lie-Quan Lee, Indiana University (llee@cs.indiana.edu)
+Andrew Lumsdaine, +Indiana University (lums@osl.iu.edu) +
+ + + diff --git a/doc/distance_recorder.html b/doc/distance_recorder.html index fe7cd559f..a6b05fe27 100644 --- a/doc/distance_recorder.html +++ b/doc/distance_recorder.html @@ -153,7 +153,7 @@

See Also

Visitor concepts

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

+ +edge_coloring +

+ + +

+

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

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

Where defined

+boost/graph/edge_coloring.hpp + +

Parameters

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

Example

+ +See example/king_ordering.cpp. + +

See Also

+ +sequential vertex ordering. + +
+
+ + +
Copyright © 2013 +Maciej Piechotka (uzytkownik2@gmail.com) +
+ + + diff --git a/doc/edge_predecessor_recorder.html b/doc/edge_predecessor_recorder.html new file mode 100644 index 000000000..9ed626b63 --- /dev/null +++ b/doc/edge_predecessor_recorder.html @@ -0,0 +1,197 @@ + + + +Boost Graph Library: edge_predecessor_recorder + +C++ Boost + +
+ +

+
+edge_predecessor_recorder<PredEdgeMap, EventTag>
+
+

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

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

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

Model of

+ +EventVisitor + + +

Where Defined

+ +

+ +boost/graph/visitors.hpp + +

Template Parameters

+ +

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

Associated Types

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

Member Functions

+ +

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

Non-Member Functions

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

See Also

+ +Visitor concepts +

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


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

Frequently Asked Questions

// initialize the vertex_index property values graph_traits<graph_t>::vertex_iterator vi, vend; graph_traits<graph_t>::vertices_size_type cnt = 0; - for(tie(vi,vend) = vertices(G); vi != vend; ++vi) + for(boost::tie(vi,vend) = vertices(G); vi != vend; ++vi) put(index, *vi, cnt++);
@@ -124,8 +124,8 @@

Frequently Asked Questions

not being found, such as:
 ../../../boost/concept_check.hpp:209: no match for
-`boost::detail::error_property_not_found & == 
- boost::detail::error_property_not_found &'
+`boost::detail::error_property_not_found & == 
+ boost::detail::error_property_not_found &'
 
or a message such as:
diff --git a/doc/file_dependency_example.html b/doc/file_dependency_example.html
index c600b74c9..501526764 100644
--- a/doc/file_dependency_example.html
+++ b/doc/file_dependency_example.html
@@ -211,7 +211,7 @@ 

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

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

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

@@ -233,7 +233,7 @@

if (in_degree (*i, g) > 0) { Graph::in_edge_iterator j, j_end; int maxdist = 0; - for (tie(j, j_end) = in_edges(*i, g); j != j_end; ++j) + for (boost::tie(j, j_end) = in_edges(*i, g); j != j_end; ++j) maxdist = std::max(time[source(*j, g)], maxdist); time[*i]=maxdist+1; } diff --git a/doc/find_flow_cost.html b/doc/find_flow_cost.html new file mode 100644 index 000000000..7f839cf90 --- /dev/null +++ b/doc/find_flow_cost.html @@ -0,0 +1,139 @@ + + + +Boost Graph Library: Find Flow Cost + +C++ Boost + +
+ +

+find_flow_cost +

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

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

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

Where Defined

+ +

+boost/graph/successive_shortest_path_nonnegative_weights.hpp + +

+ +

Parameters

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

Named Parameters

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

Complexity

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

Example

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

See Also

+ +cycle_canceling()
+successive_shortest_path_nonnegative_weights(). + +
+
+ + +
Copyright © 2013 +Piotr Wygocki, University of Warsaw (wygos at mimuw.edu.pl) +
+ + + + + + + + + + + + diff --git a/doc/floyd_warshall_shortest.html b/doc/floyd_warshall_shortest.html index ab407a6c0..7d110a80a 100644 --- a/doc/floyd_warshall_shortest.html +++ b/doc/floyd_warshall_shortest.html @@ -134,7 +134,7 @@

Named Parameters

The value used to initialize the distance for each vertex before starting the algorithm, and to represent the distance between vertices -for which there is not path. Should be larger than any possible valid +for which there is no path. Should be larger than any possible valid path length. The argument type must match the value type of the WeightMap.
diff --git a/doc/fruchterman_reingold.html b/doc/fruchterman_reingold.html index f8a61d6d6..f0ea6bd95 100644 --- a/doc/fruchterman_reingold.html +++ b/doc/fruchterman_reingold.html @@ -216,7 +216,7 @@

Named Parameters

Complexity

The time complexity is O(|V|2 + |E|) for each -iteration of the algorithm in the worse case. The average case for the +iteration of the algorithm in the worst case. The average case for the grid variant is O(|V| + |E|). The number of iterations is determined by the cooling schedule. diff --git a/doc/graph_coloring.html b/doc/graph_coloring.html index cfeaaef97..1d4dcb77d 100644 --- a/doc/graph_coloring.html +++ b/doc/graph_coloring.html @@ -127,7 +127,7 @@

Graph Coloring

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

Graph Coloring

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

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

@@ -408,7 +408,7 @@ 

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

@@ -447,8 +447,8 @@

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

add_edge(undigraph, u, v, Weight(3.1)); boost::graph_traits<UndirectedGraph>::edge_descriptor e1, e2; bool found; - tie(e1, found) = edge(u, v, undigraph); - tie(e2, found) = edge(v, u, undigraph); + boost::tie(e1, found) = edge(u, v, undigraph); + boost::tie(e2, found) = edge(v, u, undigraph); std::cout << "in an undirected graph is "; std::cout << "(u,v) == (v,u) ? " << (e1 == e2) << std::endl; diff --git a/doc/graph_theory_review.html b/doc/graph_theory_review.html index e811d2979..33a6d2cd2 100644 --- a/doc/graph_theory_review.html +++ b/doc/graph_theory_review.html @@ -552,6 +552,9 @@

Network Flow Algorithms

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

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

A flow network is shown in Figure diff --git a/doc/grid_graph.html b/doc/grid_graph.html index bebbd1c27..0a2fea5dd 100644 --- a/doc/grid_graph.html +++ b/doc/grid_graph.html @@ -69,7 +69,7 @@

Overview

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

Template Parameters

@@ -81,13 +81,13 @@

Template Parameters

  • - Dimensions - Number of dimensions in the graph, must be greater than 2 + Dimensions - Number of dimensions in the graph
  • - VertexIndex - Type used for vertex indices, defaults to std::size_t + VertexIndex - Type used for vertex indices, defaults to std::size_t
  • - EdgeIndex - Type used for edge indices, defaults to the same type as VertexIndex + EdgeIndex - Type used for edge indices, defaults to the same type as VertexIndex
diff --git a/doc/gursoy_atun_layout.html b/doc/gursoy_atun_layout.html index 52482a36a..db61443e8 100644 --- a/doc/gursoy_atun_layout.html +++ b/doc/gursoy_atun_layout.html @@ -161,7 +161,8 @@

Parameters

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

Parameters

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

Named Parameters

Default: get(vertex_index, g) Note: if you use this default, make sure your graph has an internal vertex_index property. For example, - adjacenty_list with VertexList=listS does + adjacency_list with VertexList=listS does not have an internal vertex_index property.
diff --git a/doc/hawick_circuits.html b/doc/hawick_circuits.html new file mode 100644 index 000000000..5fabcf7c5 --- /dev/null +++ b/doc/hawick_circuits.html @@ -0,0 +1,58 @@ +

+ +

C++ Boost

+ +

hawick_circuits

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

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

+ +

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

+ +

Where defined

+ +

#include <boost/graph/hawick_circuits.hpp>

+ +

Parameters

+ +

IN: Graph const& graph

+ +
+

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

+
+ +

IN: Visitor visitor

+ +
+

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

+ +

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

+
+ +

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

+ +
+

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

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

Example

edge_descriptor e; vertex_descriptor u, v; ... - tie(u, v) = incident(e, g); + boost::tie(u, v) = incident(e, g);
diff --git a/doc/isomorphism-impl-v2.w b/doc/isomorphism-impl-v2.w index 75f88b2bd..602db7ee2 100644 --- a/doc/isomorphism-impl-v2.w +++ b/doc/isomorphism-impl-v2.w @@ -388,31 +388,31 @@ unsigned integers. @d Concept checking @{ // Graph requirements -function_requires< VertexListGraphConcept >(); -function_requires< EdgeListGraphConcept >(); -function_requires< VertexListGraphConcept >(); -function_requires< BidirectionalGraphConcept >(); +BOOST_CONCEPT_ASSERT(( VertexListGraphConcept )); +BOOST_CONCEPT_ASSERT(( EdgeListGraphConcept )); +BOOST_CONCEPT_ASSERT(( VertexListGraphConcept )); +BOOST_CONCEPT_ASSERT(( BidirectionalGraphConcept )); typedef typename graph_traits::vertex_descriptor vertex1_t; typedef typename graph_traits::vertex_descriptor vertex2_t; typedef typename graph_traits::vertices_size_type size_type; // Vertex invariant requirement -function_requires< AdaptableUnaryFunctionConcept >(); -function_requires< AdaptableUnaryFunctionConcept >(); +BOOST_CONCEPT_ASSERT(( AdaptableUnaryFunctionConcept )); +BOOST_CONCEPT_ASSERT(( AdaptableUnaryFunctionConcept )); // Property map requirements -function_requires< ReadWritePropertyMapConcept >(); +BOOST_CONCEPT_ASSERT(( ReadWritePropertyMapConcept )); typedef typename property_traits::value_type IsoMappingValue; BOOST_STATIC_ASSERT((is_same::value)); -function_requires< ReadablePropertyMapConcept >(); +BOOST_CONCEPT_ASSERT(( ReadablePropertyMapConcept )); typedef typename property_traits::value_type IndexMap1Value; BOOST_STATIC_ASSERT((is_convertible::value)); -function_requires< ReadablePropertyMapConcept >(); +BOOST_CONCEPT_ASSERT(( ReadablePropertyMapConcept )); typedef typename property_traits::value_type IndexMap2Value; BOOST_STATIC_ASSERT((is_convertible::value)); @} diff --git a/doc/isomorphism-impl-v3.w b/doc/isomorphism-impl-v3.w index 4ce875176..6e35e8e7e 100644 --- a/doc/isomorphism-impl-v3.w +++ b/doc/isomorphism-impl-v3.w @@ -507,31 +507,31 @@ unsigned integers. @d Concept checking @{ // Graph requirements -function_requires< VertexListGraphConcept >(); -function_requires< EdgeListGraphConcept >(); -function_requires< VertexListGraphConcept >(); -function_requires< BidirectionalGraphConcept >(); +BOOST_CONCEPT_ASSERT(( VertexListGraphConcept )); +BOOST_CONCEPT_ASSERT(( EdgeListGraphConcept )); +BOOST_CONCEPT_ASSERT(( VertexListGraphConcept )); +BOOST_CONCEPT_ASSERT(( BidirectionalGraphConcept )); typedef typename graph_traits::vertex_descriptor vertex1_t; typedef typename graph_traits::vertex_descriptor vertex2_t; typedef typename graph_traits::vertices_size_type size_type; // Vertex invariant requirement -function_requires< AdaptableUnaryFunctionConcept >(); -function_requires< AdaptableUnaryFunctionConcept >(); +BOOST_CONCEPT_ASSERT(( AdaptableUnaryFunctionConcept )); +BOOST_CONCEPT_ASSERT(( AdaptableUnaryFunctionConcept )); // Property map requirements -function_requires< ReadWritePropertyMapConcept >(); +BOOST_CONCEPT_ASSERT(( ReadWritePropertyMapConcept )); typedef typename property_traits::value_type IsoMappingValue; BOOST_STATIC_ASSERT((is_same::value)); -function_requires< ReadablePropertyMapConcept >(); +BOOST_CONCEPT_ASSERT(( ReadablePropertyMapConcept )); typedef typename property_traits::value_type IndexMap1Value; BOOST_STATIC_ASSERT((is_convertible::value)); -function_requires< ReadablePropertyMapConcept >(); +BOOST_CONCEPT_ASSERT(( ReadablePropertyMapConcept )); typedef typename property_traits::value_type IndexMap2Value; BOOST_STATIC_ASSERT((is_convertible::value)); @} diff --git a/doc/isomorphism-impl.w b/doc/isomorphism-impl.w index 58b4bed89..e881a9461 100644 --- a/doc/isomorphism-impl.w +++ b/doc/isomorphism-impl.w @@ -174,7 +174,7 @@ need to consider those vertices that have the same vertex invariant number. The number of vertices in a graph with the same vertex invariant number $i$ is called the \emph{invariant multiplicity} for $i$. In this implementation, by default we use the out-degree of the -vertex as the vertex invariant, though the user can also supply there +vertex as the vertex invariant, though the user can also supply their own invariant function. The ability of the invariant function to prune the search space varies widely with the type of graph. @@ -301,21 +301,21 @@ unsigned integers. @d Concept checking @{ // Graph requirements -function_requires< VertexListGraphConcept >(); -function_requires< EdgeListGraphConcept >(); -function_requires< VertexListGraphConcept >(); -function_requires< BidirectionalGraphConcept >(); +BOOST_CONCEPT_ASSERT(( VertexListGraphConcept )); +BOOST_CONCEPT_ASSERT(( EdgeListGraphConcept )); +BOOST_CONCEPT_ASSERT(( VertexListGraphConcept )); +BOOST_CONCEPT_ASSERT(( BidirectionalGraphConcept )); // Property map requirements -function_requires< ReadWritePropertyMapConcept >(); +BOOST_CONCEPT_ASSERT(( ReadWritePropertyMapConcept )); typedef typename property_traits::value_type IndexMappingValue; BOOST_STATIC_ASSERT((is_same::value)); -function_requires< ReadablePropertyMapConcept >(); +BOOST_CONCEPT_ASSERT(( ReadablePropertyMapConcept )); typedef typename property_traits::value_type IndexMap1Value; BOOST_STATIC_ASSERT((is_convertible::value)); -function_requires< ReadablePropertyMapConcept >(); +BOOST_CONCEPT_ASSERT(( ReadablePropertyMapConcept )); typedef typename property_traits::value_type IndexMap2Value; BOOST_STATIC_ASSERT((is_convertible::value)); @} diff --git a/doc/isomorphism.html b/doc/isomorphism.html index 2738280aa..3b86077b1 100644 --- a/doc/isomorphism.html +++ b/doc/isomorphism.html @@ -59,7 +59,7 @@

algorithm in [46,48]. The file -isomorphism-impl.pdf contains a +isomorphism-impl.pdf contains a (somewhat out-of-date) "literate" description of the implementation. The algorithm used is simple but slow. A more efficient (and much more complex) algorithm is described in [Named Parameters

Python: Must be a vertex_vertex_map for the first graph.

-IN: vertex_invariant1(VertexInvariant1 i) +IN: vertex_invariant1(VertexInvariant1 i1) +IN: vertex_invariant2(VertexInvariant2 i2)
-A mapping i from vertices to integers such that if there is -some isomorphism that maps v onto v' then i(v) == -i(v'). The VertexInvariant type must be a BinaryFunction -where the first argument is a vertex descriptor, the second argument is a -graph, and the result type is an integer. The vertex invariant must -work with the types for graph 1. +Mappings from vertices to integers which restrict which vertices may be +considered isomorphic. If a candidate isomorphism maps v1 to v2 +but i1(v1) != i2(v2), that candidate is rejected. +This mapping can be used either to speed up the search (as is done by the +default value, which requires that the degrees of v1 and v2 are +equal) or to impose extra conditions on the result. The +VertexInvariant1 and VertexInvariant2 types must model UnaryFunction, with +the argument type of vertex_invariant1 being Graph1's vertex +descriptor type, the argument type of vertex_invariant2 being +Graph2's vertex descriptor type, and both functions having integral +result types. The values returned by these two functions must be in the range +[0, vertex_max_invariant).
-Default: degree_vertex_invariant
-Python: Unsupported parameter. -
- -IN: vertex_invariant2(VertexInvariant2 i) -
-A mapping i from vertices to integers such that if there is -some isomorphism that maps v onto v' then i(v) == -i(v'). The VertexInvariant type must be a BinaryFunction -where the first argument is a vertex descriptor, the second argument is a -graph, and the result type is an integer. The vertex invariant must -work with the types for both graph 2. -
-Default: degree_vertex_invariant
+Default: degree_vertex_invariant for both arguments
Python: Unsupported parameter.
diff --git a/doc/johnson_all_pairs_shortest.html b/doc/johnson_all_pairs_shortest.html index 8e95b05a3..716bf5761 100644 --- a/doc/johnson_all_pairs_shortest.html +++ b/doc/johnson_all_pairs_shortest.html @@ -15,7 +15,7 @@
-

+

johnson_all_pairs_shortest_paths

@@ -75,10 +75,12 @@

Parameters

OUT: DistanceMatrix& D
The length of the shortest path between each pair of vertices -u,v in the graph is stored in D[u][v]. The set of -types {DistanceMatrix, vertices_size_type, D} must be a model +u,v in the graph is stored in D[u][v]. The tuple of +types (DistanceMatrix, vertices_size_type, D) must be a model of BasicMatrix where D is the -value type of the DistanceMap. +value type of the DistanceMap. There must be implicit conversions +between the value type of the distance matrix and the value type of the weight +map.
@@ -86,12 +88,11 @@

Named Parameters

IN: weight_map(WeightMap w_map)
- The weight or ``length'' of each edge in the graph. + The weight or "length" of each edge in the graph. The type WeightMap must be a model of Readable Property Map. The edge descriptor type of the graph needs to be usable as the key type for the weight - map. The value type for the map must be - Addable with the value type of the distance map.
+ map. The value type of the weight map must support a subtraction operation.
Default: get(edge_weight, g)
@@ -112,7 +113,7 @@

Named Parameters

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

Named Parameters

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

Named Parameters

This function is used to combine distances to compute the distance of a path. The CombineFunction type must be a model of Binary - Function. The first argument type of the binary function must - match the value type of the DistanceMap property map and - the second argument type must match the value type of the - WeightMap property map. The result type must be the same - type as the distance value type.
+ Function. Both argument types and the return type of the binary function + must match the value type of the WeightMap property map. This operation is required to act as the sum operation for the weight type; in particular, it must be the inverse of the binary - operator on that type.
Default: std::plus<DT> with DT=typename property_traits<WeightMap>::value_type @@ -152,7 +151,7 @@

Named Parameters

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

Named Parameters

This value is used to initialize the distance for the source vertex before the start of the algorithm. The type DT - must be the value type of the WeigthMap.
+ must be the value type of the WeightMap.
Default: 0
diff --git a/doc/kevin_bacon.html b/doc/kevin_bacon.html index 8b2670bdf..6648da7f0 100644 --- a/doc/kevin_bacon.html +++ b/doc/kevin_bacon.html @@ -156,7 +156,7 @@

Input File and Graph Setup

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

Input File and Graph Setup

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

Input File and Graph Setup

   graph_traits<Graph>::edge_descriptor e;
-  tie(e, inserted) = add_edge(u, v, g);
+  boost::tie(e, inserted) = add_edge(u, v, g);
   if (inserted)
     connecting_movie[e] = movie_name;
 
diff --git a/doc/kolmogorov_max_flow.html b/doc/kolmogorov_max_flow.html deleted file mode 100644 index fad874527..000000000 --- a/doc/kolmogorov_max_flow.html +++ /dev/null @@ -1,407 +0,0 @@ - - - - - Boost Graph Library: Boykov-Kolmogorov Maximum Flow - - - - - - - - - -

-C++ Boost -

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

kolmogorov_max_flow -

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

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

-

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

-

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

-

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

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

-

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

-

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

-

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

-

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

-


Details:

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

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

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

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

    -
-


Implementation notes:

-

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

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

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

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

    -
-

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

-

Where Defined

-

boost/graph/kolmogorov_max_flow.hpp -

-

Parameters

-

IN: Graph& g -

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

IN: vertex_descriptor src -

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

IN: vertex_descriptor sink -

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

Named Parameters

-

IN: edge_capacity(EdgeCapacityMap cap) -

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

OUT: edge_residual_capacity(ResidualCapacityEdgeMap res) -

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

IN: edge_reverse(ReverseEdgeMap rev) -

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

UTIL: vertex_predecessor(PredecessorMap pre_map) -

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

OUT/UTIL: vertex_color(ColorMap color) -

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

UTIL: vertex_distance(DistanceMap dist) -

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

IN: vertex_index(VertexIndexMap index_map) -

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

Example

-

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

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

-The output is: -

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

-See Also

-

edmonds_karp_max_flow(),
push_relabel_max_flow(). -

-
- - - - - -
-

Copyright © 2006

-
-

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

-
-



-

- - diff --git a/doc/leda_conversion.html b/doc/leda_conversion.html index a8ba39f3d..6c24c6abf 100644 --- a/doc/leda_conversion.html +++ b/doc/leda_conversion.html @@ -236,9 +236,9 @@

How to Convert Existing Graphs to BGL

main(int,char*[]) { typedef GRAPH<int,int> Graph; - function_requires< VertexListGraphConcept<Graph> >(); - function_requires< BidirectionalGraphConcept<Graph> >(); - function_requires< MutableGraphConcept<Graph> >(); + BOOST_CONCEPT_ASSERT(( VertexListGraphConcept<Graph> )); + BOOST_CONCEPT_ASSERT(( BidirectionalGraphConcept<Graph> )); + BOOST_CONCEPT_ASSERT(( MutableGraphConcept<Graph> )); return 0; }
diff --git a/doc/maximum_adjacency_search.html b/doc/maximum_adjacency_search.html new file mode 100644 index 000000000..d2aa9e801 --- /dev/null +++ b/doc/maximum_adjacency_search.html @@ -0,0 +1,284 @@ + + + +Boost Graph Library: Maximum Adjacency Search + +C++ Boost + +

+maximum_adjacency_search +

+ +

+

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

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

+ +

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

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

Where Defined

+ +

+boost/graph/maximum_adjacency_search.hpp

+ +

Parameters

+ +IN: const UndirectedGraph& g

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

Named Parameters

+ +

IN: WeightMap weights

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

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

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

Expert Parameters

+ +

IN: vertex_index_map(VertexIndexMap vertexIndices)

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

UTIL: vertex_assignment_map(AssignmentMap assignments)

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

UTIL: max_priority_queue(MaxPriorityQueue& pq)

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

UTIL: index_in_heap_map(IndexInHeapMap indicesInHeap)

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

UTIL: distance_map(DistanceMap wAs)

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

Returns

+

void

+ +

Throws

+ +

bad_graph +

+ If num_vertices(g) is less than 2 +

+ +

std::invalid_argument +

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

+Complexity +

+ +

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

+ +

References

+ + +

Visitor Event Points

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

Notes

+ +

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

+ +
+ + +
Copyright © 2012 +Fernando Vilas +
+ + + diff --git a/doc/opposite.html b/doc/opposite.html index 6e3f12db2..f9be2e477 100644 --- a/doc/opposite.html +++ b/doc/opposite.html @@ -56,7 +56,7 @@

Example

edge_descriptor e; ... vertex_descriptor u, v; -tie(u, v) = incident(e, g); +boost::tie(u, v) = incident(e, g); assert(v == opposite(e, u, g)); assert(u == opposite(e, v, g)); diff --git a/doc/planar_face_traversal.html b/doc/planar_face_traversal.html index c52fa8b89..9a93799d6 100644 --- a/doc/planar_face_traversal.html +++ b/doc/planar_face_traversal.html @@ -97,7 +97,7 @@
A plane drawing of a graph (left), and the 8 faces defined by the planar New face: 1 2 5 4 New face: 2 3 4 5 New face: 3 0 1 4 - New face: 2 3 0 1 + New face: 1 0 3 2

Visitor Event Points

diff --git a/doc/predecessor_recorder.html b/doc/predecessor_recorder.html index 75fe44a6f..6f600eafd 100644 --- a/doc/predecessor_recorder.html +++ b/doc/predecessor_recorder.html @@ -31,7 +31,7 @@

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

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

for each vertex u in V[G] color[u] := WHITE d[u] := infinity + end for color[s] := GRAY d[s] := 0 ENQUEUE(PQ, s) @@ -171,7 +172,9 @@

Named Parameters

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

Named Parameters

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

Named Parameters

UTIL/OUT: distance_map(DistanceMap d_map)
- The shortest path weight from the source vertex s to each - vertex in the graph g is recorded in this property map. The - shortest path weight is the sum of the edge weights along the - shortest path. The type DistanceMap must be a model of - g is recorded in this property map, with edges + directed away from the spanning tree root. + The type DistanceMap must be a model of Read/Write Property Map. The vertex descriptor type of the - graph needs to be usable as the key type of the distance map. The - value type of the distance map must be Less Than - Comparable.
+ graph needs to be usable as the key type of the distance map, and the value + type needs to be the same as the value type of the weight_map + argument.
Default: iterator_property_map created from a std::vector of the WeightMap's value type of size diff --git a/doc/push_relabel_max_flow.html b/doc/push_relabel_max_flow.html index 4fcab20a2..5dff05047 100644 --- a/doc/push_relabel_max_flow.html +++ b/doc/push_relabel_max_flow.html @@ -158,7 +158,7 @@

Example

#include <boost/config.hpp> #include <iostream> #include <string> -#include <boost/graph/push_relabel_map_flow.hpp> +#include <boost/graph/push_relabel_max_flow.hpp> #include <boost/graph/adjacency_list.hpp> #include <boost/graph/read_dimacs.hpp> @@ -196,8 +196,8 @@

Example

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

Accessing the Edge Set

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

Accessing the Edge Set

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

Out-Edges, In-Edges, and Edge Descriptors

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

Out-Edges, In-Edges, and Edge Descriptors

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

Adjacent Vertices

std::cout << "adjacent vertices: "; typename graph_traits<Graph>::adjacency_iterator ai; typename graph_traits<Graph>::adjacency_iterator ai_end; - for (tie(ai, ai_end) = adjacent_vertices(v, g); + for (boost::tie(ai, ai_end) = adjacent_vertices(v, g); ai != ai_end; ++ai) std::cout << index[*ai] << " "; std::cout << std::endl; @@ -386,7 +386,7 @@

Adjacent Vertices

adjacent vertices: 0 1

  -

Adding Some Color to your Graph

+

Vertex and Edge Properties

BGL attempts to be as flexible as possible in terms of accommodating how properties are attached to a graph. For instance, a property such as edge weight may need to be used throughout a graph object's lifespan and therefore it would diff --git a/doc/r_c_shortest_paths.html b/doc/r_c_shortest_paths.html index cc5fd260f..069d4c714 100755 --- a/doc/r_c_shortest_paths.html +++ b/doc/r_c_shortest_paths.html @@ -123,7 +123,7 @@

Introduction and Problem Description

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

@@ -446,11 +446,11 @@

Parameters

OUT: std::vector<typename graph_traits<Graph>::edge_descriptor>& pareto_optimal_solution
-A container for storing the first Pareto-optimal (undominated) solution (s-t-path) in the overloads where only one Pareto-optimal solution is returned. The path is returned as a sequence of edge descriptors in reverse order (from t to s). +A container for storing the first Pareto-optimal (undominated) solution (s-t-path) in the overloads where only one Pareto-optimal solution is returned. The path is returned as a sequence of edge descriptors in reverse order (from t to s). This argument is not modified if there are no solutions.
OUT: Resource_Container& pareto_optimal_resource_container
-A Resource_Container object for storing the Pareto-optimal resource container corresponding to the first Pareto-optimal path in the overloads where only one Pareto-optimal solution is returned. +A Resource_Container object for storing the Pareto-optimal resource container corresponding to the first Pareto-optimal path in the overloads where only one Pareto-optimal solution is returned. This argument is not modified if there are no solutions.
IN: const Resource_Container& rc
@@ -466,7 +466,7 @@

Parameters

IN: Label_Allocator la
-An object of type Label_Allocator specifying a strategy for the memory management of the labels. It must offer the same interface as std::allocator. There is a default type default_r_c_shortest_paths_allocator for this parameter using the STL standard allocator. If the third or the fourth overload of the function is used, an object of this type is used as Label_Allocator parameter. If the first or the second overload is used, one must specify both a Label_Allocator and a Visitor parameter. If one wants to develop a user-defined type only for Visitor, one can use default_r_c_shortest_paths_allocator as Label_Allocator parameter. If one wants to use a specialized allocator, one can specify an arbitrary type as template parameter for the value type to the allocator; it is rebound to the correct type. +An object of type Label_Allocator specifying a strategy for the memory management of the labels. It must offer the same interface as std::allocator<r_c_shortest_paths_label<Graph, Resource_Container> >. There is a default type default_r_c_shortest_paths_allocator for this parameter using the STL standard allocator. If the third or the fourth overload of the function is used, an object of this type is used as Label_Allocator parameter. If the first or the second overload is used, one must specify both a Label_Allocator and a Visitor parameter. If one wants to develop a user-defined type only for Visitor, one can use default_r_c_shortest_paths_allocator as Label_Allocator parameter. If one wants to use a specialized allocator, one can specify an arbitrary type as template parameter for the value type to the allocator; it is rebound to the correct type.
IN: Visitor vis
diff --git a/doc/random_spanning_tree.html b/doc/random_spanning_tree.html index 15d4ac3e7..e6d82f48a 100644 --- a/doc/random_spanning_tree.html +++ b/doc/random_spanning_tree.html @@ -76,7 +76,7 @@

Parameters

A random number generator. The generator type must be a model of Uniform + href="../../../doc/html/boost_random/reference.html#boost_random.reference.concepts.uniform_random_number_generator">Uniform Random Number Generator or a pointer or reference to such a type.
diff --git a/doc/read_graphml.html b/doc/read_graphml.html index 42c542a16..21796d8ec 100644 --- a/doc/read_graphml.html +++ b/doc/read_graphml.html @@ -20,7 +20,7 @@

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

The read_graphml function interprets a graph described using the GraphML format and builds a BGL graph that captures that @@ -39,6 +39,10 @@

dynamic_properties object, where the key type is the type of the graph itself.

+

If the file contains multiple graphs, the graph_index parameter controls +which graph will be loaded. It defaults to 0, meaning that the first graph +in the file will be loaded. If graph_index is greater than or equal to the +number of graphs in the file, an empty graph will be returned.

Requirements:

diff --git a/doc/read_graphml.rst b/doc/read_graphml.rst index c61156d89..1e8bd8182 100644 --- a/doc/read_graphml.rst +++ b/doc/read_graphml.rst @@ -19,7 +19,7 @@ __ ../../../index.htm :: void read_graphml(std::istream& in, MutableGraph& graph, - dynamic_properties& dp); + dynamic_properties& dp, size_t graph_index = 0); The ``read_graphml`` function interprets a graph described using the @@ -42,6 +42,11 @@ 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. +If the file contains multiple graphs, the ``graph_index`` parameter controls +which graph will be loaded. It defaults to ``0``, meaning that the first graph +in the file will be loaded. If ``graph_index`` is greater than or equal to the +number of graphs in the file, an empty graph will be returned. + Requirements: - The type of the graph must model the `Mutable Graph`_ concept. - The type of the iterator must model the `Multi-Pass Iterator`_ diff --git a/doc/read_graphviz.html b/doc/read_graphviz.html index b2d7a0b1a..8163c6d05 100644 --- a/doc/read_graphviz.html +++ b/doc/read_graphviz.html @@ -181,8 +181,8 @@

Example

Building the GraphViz Readers

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

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

Notes

diff --git a/doc/read_graphviz.rst b/doc/read_graphviz.rst index 053d1ef22..b8bd341dd 100644 --- a/doc/read_graphviz.rst +++ b/doc/read_graphviz.rst @@ -182,8 +182,8 @@ GraphViz reader to populate an ``adjacency_list`` graph Building the GraphViz Readers ----------------------------- To use the GraphViz readers, you will need to build and link against -the "boost_graph" library. The library can be built by following the -`Boost Jam Build Instructions`_ for the subdirectory ``libs/graph/build``. +the "boost_graph" and "boost_regex" libraries. These libraries can be built by following the +`Boost Jam Build Instructions`_ for the subdirectories ``libs/graph/build`` and ``libs/regex/build``. Notes diff --git a/doc/reverse_graph.html b/doc/reverse_graph.html index 96d03537c..bb4a10f19 100644 --- a/doc/reverse_graph.html +++ b/doc/reverse_graph.html @@ -27,7 +27,7 @@

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

Example

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

Associated Types


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

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

Member Functions


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

Non-Member Functions


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

Non-Member Functions

a vertex or edge descriptor.
+
+typename graph_traits<BidirectionalGraph>::edge_descriptor
+get(edge_underlying_t, const reverse_graph& g, edge_descriptor e)
+
+This returns the underlying edge descriptor for the edge e in the reverse_graph. +
+
 template <class PropertyTag, class X, class Value>
 void
diff --git a/doc/small_world_generator.html b/doc/small_world_generator.html
index 0b853502f..5dfffae54 100644
--- a/doc/small_world_generator.html
+++ b/doc/small_world_generator.html
@@ -45,7 +45,7 @@
 
   small_world_iterator();
   small_world_iterator(RandomGenerator& gen, vertices_size_type n,
-                       vertices_size_type k, double probability,
+                       vertices_size_type k, double probability = 0.,
                        bool allow_self_loops = false);
   // Iterator operations
   reference operator*() const;
@@ -82,7 +82,7 @@ 

Constructors

 small_world_iterator(RandomGenerator& gen, vertices_size_type n,
-                     vertices_size_type k, double probability,
+                     vertices_size_type k, double probability = 0.,
                      bool allow_self_loops = false);
 
diff --git a/doc/sorted_erdos_renyi_gen.html b/doc/sorted_erdos_renyi_gen.html index 55273fa23..b61242a5a 100644 --- a/doc/sorted_erdos_renyi_gen.html +++ b/doc/sorted_erdos_renyi_gen.html @@ -63,7 +63,7 @@ href="adjacency_list.html">adjacency_list or other graph structure with iterator-based initialization. An Erdös-Renyi graph G = (n, p) is a graph with n vertices -that. The probability of having an edge (u, v) in G +such that the probability of having an edge (u, v) in G is p for any vertices u and v. Typically, there are no self-loops, but the generator can optionally introduce self-loops with probability p.

@@ -93,7 +93,7 @@

Constructors

Constructs an Erdös-Renyi generator iterator that creates a graph with n vertices and a given probability of the total number of edges that a simple graph may have. -probability. Random vertices and edges are selected using the +Random vertices and edges are selected using the random number generator gen. Self-loops are permitted only when allow_self_loops is true.
diff --git a/doc/sparse_matrix_ordering.html b/doc/sparse_matrix_ordering.html index 87b39e7f5..44a6a1bc2 100644 --- a/doc/sparse_matrix_ordering.html +++ b/doc/sparse_matrix_ordering.html @@ -143,7 +143,7 @@

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

CMVisitor cm_visitor(inverse_permutation); typename boost::graph_traits<Graph>::vertex_iterator ui, ui_end; - for (tie(ui, ui_end) = vertices(G); ui != ui_end; ++ui) + for (boost::tie(ui, ui_end) = vertices(G); ui != ui_end; ++ui) put(color, *ui, white(c)); breadth_first_search(G, s, Q, cm_visitor, color); } diff --git a/doc/subgraph.html b/doc/subgraph.html index 09d07b30b..90c6019ce 100644 --- a/doc/subgraph.html +++ b/doc/subgraph.html @@ -76,9 +76,9 @@

Example

and subgraphs in Figure 1, so we will need a total of six vertices.
-typedef adjacency_list_traits Traits;
-typedef subgraph< adjacency_list > > Graph;
+typedef adjacency_list_traits< vecS, vecS, directedS > Traits;
+typedef subgraph< adjacency_list< vecS, vecS, directedS,
+  no_property, property< edge_index_t, int > > > Graph;
 
 const int N = 6;
 Graph G0(N);
diff --git a/doc/successive_shortest_path_nonnegative_weights.html b/doc/successive_shortest_path_nonnegative_weights.html
new file mode 100644
index 000000000..d6d53be22
--- /dev/null
+++ b/doc/successive_shortest_path_nonnegative_weights.html
@@ -0,0 +1,264 @@
+
+
+
+Boost Graph Library: Successive Shortest Path for  Min Cost Max Flow
+ 
+C++ Boost 
+
+
+ +

+successive_shortest_path_nonnegative_weights +

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

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

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

+The algorithm is described in Network Flows. + +

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

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

Where Defined

+ +

+boost/graph/successive_shortest_path_nonnegative_weights.hpp + +

+ +

Parameters

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

Named Parameters

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

Complexity

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

Example

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

See Also

+ +cycle_canceling()
+find_flow_cost(). + +
+
+ + +
Copyright © 2013 +Piotr Wygocki, University of Warsaw (wygos at mimuw.edu.pl) +
+ + + + + + + + + + + + diff --git a/doc/table_of_contents.html b/doc/table_of_contents.html index 8c0783f98..9e0e9ec78 100644 --- a/doc/table_of_contents.html +++ b/doc/table_of_contents.html @@ -90,6 +90,7 @@

Table of Contents: the Boost Graph Library
  • Event Visitors
    1. predecessor_recorder +
    2. edge_predecessor_recorder
    3. distance_recorder
    4. time_stamper
    5. property_writer @@ -100,6 +101,10 @@

      Table of Contents: the Boost Graph Library
    6. Graph classes
      1. adjacency_list
      2. +
          +
        1. directed_graph
        2. +
        3. undirected_graph
        4. +
      3. adjacency_matrix
      4. compressed_sparse_row_graph
    7. @@ -167,7 +172,7 @@

      Table of Contents: the Boost Graph Library href="./johnson_all_pairs_shortest.html">johnson_all_pairs_shortest_paths
    8. floyd_warshall_all_pairs_shortest_paths
    9. r_c_shortest_paths - resource-constrained shortest paths
    10. -
    11. astar_search
    12. +
    13. astar_search (A* search algorithm)
  • Minimum Spanning Tree Algorithms
      @@ -181,6 +186,11 @@

      Table of Contents: the Boost Graph Library
    1. random_spanning_tree
    +
  • Algorithm for Common Spanning Trees of Two Graphs +
      +
    1. two_graphs_common_spanning_trees +
  • Connected Components Algorithms
    1. connected_components @@ -201,16 +211,19 @@

      Table of Contents: the Boost Graph Library
      1. edmonds_karp_max_flow
      2. push_relabel_max_flow -
      3. - kolmogorov_max_flow (Deprecated. - Use boykov_kolmogorov_max_flow - instead.) -
      4. boykov_kolmogorov_max_flow
      5. edmonds_maximum_cardinality_matching +
      +
    2. Minimum Cost Maximum Flow Algorithms +
        +
      1. cycle_canceling +
      2. successive_shortest_path_nonnegative_weights +
      3. find_flow_cost
      4. +
      +
    3. Minimum Cut Algorithms +
      1. stoer_wagner_min_cut
      -
    4. Sparse Matrix Ordering Algorithms
      1. Table of Contents: the Boost Graph Library
      2. Graph Structure Comparisons
        1. isomorphism +
        2. vf2_sub_graph_iso (VF2 subgraph isomorphism algorithm)
        3. mcgregor_common_subgraphs
        @@ -276,9 +290,12 @@

        Table of Contents: the Boost Graph Library
      3. Miscellaneous Algorithms
        1. metric_tsp_approx
        2. -
        3. sequential_vertex_coloring -
        4. is_bipartite (including two-coloring of bipartite graphs) -
        5. find_odd_cycle +
        6. sequential_vertex_coloring
        7. +
        8. edge_coloring
        9. +
        10. is_bipartite (including two-coloring of bipartite graphs)
        11. +
        12. find_odd_cycle
        13. +
        14. maximum_adjacency_search
        15. +
        16. hawick_circuits (find all circuits of a directed graph)
      4. diff --git a/doc/topology.html b/doc/topology.html index 24271c0c7..57f53e57c 100644 --- a/doc/topology.html +++ b/doc/topology.html @@ -124,8 +124,8 @@

        Summary

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

        Summary

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

    Summary

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

    Class template cube_topology

    -

    Class template cube_topology is a two-dimensional +

    Class template cube_topology is a three-dimensional hypercube topology.

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

    Summary

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

    Summary

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

    Summary

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

    Class template sphere_topology

    -

    Class template sphere_topology is a two-dimensional +

    Class template sphere_topology is a three-dimensional ball topology.

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

    Summary

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

    Summary

    typedef unspecified point_type; heart_topology(); - heart_topology(RandomNumberGenerator& gen); + heart_topology(RandomNumberGenerator& gen); point_type random_point() const; double distance(point_type a, point_type b) const; point_type move_position_toward(point_type a, double fraction, point_type b) const; diff --git a/doc/transitive_closure.w b/doc/transitive_closure.w index c8db56dc9..136eab681 100644 --- a/doc/transitive_closure.w +++ b/doc/transitive_closure.w @@ -160,11 +160,11 @@ algorithm. @d Concept checking @{ -function_requires< VertexListGraphConcept >(); -function_requires< AdjacencyGraphConcept >(); -function_requires< VertexMutableGraphConcept >(); -function_requires< EdgeMutableGraphConcept >(); -function_requires< ReadablePropertyMapConcept >(); +BOOST_CONCEPT_ASSERT(( VertexListGraphConcept )); +BOOST_CONCEPT_ASSERT(( AdjacencyGraphConcept )); +BOOST_CONCEPT_ASSERT(( VertexMutableGraphConcept )); +BOOST_CONCEPT_ASSERT(( EdgeMutableGraphConcept )); +BOOST_CONCEPT_ASSERT(( ReadablePropertyMapConcept )); @} \noindent To simplify the code in the rest of the function we make the @@ -566,8 +566,8 @@ void warshall_transitive_closure(G& g) typedef typename graph_traits::vertex_descriptor vertex; typedef typename graph_traits::vertex_iterator vertex_iterator; - function_requires< AdjacencyMatrixConcept >(); - function_requires< EdgeMutableGraphConcept >(); + BOOST_CONCEPT_ASSERT(( AdjacencyMatrixConcept )); + BOOST_CONCEPT_ASSERT(( EdgeMutableGraphConcept )); // Matrix form: // for k @@ -597,8 +597,8 @@ void warren_transitive_closure(G& g) typedef typename graph_traits::vertex_descriptor vertex; typedef typename graph_traits::vertex_iterator vertex_iterator; - function_requires< AdjacencyMatrixConcept >(); - function_requires< EdgeMutableGraphConcept >(); + BOOST_CONCEPT_ASSERT(( AdjacencyMatrixConcept )); + BOOST_CONCEPT_ASSERT(( EdgeMutableGraphConcept )); // Make sure second loop will work if (num_vertices(g) == 0) @@ -671,6 +671,7 @@ indent -nut -npcs -i2 -br -cdw -ce transitive_closure.hpp #include #include #include +#include namespace boost { diff --git a/doc/two_graphs_common_spanning_trees.html b/doc/two_graphs_common_spanning_trees.html new file mode 100644 index 000000000..f06825b04 --- /dev/null +++ b/doc/two_graphs_common_spanning_trees.html @@ -0,0 +1,143 @@ + + + +Boost Graph Library: Two-Graphs Common Spanning Trees + +C++ Boost + +
    + +

    Two-Graphs Common Spanning Trees (MRT Algorithm)

    + +

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

    + +

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

    + +

    +// Ordered Edges List +

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

    + +

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

    +

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

    + +

    Where Defined

    + +

    +boost/graph/two_graphs_common_spanning_trees.hpp + +

    Parameters

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

    Example

    + +

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

    + +

    Notes

    + +

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

    + +
    +
    + + + + + +
    Copyright © 2012Michele Caini, (michele.caini@gmail.com)
    + + + diff --git a/doc/undirected_dfs.html b/doc/undirected_dfs.html index ffbefa286..78def89b0 100644 --- a/doc/undirected_dfs.html +++ b/doc/undirected_dfs.html @@ -7,7 +7,7 @@ http://www.boost.org/LICENSE_1_0.txt) --> -Boost Graph Library: Depth-First Search +Boost Graph Library: Undirected Depth-First Search call DFS-VISIT(G, v) else if (vcolor[v] = GRAY and ec = WHITE) ... + ... end for vcolor[u] := BLACK f_time[u] := time := time + 1 @@ -152,6 +153,8 @@

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

    Visitor Event Points

  • vis.back_edge(e, g) is invoked on the back edges in the graph. +
  • vis.finish_edge(e, g) is invoked on the back edges in + the graph as well as on each tree edge after its target vertex is finished. +
  • vis.finish_vertex(u, g) is invoked on a vertex after all of its out edges have been added to the search tree and all of the adjacent vertices have been discovered (but before their diff --git a/doc/undirected_graph.html b/doc/undirected_graph.html new file mode 100644 index 000000000..09a55b0cb --- /dev/null +++ b/doc/undirected_graph.html @@ -0,0 +1,96 @@ + + + +Boost Graph Library: Undirected Graph + +C++ Boost + +
    + +

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

    + + +

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

    Example

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

    + + +

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

    Template Parameters

    + +

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

    + +

    Where Defined

    + +

    +boost/graph/undirected_graph.hpp + +

    + +
    +


    + + +
    Copyright © 2000-2001 +Jeremy Siek, +Indiana University (jsiek@osl.iu.edu)
    +Lie-Quan Lee, Indiana University (llee@cs.indiana.edu)
    +Andrew Lumsdaine, +Indiana University (lums@osl.iu.edu) +
    + + + diff --git a/doc/using_adjacency_list.html b/doc/using_adjacency_list.html index 03206ecc3..efcb40f12 100644 --- a/doc/using_adjacency_list.html +++ b/doc/using_adjacency_list.html @@ -71,7 +71,7 @@

  • slistS selects std::slist.
  • setS selects std::set.
  • multisetS selects std::multiset.
  • -
  • hash_setS selects std::hash_set.
  • +
  • hash_setS selects boost::unordered_set.
  • @@ -326,7 +326,7 @@

    Directed and Undirected Adjacency List graph. See Section Undirected Graphs for a description of the difference between directed and undirected -graphs in BGL. The bidirectealS selector specifies that the +graphs in BGL. The bidirectionalS selector specifies that the graph will provide the in_edges() function as well as the out_edges() function. This imposes twice as much space overhead per edge, which is why in_edges() is optional. diff --git a/doc/using_property_maps.html b/doc/using_property_maps.html index 451e858e1..661e66e05 100644 --- a/doc/using_property_maps.html +++ b/doc/using_property_maps.html @@ -219,7 +219,7 @@

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

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

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

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

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

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

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

    diff --git a/doc/vf2_sub_graph_iso.html b/doc/vf2_sub_graph_iso.html new file mode 100755 index 000000000..95ea9496b --- /dev/null +++ b/doc/vf2_sub_graph_iso.html @@ -0,0 +1,531 @@ + + + + + + Boost Graph Library: VF2 (Sub)Graph Isomorphism + + + +

    C++ Boost

    +

    + vf2_subgraph_iso +

    +
    +// All defaults interface
    +template <typename GraphSmall,
    +          typename GraphLarge,
    +          typename SubGraphIsoMapCallback>
    +bool vf2_subgraph_iso(const GraphSmall& graph_small,
    +                      const GraphLarge& graph_large, 
    +                      SubGraphIsoMapCallback user_callback)
    +
    +
    +// Named parameter version
    +template <typename GraphSmall,
    +          typename GraphLarge,
    +          typename VertexOrderSmall,
    +          typename SubGraphIsoMapCallback,
    +          typename Param,
    +          typename Tag,
    +          typename Rest>
    +bool vf2_subgraph_iso(const GraphSmall& graph_small,
    +                      const GraphLarge& graph_large,
    +                      SubGraphIsoMapCallback user_callback,
    +                      const VertexOrderSmall& vertex_order_small,
    +                      const bgl_named_params<Param, Tag, Rest>& params)
    +
    +
    +// Non-named parameter version
    +template <typename GraphSmall,
    +          typename GraphLarge,
    +          typename IndexMapSmall,
    +          typename IndexMapLarge,
    +          typename VertexOrderSmall,
    +          typename EdgeEquivalencePredicate,
    +          typename VertexEquivalencePredicate,
    +          typename SubGraphIsoMapCallback>
    +bool vf2_subgraph_iso(const GraphSmall& graph_small,
    +                      const GraphLarge& graph_large,
    +                      SubGraphIsoMapCallback user_callback,
    +                      IndexMapSmall index_map_small,
    +                      IndexMapLarge index_map_large, 
    +                      const VertexOrderSmall& vertex_order_small,
    +                      EdgeEquivalencePredicate edge_comp,
    +                      VertexEquivalencePredicate vertex_comp)
    +    
    +

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

    + +

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

    +

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

    + +

    Where Defined

    +

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

    + +

    Parameters

    + +

    IN: const GraphSmall& graph_small

    +
    +

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

    +
    + +

    IN: const GraphLarge& graph_large

    +
    +

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

    +
    + +

    OUT: SubGraphIsoMapCallback user_callback

    +
    +

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

    +
    +template <typename CorrespondenceMap1To2,
    +          typename CorrespondenceMap2To1>
    +bool operator()(CorrespondenceMap1To2 f, CorrespondenceMap2To1 g) const
    +      
    +

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

    +
    + +

    IN: const VertexOrderSmall& vertex_order_small

    +
    +

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

    +
    + +

    Named Parameters

    + +

    IN: vertex_index1(IndexMapSmall index_map_small)

    +
    +

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

    +
    + +

    IN: vertex_index2(IndexMapLarge index_map_large)

    +
    +

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

    +
    + +

    IN: edges_equivalent(EdgeEquivalencePredicate edge_comp)

    +
    +

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

    +
    + +

    IN: vertices_equivalent(VertexEquivalencePredicate vertex_comp)

    +
    +

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

    +
    + +

    Related Functions

    +

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

    +

    vf2_graph_iso(...)

    +

    vf2_subgraph_mono(...)

    +

    + for isomorphism and (not necessarily induced) subgraph isomorphism testing, + taking the same parameters as the corresponding functions vf2_subgraph_iso + for induced subgraph isomorphism testing. + For vf2_graph_iso the algorithm finds all isomorphism mappings between + graphs graph1 and graph2 and outputs them to + user_callback. + For vf2_graph_mono the algorithm finds all mappings of graph_small + to subgraphs of graph_large. + Note that, as opposed to vf2_subgraph_iso, + these subgraphs need not to be induced subgraphs. +

    +

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

    + +

    Utility Functions and Structs

    +

    + +template<typename Graph1, + typename Graph2> +struct vf2_print_callback + +

    +
    +

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

    +
    + +
    +template<typename Graph>
    +std::vector<typename graph_traits<Graph>::vertex_descriptor>
    +  vertex_order_by_mult(const Graph& graph) 
    +    
    +
    +

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

    +
    + +
    +// Variant of verify_subgraph_iso with all default parameters
    +template<typename Graph1,
    +         typename Graph2,
    +         typename CorresponenceMap1To2>
    +inline bool verify_vf2_subgraph_iso(const Graph1& graph1, const Graph2& graph2, 
    +                                    const CorresponenceMap1To2 f)
    +
    +
    +// Verifies a graph (sub)graph isomorphism map 
    +template<typename Graph1,
    +         typename Graph2,
    +         typename CorresponenceMap1To2,
    +         typename EdgeEquivalencePredicate,
    +         typename VertexEquivalencePredicate>
    +inline bool verify_vf2_subgraph_iso(const Graph1& graph1, const Graph2& graph2, 
    +                                    const CorresponenceMap1To2 f,
    +                                    EdgeEquivalencePredicate edge_comp, 
    +                                    VertexEquivalencePredicate vertex_comp) 
    +    
    +
    +

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

    +
    + + +

    Complexity

    +

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

    + +

    Examples

    + +

    Example 1

    +

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

    +
    +typedef adjacency_list<setS, vecS, bidirectionalS> graph_type;
    +
    +// Build graph1
    +int num_vertices1 = 8; graph_type graph1(num_vertices1);
    +add_edge(0, 6, graph1); add_edge(0, 7, graph1);
    +add_edge(1, 5, graph1); add_edge(1, 7, graph1);
    +add_edge(2, 4, graph1); add_edge(2, 5, graph1); add_edge(2, 6, graph1);
    +add_edge(3, 4, graph1);
    +
    +// Build graph2
    +int num_vertices2 = 9; graph_type graph2(num_vertices2);
    +add_edge(0, 6, graph2); add_edge(0, 8, graph2);
    +add_edge(1, 5, graph2); add_edge(1, 7, graph2);
    +add_edge(2, 4, graph2); add_edge(2, 7, graph2); add_edge(2, 8, graph2);
    +add_edge(3, 4, graph2); add_edge(3, 5, graph2); add_edge(3, 6, graph2);
    +
    +// Create callback to print mappings
    +vf2_print_callback<graph_type, graph_type> callback(graph1, graph2);
    +
    +
    +// Print out all subgraph isomorphism mappings between graph1 and graph2.
    +// Vertices and edges are assumed to be always equivalent.
    +vf2_subgraph_iso(graph1, graph2, callback);
    +    
    +

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

    + +

    Example 2

    +

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

    +
    +// Define edge and vertex properties
    +typedef property<edge_name_t, char> edge_property;
    +typedef property<vertex_name_t, char, property<vertex_index_t, int> > vertex_property;
    +
    +// Using a vecS graphs => the index maps are implicit.
    +typedef adjacency_list<vecS, vecS, bidirectionalS, vertex_property, edge_property> graph_type;
    +
    +// Create graph1
    +graph_type graph1;
    +// Add vertices... 
    +add_vertex(vertex_property('a'), graph1);
    +...
    +//... and edges 
    +add_edge(0, 1, edge_property('b'), graph1); 
    +add_edge(0, 1, edge_property('b'), graph1); 
    +...
    +
    +// Create graph2 
    +graph_type graph2;
    +add_vertex(vertex_property('a'), graph2);
    +...  
    +add_edge(0, 1, edge_property('a'), graph2); 
    +...
    +    
    + +

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

    + +
    +// Create the vertex binary predicate
    +typedef property_map<graph_type, vertex_name_t>::type vertex_name_map_t;
    +typedef property_map_equivalent<vertex_name_map_t, vertex_name_map_t> vertex_comp_t;
    +vertex_comp_t vertex_comp =
    +  make_property_map_equivalent(get(vertex_name, graph1), get(vertex_name, graph2));
    +
    +// Create the vertex binary predicate
    +typedef property_map<graph_type, edge_name_t>::type edge_name_map_t;
    +typedef property_map_equivalent<edge_name_map_t, edge_name_map_t> edge_comp_t;
    +edge_comp_t edge_comp =
    +  make_property_map_equivalent(get(edge_name, graph1), get(edge_name, graph2));
    +    
    + +

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

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

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

    + +

    Notes

    +

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

    + +

    Bibliography

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

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

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

    +
    +
    +
    +

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

    + + diff --git a/doc/write-graphviz.html b/doc/write-graphviz.html index 5ae376c52..9af6e7b7b 100644 --- a/doc/write-graphviz.html +++ b/doc/write-graphviz.html @@ -134,7 +134,7 @@

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

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

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

    Parameters

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

    Parameters

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

    Parameters

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

    Example

    -This example demonstrates using BGL-graphviz interface to write -a BGL graph into a graphviz format file. +This example demonstrates using the BGL-Graphviz interface to write +a BGL graph into a Graphviz format file.
     #include <boost/graph/graphviz.hpp>
    diff --git a/doc/write_graphml.html b/doc/write_graphml.html
    index b3bbd131f..8ed7127ab 100644
    --- a/doc/write_graphml.html
    +++ b/doc/write_graphml.html
    @@ -116,11 +116,11 @@ 

    Example

    Graph g(used_by, used_by + nedges, N); graph_traits<Graph>::vertex_iterator v, v_end; - for (tie(v,v_end) = vertices(g); v != v_end; ++v) + for (boost::tie(v,v_end) = vertices(g); v != v_end; ++v) put(vertex_color_t(), g, *v, name[*v]); graph_traits<Graph>::edge_iterator e, e_end; - for (tie(e,e_end) = edges(g); e != e_end; ++e) + for (boost::tie(e,e_end) = edges(g); e != e_end; ++e) put(edge_weight_t(), g, *e, 3); dynamic_properties dp; diff --git a/example/Jamfile.v2 b/example/Jamfile.v2 index c85df0ca4..13cdf75f6 100644 --- a/example/Jamfile.v2 +++ b/example/Jamfile.v2 @@ -20,6 +20,7 @@ exe bron_kerbosch_print_cliques : bron_kerbosch_print_cliques.cpp ; exe bron_kerbosch_clique_number : bron_kerbosch_clique_number.cpp ; exe mcgregor_subgraphs_example : mcgregor_subgraphs_example.cpp ; exe grid_graph_example : grid_graph_example.cpp ; +exe grid_graph_properties : grid_graph_properties.cpp ; exe bipartite_example : bipartite_example.cpp ; exe fr_layout : fr_layout.cpp ; exe canonical_ordering : canonical_ordering.cpp ; @@ -29,4 +30,28 @@ exe ospf-example : ospf-example.cpp ../build//boost_graph ; # exe cc-internet : cc-internet.cpp ../build//boost_graph ; exe implicit_graph : implicit_graph.cpp ; exe astar_maze : astar_maze.cpp ; +exe astar-cities : astar-cities.cpp ; exe stoer_wagner : stoer_wagner.cpp ; +exe bfs-example : bfs-example.cpp ; +exe bfs-example2 : bfs-example2.cpp ; +exe dfs-example : dfs-example.cpp ; +exe dijkstra-example : dijkstra-example.cpp ; +exe dijkstra-example-listS : dijkstra-example-listS.cpp ; +exe dijkstra-no-color-map-example : dijkstra-no-color-map-example.cpp ; +exe adjacency_list_io : adjacency_list_io.cpp ; +exe undirected_adjacency_list : undirected_adjacency_list.cpp ; +exe directed_graph : directed_graph.cpp ; +exe undirected_graph : undirected_graph.cpp ; +exe two_graphs_common_spanning_trees : two_graphs_common_spanning_trees.cpp ; +exe strong_components : strong_components.cpp ../build//boost_graph ; +exe strong-components : strong-components.cpp ; +exe subgraph : subgraph.cpp ; +exe subgraph_properties : subgraph_properties.cpp ; +exe vf2_sub_graph_iso_example : vf2_sub_graph_iso_example.cpp ; +exe vf2_sub_graph_iso_multi_example : vf2_sub_graph_iso_multi_example.cpp ; +exe sloan_ordering : sloan_ordering.cpp ; +exe hawick_circuits : hawick_circuits.cpp ; +exe edge_coloring : edge_coloring.cpp ; +exe successive_shortest_path_nonnegative_weights_example : successive_shortest_path_nonnegative_weights_example.cpp ; +exe cycle_canceling_example : cycle_canceling_example.cpp ; + diff --git a/example/actor_clustering.cpp b/example/actor_clustering.cpp index a29256479..9b1b40221 100644 --- a/example/actor_clustering.cpp +++ b/example/actor_clustering.cpp @@ -9,7 +9,7 @@ // This program performs betweenness centrality (BC) clustering on the // actor collaboration graph available at -// http://www.nd.edu/~networks/database/index.html and outputs the +// http://www.nd.edu/~networks/resources/actor/actor.dat.gz and outputs the // result of clustering in Pajek format. // // This program mimics the BC clustering algorithm program implemented diff --git a/example/astar-cities.cpp b/example/astar-cities.cpp index d5affd110..48b3260f9 100644 --- a/example/astar-cities.cpp +++ b/example/astar-cities.cpp @@ -118,7 +118,6 @@ int main(int argc, char **argv) typedef property_map::type WeightMap; typedef mygraph_t::vertex_descriptor vertex; typedef mygraph_t::edge_descriptor edge_descriptor; - typedef mygraph_t::vertex_iterator vertex_iterator; typedef std::pair edge; // specify data @@ -171,7 +170,7 @@ int main(int argc, char **argv) // pick random start/goal - mt19937 gen(time(0)); + boost::mt19937 gen(time(0)); vertex start = random_vertex(g, gen); vertex goal = random_vertex(g, gen); @@ -192,11 +191,12 @@ int main(int argc, char **argv) vector d(num_vertices(g)); try { // call astar named parameter interface - astar_search + astar_search_tree (g, start, distance_heuristic (locations, goal), - predecessor_map(&p[0]).distance_map(&d[0]). + predecessor_map(make_iterator_property_map(p.begin(), get(vertex_index, g))). + distance_map(make_iterator_property_map(d.begin(), get(vertex_index, g))). visitor(astar_goal_visitor(goal))); diff --git a/example/astar_maze.cpp b/example/astar_maze.cpp index 20cff4fdd..fad2c208f 100644 --- a/example/astar_maze.cpp +++ b/example/astar_maze.cpp @@ -139,7 +139,7 @@ class euclidean_heuristic: euclidean_heuristic(vertex_descriptor goal):m_goal(goal) {}; double operator()(vertex_descriptor v) { - return sqrt(pow(m_goal[0] - v[0], 2) + pow(m_goal[1] - v[1], 2)); + return sqrt(pow(double(m_goal[0] - v[0]), 2) + pow(double(m_goal[1] - v[1]), 2)); } private: @@ -221,7 +221,7 @@ std::ostream& operator<<(std::ostream& output, const maze& m) { if (x == 0) output << BARRIER; // Put the character representing this point in the maze grid. - vertex_descriptor u = {{x, y}}; + vertex_descriptor u = {{x, vertices_size_type(y)}}; if (m.solution_contains(u)) output << "."; else if (m.has_barrier(u)) diff --git a/example/bfs-example.cpp b/example/bfs-example.cpp index 20e3b8da9..0436204ce 100644 --- a/example/bfs-example.cpp +++ b/example/bfs-example.cpp @@ -8,7 +8,7 @@ #include #include #include -#include +#include #include @@ -54,15 +54,18 @@ main() #endif // Typedefs - typedef graph_traits < graph_t >::vertex_descriptor Vertex; typedef graph_traits < graph_t >::vertices_size_type Size; - typedef Size* Iiter; // a vector to hold the discover time property for each vertex std::vector < Size > dtime(num_vertices(g)); + typedef + iterator_property_map::iterator, + property_map::const_type> + dtime_pm_type; + dtime_pm_type dtime_pm(dtime.begin(), get(vertex_index, g)); Size time = 0; - bfs_time_visitor < Size * >vis(&dtime[0], time); + bfs_time_visitor < dtime_pm_type >vis(dtime_pm, time); breadth_first_search(g, vertex(s, g), visitor(vis)); // Use std::sort to order the vertices by their discover time @@ -70,7 +73,7 @@ main() integer_range < int >range(0, N); std::copy(range.begin(), range.end(), discover_order.begin()); std::sort(discover_order.begin(), discover_order.end(), - indirect_cmp < Iiter, std::less < Size > >(&dtime[0])); + indirect_cmp < dtime_pm_type, std::less < Size > >(dtime_pm)); std::cout << "order of discovery: "; for (int i = 0; i < N; ++i) diff --git a/example/bfs-example2.cpp b/example/bfs-example2.cpp index 8225327ec..bc5d92abd 100644 --- a/example/bfs-example2.cpp +++ b/example/bfs-example2.cpp @@ -8,7 +8,8 @@ #include #include #include -#include +#include +#include #include @@ -30,6 +31,7 @@ template < typename TimeMap > class bfs_time_visitor:public default_bfs_visitor struct VertexProps { boost::default_color_type color; std::size_t discover_time; + unsigned int index; }; int @@ -63,9 +65,7 @@ main() #endif // Typedefs - typedef graph_traits::vertex_descriptor Vertex; typedef graph_traits::vertices_size_type Size; - typedef Size* Iiter; Size time = 0; typedef property_map::type dtime_map_t; @@ -76,17 +76,28 @@ main() // a vector to hold the discover time property for each vertex std::vector < Size > dtime(num_vertices(g)); + typedef + iterator_property_map::iterator, + property_map::type> + dtime_pm_type; graph_traits::vertex_iterator vi, vi_end; std::size_t c = 0; - for (boost::tie(vi, vi_end) = vertices(g); vi != vi_end; ++vi, ++c) + for (boost::tie(vi, vi_end) = vertices(g); vi != vi_end; ++vi, ++c) { dtime[c] = dtime_map[*vi]; + put(&VertexProps::index, g, *vi, c); + } + dtime_pm_type dtime_pm(dtime.begin(), get(&VertexProps::index, g)); // Use std::sort to order the vertices by their discover time std::vector::vertices_size_type > discover_order(N); integer_range < int >range(0, N); std::copy(range.begin(), range.end(), discover_order.begin()); std::sort(discover_order.begin(), discover_order.end(), - indirect_cmp < Iiter, std::less < Size > >(&dtime[0])); + make_indirect_cmp( + std::less(), + make_iterator_property_map( + dtime.begin(), + typed_identity_property_map()))); std::cout << "order of discovery: "; for (int i = 0; i < N; ++i) diff --git a/example/bipartite_example.cpp b/example/bipartite_example.cpp index 05dd9cd8d..c8e62ad26 100644 --- a/example/bipartite_example.cpp +++ b/example/bipartite_example.cpp @@ -31,7 +31,7 @@ void print_bipartite (const Graph& g) if (bipartite) { typedef std::vector partition_t; - typedef vec_adj_list_vertex_id_map index_map_t; + typedef typename property_map ::type index_map_t; typedef iterator_property_map partition_map_t; partition_t partition (num_vertices (g)); diff --git a/example/canonical_ordering.cpp b/example/canonical_ordering.cpp index 770b251e3..947984255 100644 --- a/example/canonical_ordering.cpp +++ b/example/canonical_ordering.cpp @@ -54,7 +54,7 @@ int main(int argc, char** argv) property_map::type e_index = get(edge_index, g); graph_traits::edges_size_type edge_count = 0; graph_traits::edge_iterator ei, ei_end; - for(tie(ei, ei_end) = edges(g); ei != ei_end; ++ei) + for(boost::tie(ei, ei_end) = edges(g); ei != ei_end; ++ei) put(e_index, *ei, edge_count++); @@ -64,7 +64,8 @@ int main(int argc, char** argv) std::vector embedding(num_vertices(g)); if (boyer_myrvold_planarity_test(boyer_myrvold_params::graph = g, boyer_myrvold_params::embedding = - &embedding[0] + make_iterator_property_map( + embedding.begin(), get(vertex_index, g)) ) ) std::cout << "Input graph is planar" << std::endl; @@ -75,7 +76,10 @@ int main(int argc, char** argv) ordering_storage_t; ordering_storage_t ordering; - planar_canonical_ordering(g, &embedding[0], std::back_inserter(ordering)); + planar_canonical_ordering(g, + make_iterator_property_map( + embedding.begin(), get(vertex_index, g)), + std::back_inserter(ordering)); ordering_storage_t::iterator oi, oi_end; oi_end = ordering.end(); diff --git a/example/closeness_centrality.cpp b/example/closeness_centrality.cpp index b5aa4776b..ea921114c 100644 --- a/example/closeness_centrality.cpp +++ b/example/closeness_centrality.cpp @@ -75,7 +75,7 @@ main(int argc, char *argv[]) // Print the closeness centrality of each vertex. graph_traits::vertex_iterator i, end; - for(tie(i, end) = vertices(g); i != end; ++i) { + for(boost::tie(i, end) = vertices(g); i != end; ++i) { cout << setw(12) << setiosflags(ios::left) << g[*i].name << get(cm, *i) << endl; } diff --git a/example/clustering_coefficient.cpp b/example/clustering_coefficient.cpp index 70f8e731c..c4a451f13 100644 --- a/example/clustering_coefficient.cpp +++ b/example/clustering_coefficient.cpp @@ -58,7 +58,7 @@ main(int argc, char *argv[]) // Print the clustering coefficient of each vertex. graph_traits::vertex_iterator i, end; - for(tie(i, end) = vertices(g); i != end; ++i) { + for(boost::tie(i, end) = vertices(g); i != end; ++i) { cout << setw(12) << setiosflags(ios::left) << g[*i].name << get(cm, *i) << endl; } diff --git a/example/cycle_canceling_example.cpp b/example/cycle_canceling_example.cpp new file mode 100644 index 000000000..46e85f149 --- /dev/null +++ b/example/cycle_canceling_example.cpp @@ -0,0 +1,28 @@ +//======================================================================= +// Copyright 2013 University of Warsaw. +// Authors: Piotr Wygocki +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +//======================================================================= + +#include +#include + +#include "../test/min_cost_max_flow_utils.hpp" + + +int main() { + boost::SampleGraph::vertex_descriptor s,t; + boost::SampleGraph::Graph g; + boost::SampleGraph::getSampleGraph(g, s, t); + + boost::edmonds_karp_max_flow(g, s, t); + boost::cycle_canceling(g); + + int cost = boost::find_flow_cost(g); + assert(cost == 29); + return 0; +} + diff --git a/example/degree_centrality.cpp b/example/degree_centrality.cpp index 7da764e1b..a8aae31cb 100644 --- a/example/degree_centrality.cpp +++ b/example/degree_centrality.cpp @@ -57,7 +57,7 @@ main(int argc, char *argv[]) // Print the degree centrality of each vertex. graph_traits::vertex_iterator i, end; - for(tie(i, end) = vertices(g); i != end; ++i) { + for(boost::tie(i, end) = vertices(g); i != end; ++i) { cout << setiosflags(ios::left) << setw(12) << g[*i].name << cm[*i] << endl; } diff --git a/example/dfs-example.cpp b/example/dfs-example.cpp index 017053de7..0117b81dc 100644 --- a/example/dfs-example.cpp +++ b/example/dfs-example.cpp @@ -7,7 +7,7 @@ //======================================================================= #include #include -#include +#include #include #include @@ -58,15 +58,17 @@ main() graph_t g(edge_array, edge_array + sizeof(edge_array) / sizeof(E), N); #endif - // Typedefs - typedef boost::graph_traits < graph_t >::vertex_descriptor Vertex; - typedef size_type* Iiter; - // discover time and finish time properties std::vector < size_type > dtime(num_vertices(g)); std::vector < size_type > ftime(num_vertices(g)); + typedef + iterator_property_map::iterator, + property_map::const_type> + time_pm_type; + time_pm_type dtime_pm(dtime.begin(), get(vertex_index, g)); + time_pm_type ftime_pm(ftime.begin(), get(vertex_index, g)); size_type t = 0; - dfs_time_visitor < size_type * >vis(&dtime[0], &ftime[0], t); + dfs_time_visitor < time_pm_type >vis(dtime_pm, ftime_pm, t); depth_first_search(g, visitor(vis)); @@ -75,7 +77,7 @@ main() integer_range < size_type > r(0, N); std::copy(r.begin(), r.end(), discover_order.begin()); std::sort(discover_order.begin(), discover_order.end(), - indirect_cmp < Iiter, std::less < size_type > >(&dtime[0])); + indirect_cmp < time_pm_type, std::less < size_type > >(dtime_pm)); std::cout << "order of discovery: "; int i; for (i = 0; i < N; ++i) @@ -84,7 +86,7 @@ main() std::vector < size_type > finish_order(N); std::copy(r.begin(), r.end(), finish_order.begin()); std::sort(finish_order.begin(), finish_order.end(), - indirect_cmp < Iiter, std::less < size_type > >(&ftime[0])); + indirect_cmp < time_pm_type, std::less < size_type > >(ftime_pm)); std::cout << std::endl << "order of finish: "; for (i = 0; i < N; ++i) std::cout << name[finish_order[i]] << " "; diff --git a/example/dfs.cpp b/example/dfs.cpp index 9dd13da8c..e68ba39af 100644 --- a/example/dfs.cpp +++ b/example/dfs.cpp @@ -27,12 +27,18 @@ Tree edge: 0 --> 2 Tree edge: 2 --> 1 Back edge: 1 --> 1 + Finish edge: 1 --> 1 Tree edge: 1 --> 3 Back edge: 3 --> 1 + Finish edge: 3 --> 1 Tree edge: 3 --> 4 Back edge: 4 --> 0 + Finish edge: 4 --> 0 Back edge: 4 --> 1 + Finish edge: 4 --> 1 Forward or cross edge: 2 --> 3 + Finish edge: 2 --> 3 + Finish edge: 0 --> 2 1 10 3 8 2 9 @@ -69,6 +75,12 @@ struct edge_categorizer : public dfs_visitor { << " --> " << target(e, G) << endl; Base::forward_or_cross_edge(e, G); } + template + void finish_edge(Edge e, Graph& G) { + cout << "Finish edge: " << source(e, G) << + " --> " << target(e, G) << endl; + Base::finish_edge(e, G); + } }; template edge_categorizer diff --git a/example/dfs.expected b/example/dfs.expected index 84aa0c456..b0da6de42 100644 --- a/example/dfs.expected +++ b/example/dfs.expected @@ -1,12 +1,18 @@ Tree edge: 0 --> 2 Tree edge: 2 --> 1 Back edge: 1 --> 1 +Finish edge: 1 --> 1 Tree edge: 1 --> 3 Back edge: 3 --> 1 +Finish edge: 3 --> 1 Tree edge: 3 --> 4 Back edge: 4 --> 0 +Finish edge: 4 --> 0 Back edge: 4 --> 1 +Finish edge: 4 --> 1 Forward or cross edge: 2 --> 3 +Finish edge: 2 --> 3 +Finish edge: 0 --> 2 1 10 3 8 2 9 diff --git a/example/dijkstra-example-listS.cpp b/example/dijkstra-example-listS.cpp index 1c9342072..500f9811b 100644 --- a/example/dijkstra-example-listS.cpp +++ b/example/dijkstra-example-listS.cpp @@ -26,7 +26,6 @@ main(int, char *[]) property > > >, property > graph_t; - typedef graph_traits::edge_descriptor edge_descriptor; typedef std::pair Edge; const int num_nodes = 5; @@ -38,25 +37,8 @@ main(int, char *[]) int num_arcs = sizeof(edge_array) / sizeof(Edge); graph_traits::vertex_iterator i, iend; -#if defined(BOOST_MSVC) && BOOST_MSVC <= 1300 - graph_t g(num_nodes); - property_map::type weightmap = get(edge_weight, g); - - std::vector msvc_vertices; - for (boost::tie(i, iend) = vertices(g); i != iend; ++i) - msvc_vertices.push_back(*i); - - for (std::size_t j = 0; j < num_arcs; ++j) { - edge_descriptor e; bool inserted; - boost::tie(e, inserted) = add_edge(msvc_vertices[edge_array[j].first], - msvc_vertices[edge_array[j].second], g); - weightmap[e] = weights[j]; - } - -#else graph_t g(edge_array, edge_array + num_arcs, weights, num_nodes); property_map::type weightmap = get(edge_weight, g); -#endif // Manually intialize the vertex index and name maps property_map::type indexmap = get(vertex_index, g); @@ -73,16 +55,7 @@ main(int, char *[]) d = get(vertex_distance, g); property_map::type p = get(vertex_predecessor, g); -#if defined(BOOST_MSVC) && BOOST_MSVC <= 1300 - // VC++ has trouble with the named parameters mechanism - property_map::type indexmap = get(vertex_index, g); - dijkstra_shortest_paths(g, s, p, d, weightmap, indexmap, - std::less(), closed_plus(), - (std::numeric_limits::max)(), 0, - default_dijkstra_visitor()); -#else dijkstra_shortest_paths(g, s, predecessor_map(p).distance_map(d)); -#endif std::cout << "distances and parents:" << std::endl; graph_traits < graph_t >::vertex_iterator vi, vend; diff --git a/example/dijkstra-example.cpp b/example/dijkstra-example.cpp index 6a77ddedb..269d2570c 100644 --- a/example/dijkstra-example.cpp +++ b/example/dijkstra-example.cpp @@ -12,6 +12,7 @@ #include #include #include +#include using namespace boost; @@ -21,7 +22,6 @@ main(int, char *[]) typedef adjacency_list < listS, vecS, directedS, no_property, property < edge_weight_t, int > > graph_t; typedef graph_traits < graph_t >::vertex_descriptor vertex_descriptor; - typedef graph_traits < graph_t >::edge_descriptor edge_descriptor; typedef std::pair Edge; const int num_nodes = 5; @@ -32,32 +32,15 @@ main(int, char *[]) }; int weights[] = { 1, 2, 1, 2, 7, 3, 1, 1, 1 }; int num_arcs = sizeof(edge_array) / sizeof(Edge); -#if defined(BOOST_MSVC) && BOOST_MSVC <= 1300 - graph_t g(num_nodes); - property_map::type weightmap = get(edge_weight, g); - for (std::size_t j = 0; j < num_arcs; ++j) { - edge_descriptor e; bool inserted; - boost::tie(e, inserted) = add_edge(edge_array[j].first, edge_array[j].second, g); - weightmap[e] = weights[j]; - } -#else graph_t g(edge_array, edge_array + num_arcs, weights, num_nodes); property_map::type weightmap = get(edge_weight, g); -#endif std::vector p(num_vertices(g)); std::vector d(num_vertices(g)); vertex_descriptor s = vertex(A, g); -#if defined(BOOST_MSVC) && BOOST_MSVC <= 1300 - // VC++ has trouble with the named parameters mechanism - property_map::type indexmap = get(vertex_index, g); - dijkstra_shortest_paths(g, s, &p[0], &d[0], weightmap, indexmap, - std::less(), closed_plus(), - (std::numeric_limits::max)(), 0, - default_dijkstra_visitor()); -#else - dijkstra_shortest_paths(g, s, predecessor_map(&p[0]).distance_map(&d[0])); -#endif + dijkstra_shortest_paths(g, s, + predecessor_map(boost::make_iterator_property_map(p.begin(), get(boost::vertex_index, g))). + distance_map(boost::make_iterator_property_map(d.begin(), get(boost::vertex_index, g)))); std::cout << "distances and parents:" << std::endl; graph_traits < graph_t >::vertex_iterator vi, vend; diff --git a/example/dijkstra-no-color-map-example.cpp b/example/dijkstra-no-color-map-example.cpp index cc89ab4fd..14d196d9f 100644 --- a/example/dijkstra-no-color-map-example.cpp +++ b/example/dijkstra-no-color-map-example.cpp @@ -16,6 +16,7 @@ #include #include #include +#include using namespace boost; @@ -25,7 +26,6 @@ main(int, char *[]) typedef adjacency_list < listS, vecS, directedS, no_property, property < edge_weight_t, int > > graph_t; typedef graph_traits < graph_t >::vertex_descriptor vertex_descriptor; - typedef graph_traits < graph_t >::edge_descriptor edge_descriptor; typedef std::pair Edge; const int num_nodes = 5; @@ -36,33 +36,15 @@ main(int, char *[]) }; int weights[] = { 1, 2, 1, 2, 7, 3, 1, 1, 1 }; int num_arcs = sizeof(edge_array) / sizeof(Edge); -#if defined(BOOST_MSVC) && BOOST_MSVC <= 1300 - graph_t g(num_nodes); - property_map::type weightmap = get(edge_weight, g); - for (std::size_t j = 0; j < num_arcs; ++j) { - edge_descriptor e; bool inserted; - boost::tie(e, inserted) = add_edge(edge_array[j].first, edge_array[j].second, g); - weightmap[e] = weights[j]; - } -#else graph_t g(edge_array, edge_array + num_arcs, weights, num_nodes); property_map::type weightmap = get(edge_weight, g); -#endif std::vector p(num_vertices(g)); std::vector d(num_vertices(g)); vertex_descriptor s = vertex(A, g); -#if defined(BOOST_MSVC) && BOOST_MSVC <= 1300 - // VC++ has trouble with the named parameters mechanism - property_map::type indexmap = get(vertex_index, g); - dijkstra_shortest_paths_no_color_map(g, s, &p[0], &d[0], weightmap, - indexmap, std::less(), - closed_plus(), - (std::numeric_limits::max)(), 0, - default_dijkstra_visitor()); -#else - dijkstra_shortest_paths_no_color_map(g, s, predecessor_map(&p[0]).distance_map(&d[0])); -#endif + dijkstra_shortest_paths_no_color_map(g, s, + predecessor_map(boost::make_iterator_property_map(p.begin(), get(boost::vertex_index, g))). + distance_map(boost::make_iterator_property_map(d.begin(), get(boost::vertex_index, g)))); std::cout << "distances and parents:" << std::endl; graph_traits < graph_t >::vertex_iterator vi, vend; diff --git a/example/directed_graph.cpp b/example/directed_graph.cpp new file mode 100644 index 000000000..bb308aa59 --- /dev/null +++ b/example/directed_graph.cpp @@ -0,0 +1,26 @@ +//======================================================================= +// Copyright 2012 +// Authors: David Doria +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +//======================================================================= + +#include // A subclass to provide reasonable arguments to adjacency_list for a typical directed graph + +int main(int,char*[]) +{ + // directed_graph is a subclass of adjacency_list which gives you object oriented access to functions + // like add_vertex and add_edge, which makes the code easier to understand. However, it hard codes many + // of the template parameters, so it is much less flexible. + + typedef boost::directed_graph<> Graph; + Graph g; + boost::graph_traits::vertex_descriptor v0 = g.add_vertex(); + boost::graph_traits::vertex_descriptor v1 = g.add_vertex(); + + g.add_edge(v0, v1); + + return 0; +} diff --git a/example/edge_coloring.cpp b/example/edge_coloring.cpp new file mode 100644 index 000000000..81a8a38da --- /dev/null +++ b/example/edge_coloring.cpp @@ -0,0 +1,70 @@ +//======================================================================= +// Copyright 2013 Maciej Piechotka +// Authors: Maciej Piechotka +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +//======================================================================= + +#include +#include +#include +#include + +/* + Sample output + Colored using 5 colors + a-d: 4 + a-f: 0 + b-c: 2 + b-e: 3 + b-g: 1 + b-j: 0 + c-d: 0 + c-e: 1 + d-f: 2 + d-i: 1 + e-g: 4 + f-g: 3 + f-h: 1 + g-h: 0 +*/ + +int main(int, char *[]) +{ + using namespace boost; + using namespace std; + typedef adjacency_list Graph; + + typedef std::pair Pair; + Pair edges[14] = { Pair(0,3), //a-d + Pair(0,5), //a-f + Pair(1,2), //b-c + Pair(1,4), //b-e + Pair(1,6), //b-g + Pair(1,9), //b-j + Pair(2,3), //c-d + Pair(2,4), //c-e + Pair(3,5), //d-f + Pair(3,8), //d-i + Pair(4,6), //e-g + Pair(5,6), //f-g + Pair(5,7), //f-h + Pair(6,7) }; //g-h + + Graph G(10); + + for (size_t i = 0; i < sizeof(edges)/sizeof(edges[0]); i++) + add_edge(edges[i].first, edges[i].second, G).first; + + size_t colors = edge_coloring(G, get(edge_bundle, G)); + + cout << "Colored using " << colors << " colors" << endl; + for (size_t i = 0; i < sizeof(edges)/sizeof(edges[0]); i++) { + cout << " " << (char)('a' + edges[i].first) << "-" << (char)('a' + edges[i].second) << ": " << G[edge(edges[i].first, edges[i].second, G).first] << endl; + } + + return 0; +} + diff --git a/example/grid_graph_properties.cpp b/example/grid_graph_properties.cpp new file mode 100644 index 000000000..37d252a85 --- /dev/null +++ b/example/grid_graph_properties.cpp @@ -0,0 +1,40 @@ +//======================================================================= +// Copyright 2012 David Doria +// Authors: David Doria +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +//======================================================================= + +#include +#include +#include + +int main(int argc, char* argv[]) +{ + // A 2D grid graph + typedef boost::grid_graph<2> GraphType; + + // Create a 5x5 graph + const unsigned int dimension = 5; + boost::array lengths = { { dimension, dimension } }; + GraphType graph(lengths); + + // Get the index map of the grid graph + typedef boost::property_map::const_type indexMapType; + indexMapType indexMap(get(boost::vertex_index, graph)); + + // Create a float for every node in the graph + boost::vector_property_map dataMap(num_vertices(graph), indexMap); + + // Associate the value 2.0 with the node at position (0,1) in the grid + boost::graph_traits::vertex_descriptor v = { { 0, 1 } }; + put(dataMap, v, 2.0f); + + // Get the data at the node at position (0,1) in the grid + float retrieved = get(dataMap, v); + std::cout << "Retrieved value: " << retrieved << std::endl; + + return 0; +} diff --git a/example/hawick_circuits.cpp b/example/hawick_circuits.cpp new file mode 100644 index 000000000..b29467b9e --- /dev/null +++ b/example/hawick_circuits.cpp @@ -0,0 +1,96 @@ +// Copyright Louis Dionne 2013 + +// Use, modification and distribution is subject to the Boost Software +// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy +// at http://www.boost.org/LICENSE_1_0.txt) + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +template +struct cycle_printer +{ + cycle_printer(OutputStream& stream) + : os(stream) + { } + + template + void cycle(Path const& p, Graph const& g) + { + if (p.empty()) + return; + + // Get the property map containing the vertex indices + // so we can print them. + typedef typename boost::property_map< + Graph, boost::vertex_index_t + >::const_type IndexMap; + + IndexMap indices = get(boost::vertex_index, g); + + // Iterate over path printing each vertex that forms the cycle. + typename Path::const_iterator i, before_end = boost::prior(p.end()); + for (i = p.begin(); i != before_end; ++i) { + os << get(indices, *i) << " "; + } + os << get(indices, *i) << '\n'; + } + OutputStream& os; +}; + + +// VertexPairIterator is an iterator over pairs of whitespace separated +// vertices `u` and `v` representing a directed edge from `u` to `v`. +template +void build_graph(Graph& graph, unsigned int const nvertices, + VertexPairIterator first, VertexPairIterator last) { + typedef boost::graph_traits Traits; + typedef typename Traits::vertex_descriptor vertex_descriptor; + std::map vertices; + + for (unsigned int i = 0; i < nvertices; ++i) + vertices[i] = add_vertex(graph); + + for (; first != last; ++first) { + unsigned int u = *first++; + + BOOST_ASSERT_MSG(first != last, + "there is a lonely vertex at the end of the edge list"); + + unsigned int v = *first; + + BOOST_ASSERT_MSG(vertices.count(u) == 1 && vertices.count(v) == 1, + "specified a vertex over the number of vertices in the graph"); + + add_edge(vertices[u], vertices[v], graph); + } + BOOST_ASSERT(num_vertices(graph) == nvertices); +} + + +int main(int argc, char const* argv[]) { + if (argc < 2) { + std::cout << "usage: " << argv[0] << " num_vertices < input\n"; + return EXIT_FAILURE; + } + + unsigned int num_vertices = boost::lexical_cast(argv[1]); + std::istream_iterator first_vertex(std::cin), last_vertex; + boost::directed_graph<> graph; + build_graph(graph, num_vertices, first_vertex, last_vertex); + + cycle_printer visitor(std::cout); + boost::hawick_circuits(graph, visitor); + + return EXIT_SUCCESS; +} diff --git a/example/implicit_graph.cpp b/example/implicit_graph.cpp index 6efdeac97..9b42e4d6b 100644 --- a/example/implicit_graph.cpp +++ b/example/implicit_graph.cpp @@ -4,7 +4,7 @@ // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) - +#include #include #include #include @@ -95,6 +95,12 @@ namespace boost { typedef edge_weight_map type; typedef edge_weight_map const_type; }; + + template<> + struct property_map< const ring_graph, edge_weight_t > { + typedef edge_weight_map type; + typedef edge_weight_map const_type; + }; } // Tag values that specify the traversal type in graph::traversal_category. @@ -374,7 +380,7 @@ edges_size_type num_edges(const ring_graph& g) { // AdjacencyMatrix valid expressions std::pair edge(vertex_descriptor u, vertex_descriptor v, const ring_graph& g) { - if (abs(u-v) == 1 && + if ((u == v + 1 || v == u + 1) && u >= 0 && u < num_vertices(g) && v >= 0 && v < num_vertices(g)) return std::pair(edge_descriptor(u, v), true); else @@ -444,15 +450,15 @@ int main (int argc, char const *argv[]) { // Check the concepts that graph models. This is included to demonstrate // how concept checking works, but is not required for a working program // since Boost algorithms do their own concept checking. - function_requires< BidirectionalGraphConcept >(); - function_requires< AdjacencyGraphConcept >(); - function_requires< VertexListGraphConcept >(); - function_requires< EdgeListGraphConcept >(); - function_requires< AdjacencyMatrixConcept >(); - function_requires< - ReadablePropertyMapConcept >(); - function_requires< - ReadablePropertyGraphConcept >(); + BOOST_CONCEPT_ASSERT(( BidirectionalGraphConcept )); + BOOST_CONCEPT_ASSERT(( AdjacencyGraphConcept )); + BOOST_CONCEPT_ASSERT(( VertexListGraphConcept )); + BOOST_CONCEPT_ASSERT(( EdgeListGraphConcept )); + BOOST_CONCEPT_ASSERT(( AdjacencyMatrixConcept )); + BOOST_CONCEPT_ASSERT(( + ReadablePropertyMapConcept )); + BOOST_CONCEPT_ASSERT(( + ReadablePropertyGraphConcept )); // Specify the size of the graph on the command line, or use a default size // of 5. @@ -460,7 +466,6 @@ int main (int argc, char const *argv[]) { // Create a small ring graph. ring_graph g(n); - const_edge_weight_map m = get(edge_weight, g); // Print the outgoing edges of all the vertices. For n=5 this will print: // @@ -473,18 +478,18 @@ int main (int argc, char const *argv[]) { // 5 vertices std::cout << "Vertices, outgoing edges, and adjacent vertices" << std::endl; vertex_iterator vi, vi_end; - for (tie(vi, vi_end) = vertices(g); vi != vi_end; vi++) { + for (boost::tie(vi, vi_end) = vertices(g); vi != vi_end; vi++) { vertex_descriptor u = *vi; std::cout << "Vertex " << u << ": "; // Adjacenct edges out_edge_iterator ei, ei_end; - for (tie(ei, ei_end) = out_edges(u, g); ei != ei_end; ei++) + for (boost::tie(ei, ei_end) = out_edges(u, g); ei != ei_end; ei++) std::cout << *ei << " "; std::cout << " Adjacent vertices "; // Adjacent vertices // Here we want our adjacency_iterator and not boost::adjacency_iterator. ::adjacency_iterator ai, ai_end; - for (tie(ai, ai_end) = adjacent_vertices(u, g); ai != ai_end; ai++) { + for (boost::tie(ai, ai_end) = adjacent_vertices(u, g); ai != ai_end; ai++) { std::cout << *ai << " "; } std::cout << std::endl; @@ -503,7 +508,7 @@ int main (int argc, char const *argv[]) { // 5 edges std::cout << "Edges and weights" << std::endl; edge_iterator ei, ei_end; - for (tie(ei, ei_end) = edges(g); ei != ei_end; ei++) { + for (boost::tie(ei, ei_end) = edges(g); ei != ei_end; ei++) { edge_descriptor e = *ei; std::cout << e << " weight " << get(edge_weight, g, e) << std::endl; } @@ -522,13 +527,19 @@ int main (int argc, char const *argv[]) { vertex_descriptor source = 0; std::vector pred(num_vertices(g)); std::vector dist(num_vertices(g)); + iterator_property_map::iterator, + property_map::const_type> + pred_pm(pred.begin(), get(vertex_index, g)); + iterator_property_map::iterator, + property_map::const_type> + dist_pm(dist.begin(), get(vertex_index, g)); dijkstra_shortest_paths(g, source, - predecessor_map(&pred[0]). - distance_map(&dist[0]) ); + predecessor_map(pred_pm). + distance_map(dist_pm) ); std::cout << "Dijkstra search from vertex " << source << std::endl; - for (tie(vi, vi_end) = vertices(g); vi != vi_end; ++vi) { + for (boost::tie(vi, vi_end) = vertices(g); vi != vi_end; ++vi) { vertex_descriptor u = *vi; std::cout << "Vertex " << u << ": " << "parent "<< pred[*vi] << ", " diff --git a/example/inclusive_mean_geodesic.cpp b/example/inclusive_mean_geodesic.cpp index 91d5a0d47..d825a27dc 100644 --- a/example/inclusive_mean_geodesic.cpp +++ b/example/inclusive_mean_geodesic.cpp @@ -121,7 +121,7 @@ main(int argc, char *argv[]) cout << setw(12) << setiosflags(ios::left) << "excluding"; cout << setw(12) << setiosflags(ios::left) << "including" << endl; graph_traits::vertex_iterator i, end; - for(tie(i, end) = vertices(g); i != end; ++i) { + for(boost::tie(i, end) = vertices(g); i != end; ++i) { cout << setw(12) << setiosflags(ios::left) << g[*i].name << setw(12) << get(exmap, *i) diff --git a/example/influence_prestige.cpp b/example/influence_prestige.cpp index 348b0d160..e7d26f134 100644 --- a/example/influence_prestige.cpp +++ b/example/influence_prestige.cpp @@ -62,7 +62,7 @@ main(int argc, char *argv[]) // Print the degree centrality of each vertex graph_traits::vertex_iterator i, end; - for(tie(i, end) = vertices(g); i != end; ++i) { + for(boost::tie(i, end) = vertices(g); i != end; ++i) { Vertex v = *i; cout << setiosflags(ios::left) << setw(12) << g[v].name << "\t" diff --git a/example/kuratowski_subgraph.cpp b/example/kuratowski_subgraph.cpp index 5b080f46f..8f55a3e65 100644 --- a/example/kuratowski_subgraph.cpp +++ b/example/kuratowski_subgraph.cpp @@ -55,7 +55,7 @@ int main(int argc, char** argv) property_map::type e_index = get(edge_index, g); graph_traits::edges_size_type edge_count = 0; graph_traits::edge_iterator ei, ei_end; - for(tie(ei, ei_end) = edges(g); ei != ei_end; ++ei) + for(boost::tie(ei, ei_end) = edges(g); ei != ei_end; ++ei) put(e_index, *ei, edge_count++); diff --git a/example/leda-concept-check.cpp b/example/leda-concept-check.cpp index 21fc16060..f5720e7db 100644 --- a/example/leda-concept-check.cpp +++ b/example/leda-concept-check.cpp @@ -7,15 +7,16 @@ //======================================================================= #include #include +#include int main() { using namespace boost; - typedef leda::GRAPH < int, int >Graph; - function_requires < VertexListGraphConcept < Graph > >(); - function_requires < BidirectionalGraphConcept < Graph > >(); - function_requires < VertexMutableGraphConcept < Graph > >(); - function_requires < EdgeMutableGraphConcept < Graph > >(); + typedef leda::GRAPH Graph; + BOOST_CONCEPT_ASSERT(( VertexListGraphConcept )); + BOOST_CONCEPT_ASSERT(( BidirectionalGraphConcept< Graph> )); + BOOST_CONCEPT_ASSERT(( VertexMutableGraphConcept< Graph> )); + BOOST_CONCEPT_ASSERT(( EdgeMutableGraphConcept )); return EXIT_SUCCESS; } diff --git a/example/loops_dfs.cpp b/example/loops_dfs.cpp index c6babb1eb..9536701b9 100644 --- a/example/loops_dfs.cpp +++ b/example/loops_dfs.cpp @@ -6,6 +6,7 @@ // http://www.boost.org/LICENSE_1_0.txt) //======================================================================= #include +#include #include #include #include @@ -47,7 +48,7 @@ find_loops(typename graph_traits < Graph >::vertex_descriptor entry, const Graph & g, Loops & loops) // A container of sets of vertices { - function_requires < BidirectionalGraphConcept < Graph > >(); + BOOST_CONCEPT_ASSERT(( BidirectionalGraphConcept )); typedef typename graph_traits < Graph >::edge_descriptor Edge; typedef typename graph_traits < Graph >::vertex_descriptor Vertex; std::vector < Edge > back_edges; @@ -69,7 +70,7 @@ compute_loop_extent(typename graph_traits < Graph >::edge_descriptor back_edge, const Graph & g, Set & loop_set) { - function_requires < BidirectionalGraphConcept < Graph > >(); + BOOST_CONCEPT_ASSERT(( BidirectionalGraphConcept )); typedef typename graph_traits < Graph >::vertex_descriptor Vertex; typedef color_traits < default_color_type > Color; diff --git a/example/make_biconnected_planar.cpp b/example/make_biconnected_planar.cpp index 3c4a7745b..d0c0dd8eb 100644 --- a/example/make_biconnected_planar.cpp +++ b/example/make_biconnected_planar.cpp @@ -51,7 +51,7 @@ int main(int argc, char** argv) property_map::type e_index = get(edge_index, g); graph_traits::edges_size_type edge_count = 0; graph_traits::edge_iterator ei, ei_end; - for(tie(ei, ei_end) = edges(g); ei != ei_end; ++ei) + for(boost::tie(ei, ei_end) = edges(g); ei != ei_end; ++ei) put(e_index, *ei, edge_count++); @@ -86,7 +86,7 @@ int main(int argc, char** argv) // Re-initialize the edge index, since we just added a few edges edge_count = 0; - for(tie(ei, ei_end) = edges(g); ei != ei_end; ++ei) + for(boost::tie(ei, ei_end) = edges(g); ei != ei_end; ++ei) put(e_index, *ei, edge_count++); // Re-size the storage for the biconnected components, since we diff --git a/example/make_maximal_planar.cpp b/example/make_maximal_planar.cpp index 70fd9b3f1..50d42e8de 100644 --- a/example/make_maximal_planar.cpp +++ b/example/make_maximal_planar.cpp @@ -74,7 +74,7 @@ int main(int argc, char** argv) property_map::type e_index = get(edge_index, g); graph_traits::edges_size_type edge_count = 0; graph_traits::edge_iterator ei, ei_end; - for(tie(ei, ei_end) = edges(g); ei != ei_end; ++ei) + for(boost::tie(ei, ei_end) = edges(g); ei != ei_end; ++ei) put(e_index, *ei, edge_count++); @@ -94,7 +94,7 @@ int main(int argc, char** argv) // Re-initialize the edge index, since we just added a few edges edge_count = 0; - for(tie(ei, ei_end) = edges(g); ei != ei_end; ++ei) + for(boost::tie(ei, ei_end) = edges(g); ei != ei_end; ++ei) put(e_index, *ei, edge_count++); @@ -116,7 +116,7 @@ int main(int argc, char** argv) // Re-initialize the edge index, since we just added a few edges edge_count = 0; - for(tie(ei, ei_end) = edges(g); ei != ei_end; ++ei) + for(boost::tie(ei, ei_end) = edges(g); ei != ei_end; ++ei) put(e_index, *ei, edge_count++); // Test for planarity one final time; compute the planar embedding as a diff --git a/example/matching_example.cpp b/example/matching_example.cpp old mode 100755 new mode 100644 index f1d47d954..de39f57c5 --- a/example/matching_example.cpp +++ b/example/matching_example.cpp @@ -44,6 +44,7 @@ int main() // our vertices are stored in a vector, so we can refer to vertices // by integers in the range 0..15 + add_edge(1,2,g); add_edge(0,4,g); add_edge(1,5,g); add_edge(2,6,g); @@ -83,7 +84,7 @@ int main() std::cout << "The matching is:" << std::endl; graph_traits::vertex_iterator vi, vi_end; - for(tie(vi,vi_end) = vertices(g); vi != vi_end; ++vi) + for(boost::tie(vi,vi_end) = vertices(g); vi != vi_end; ++vi) if (mate[*vi] != graph_traits::null_vertex() && *vi < mate[*vi]) std::cout << "{" << *vi << ", " << mate[*vi] << "}" << std::endl; @@ -109,7 +110,7 @@ int main() std::cout << "The matching is:" << std::endl; - for(tie(vi,vi_end) = vertices(g); vi != vi_end; ++vi) + for(boost::tie(vi,vi_end) = vertices(g); vi != vi_end; ++vi) if (mate[*vi] != graph_traits::null_vertex() && *vi < mate[*vi]) std::cout << "{" << *vi << ", " << mate[*vi] << "}" << std::endl; diff --git a/example/mcgregor_subgraphs_example.cpp b/example/mcgregor_subgraphs_example.cpp index 35a3b6930..543259fc7 100644 --- a/example/mcgregor_subgraphs_example.cpp +++ b/example/mcgregor_subgraphs_example.cpp @@ -76,11 +76,7 @@ int main (int argc, char *argv[]) { property >, property > Graph; - typedef graph_traits::vertex_descriptor Vertex; - typedef graph_traits::edge_descriptor Edge; - typedef property_map::type VertexNameMap; - typedef property_map::type EdgeNameMap; // Test maximum and unique variants on known graphs Graph graph_simple1, graph_simple2; diff --git a/example/mean_geodesic.cpp b/example/mean_geodesic.cpp index f6b6892c0..ca246b0a2 100644 --- a/example/mean_geodesic.cpp +++ b/example/mean_geodesic.cpp @@ -77,7 +77,7 @@ main(int argc, char *argv[]) // Print the mean geodesic distance of each vertex and finally, // the graph itself. graph_traits::vertex_iterator i, end; - for(tie(i, end) = vertices(g); i != end; ++i) { + for(boost::tie(i, end) = vertices(g); i != end; ++i) { cout << setw(12) << setiosflags(ios::left) << g[*i].name << get(gm, *i) << endl; } diff --git a/example/min_max_paths.cpp b/example/min_max_paths.cpp index 42a740b68..f32dd76e2 100644 --- a/example/min_max_paths.cpp +++ b/example/min_max_paths.cpp @@ -6,6 +6,9 @@ // accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) //======================================================================= + +#error "This example appears to be incorrect; it uses edge weights that are smaller than 0 using the comparison operator passed to Dijkstra's algorithm, which is not allowed." + #include #include diff --git a/example/planar_face_traversal.cpp b/example/planar_face_traversal.cpp index 8d4daab46..fe96d2de4 100644 --- a/example/planar_face_traversal.cpp +++ b/example/planar_face_traversal.cpp @@ -94,7 +94,7 @@ int main(int argc, char** argv) property_map::type e_index = get(edge_index, g); graph_traits::edges_size_type edge_count = 0; graph_traits::edge_iterator ei, ei_end; - for(tie(ei, ei_end) = edges(g); ei != ei_end; ++ei) + for(boost::tie(ei, ei_end) = edges(g); ei != ei_end; ++ei) put(e_index, *ei, edge_count++); diff --git a/example/put-get-helper-eg.cpp b/example/put-get-helper-eg.cpp index 1134c0293..9c14e1b99 100644 --- a/example/put-get-helper-eg.cpp +++ b/example/put-get-helper-eg.cpp @@ -8,6 +8,7 @@ #include #include #include +#include #ifdef BOOST_NO_STD_ITERATOR_TRAITS #error This examples requires a compiler that provides a working std::iterator_traits @@ -53,6 +54,6 @@ main() typedef foo::iterator_property_map < vec_t::iterator, boost::identity_property_map > pmap_t; using namespace boost; - function_requires < Mutable_LvaluePropertyMapConcept < pmap_t, int > >(); + BOOST_CONCEPT_ASSERT(( Mutable_LvaluePropertyMapConcept )); return 0; } diff --git a/example/scaled_closeness_centrality.cpp b/example/scaled_closeness_centrality.cpp index 5223da97e..a2ade80c6 100644 --- a/example/scaled_closeness_centrality.cpp +++ b/example/scaled_closeness_centrality.cpp @@ -104,7 +104,7 @@ main(int argc, char *argv[]) // Print the scaled closeness centrality of each vertex. graph_traits::vertex_iterator i, end; - for(tie(i, end) = vertices(g); i != end; ++i) { + for(boost::tie(i, end) = vertices(g); i != end; ++i) { cout << setw(12) << setiosflags(ios::left) << g[*i].name << get(cm, *i) << endl; } diff --git a/example/stoer_wagner.cpp b/example/stoer_wagner.cpp index 792ee2084..09f13006a 100644 --- a/example/stoer_wagner.cpp +++ b/example/stoer_wagner.cpp @@ -5,6 +5,7 @@ #include #include +#include #include #include #include @@ -19,14 +20,13 @@ struct edge_t unsigned long second; }; -// A graphic of the min-cut is available at +// A graphic of the min-cut is available at int main() { using namespace std; typedef boost::adjacency_list > undirected_graph; - typedef boost::graph_traits::vertex_descriptor vertex_descriptor; typedef boost::property_map::type weight_map_type; typedef boost::property_traits::value_type weight_type; diff --git a/example/straight_line_drawing.cpp b/example/straight_line_drawing.cpp index 06d1145fc..15aa82968 100644 --- a/example/straight_line_drawing.cpp +++ b/example/straight_line_drawing.cpp @@ -122,7 +122,7 @@ int main(int argc, char** argv) std::cout << "The straight line drawing is: " << std::endl; graph_traits::vertex_iterator vi, vi_end; - for(tie(vi,vi_end) = vertices(g); vi != vi_end; ++vi) + for(boost::tie(vi,vi_end) = vertices(g); vi != vi_end; ++vi) { coord_t coord(get(straight_line_drawing,*vi)); std::cout << *vi << " -> (" << coord.x << ", " << coord.y << ")" diff --git a/example/strong_components.cpp b/example/strong_components.cpp index 4b01f8862..089e3ef92 100644 --- a/example/strong_components.cpp +++ b/example/strong_components.cpp @@ -46,22 +46,23 @@ int main(int, char*[]) using namespace boost; const char* name = "abcdefghij"; - GraphvizDigraph G; - read_graphviz("scc.dot", G); + adjacency_list G; + dynamic_properties dp; + read_graphviz("scc.dot", G, dp); std::cout << "A directed graph:" << std::endl; print_graph(G, name); std::cout << std::endl; - typedef graph_traits::vertex_descriptor Vertex; + typedef graph_traits >::vertex_descriptor Vertex; std::vector component(num_vertices(G)), discover_time(num_vertices(G)); std::vector color(num_vertices(G)); std::vector root(num_vertices(G)); - int num = strong_components(G, &component[0], - root_map(&root[0]). - color_map(&color[0]). - discover_time_map(&discover_time[0])); + int num = strong_components(G, make_iterator_property_map(component.begin(), get(vertex_index, G)), + root_map(make_iterator_property_map(root.begin(), get(vertex_index, G))). + color_map(make_iterator_property_map(color.begin(), get(vertex_index, G))). + discover_time_map(make_iterator_property_map(discover_time.begin(), get(vertex_index, G)))); std::cout << "Total number of components: " << num << std::endl; std::vector::size_type i; diff --git a/example/subgraph.cpp b/example/subgraph.cpp index a28a6cab8..289ae54d9 100644 --- a/example/subgraph.cpp +++ b/example/subgraph.cpp @@ -41,7 +41,6 @@ int main(int,char*[]) { using namespace boost; - typedef adjacency_list_traits Traits; typedef subgraph< adjacency_list, property > > Graph; diff --git a/example/subgraph_properties.cpp b/example/subgraph_properties.cpp index 7de21cec9..613d53a3c 100644 --- a/example/subgraph_properties.cpp +++ b/example/subgraph_properties.cpp @@ -69,20 +69,20 @@ int main(int,char*[]) std::cout << std::endl << "After initializing properties for G1:" << std::endl; std::cout << " Global and local properties for vertex G0[C]..." << std::endl; - std::cout << " G0[C]= " << boost::get(vertex_name, G0, C) << std::endl;// prints: "G0[C]= C" - std::cout << " G1[A1]= " << boost::get(vertex_name, G1, A1) << std::endl;// prints: "G1[A1]= A1" + std::cout << " G0[C]= " << boost::get(vertex_name, G0, vertex(C, G0)) << std::endl;// prints: "G0[C]= C" + std::cout << " G1[A1]= " << boost::get(vertex_name, G1, vertex(A1, G1)) << std::endl;// prints: "G1[A1]= A1" name1[B1] = "B1"; std::cout << " Global and local properties for vertex G0[E]..." << std::endl; - std::cout << " G0[E]= " << boost::get(vertex_name, G0, E) << std::endl;// prints: "G0[E]= E" - std::cout << " G1[B1]= " << boost::get(vertex_name, G1, B1) << std::endl;// prints: "G1[B1]= B1" + std::cout << " G0[E]= " << boost::get(vertex_name, G0, vertex(E, G0)) << std::endl;// prints: "G0[E]= E" + std::cout << " G1[B1]= " << boost::get(vertex_name, G1, vertex(B1, G1)) << std::endl;// prints: "G1[B1]= B1" name1[C1] = "C1"; std::cout << " Global and local properties for vertex G0[F]..." << std::endl; - std::cout << " G0[F]= " << boost::get(vertex_name, G0, F) << std::endl;// prints: "G0[F]= F" - std::cout << " G1[C1]= " << boost::get(vertex_name, G1, C1) << std::endl;// prints: "G1[C1]= C1" + std::cout << " G0[F]= " << boost::get(vertex_name, G0, vertex(F, G0)) << std::endl;// prints: "G0[F]= F" + std::cout << " G1[C1]= " << boost::get(vertex_name, G1, vertex(C1, G1)) << std::endl;// prints: "G1[C1]= C1" Graph& G2 = G0.create_subgraph(); enum { A2, B2 }; // for conveniently refering to vertices in G2 @@ -95,15 +95,15 @@ int main(int,char*[]) std::cout << std::endl << std::endl << "After initializing properties for G2:" << std::endl; std::cout << " Global and local properties for vertex G0[A]" << std::endl; - std::cout << " G0[A]= " << boost::get(vertex_name, G0, A) << std::endl;// prints: "G0[A]= A" - std::cout << " G2[A2]= " << boost::get(vertex_name, G2, A2) << std::endl;// prints: "G2[A2]= A2" + std::cout << " G0[A]= " << boost::get(vertex_name, G0, vertex(A, G0)) << std::endl;// prints: "G0[A]= A" + std::cout << " G2[A2]= " << boost::get(vertex_name, G2, vertex(A2, G2)) << std::endl;// prints: "G2[A2]= A2" name2[B2] = "B2"; std::cout << " Global and local properties for vertex G0[C]..." << std::endl; - std::cout << " G0[C]= " << boost::get(vertex_name, G0, C) << std::endl;// prints: "G0[C]= C" - std::cout << " G1[A1]= " << boost::get(vertex_name, G1, A1) << std::endl;// prints: "G1[A1]= A1" - std::cout << " G2[B2]= " << boost::get(vertex_name, G2, B2) << std::endl;// prints: "G2[B2]= B2" + std::cout << " G0[C]= " << boost::get(vertex_name, G0, vertex(C, G0)) << std::endl;// prints: "G0[C]= C" + std::cout << " G1[A1]= " << boost::get(vertex_name, G1, vertex(A1, G1)) << std::endl;// prints: "G1[A1]= A1" + std::cout << " G2[B2]= " << boost::get(vertex_name, G2, vertex(B2, G2)) << std::endl;// prints: "G2[B2]= B2" return 0; } diff --git a/example/successive_shortest_path_nonnegative_weights_example.cpp b/example/successive_shortest_path_nonnegative_weights_example.cpp new file mode 100644 index 000000000..0edc3710f --- /dev/null +++ b/example/successive_shortest_path_nonnegative_weights_example.cpp @@ -0,0 +1,30 @@ +//======================================================================= +// Copyright 2013 University of Warsaw. +// Authors: Piotr Wygocki +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +//======================================================================= + +#include +#include + +#include "../test/min_cost_max_flow_utils.hpp" + + +int main() { + boost::SampleGraph::vertex_descriptor s,t; + boost::SampleGraph::Graph g; + boost::SampleGraph::getSampleGraph(g, s, t); + + boost::successive_shortest_path_nonnegative_weights(g, s, t); + + int cost = boost::find_flow_cost(g); + assert(cost == 29); + + return 0; +} + + + diff --git a/example/two_graphs_common_spanning_trees.cpp b/example/two_graphs_common_spanning_trees.cpp new file mode 100644 index 000000000..2fa851798 --- /dev/null +++ b/example/two_graphs_common_spanning_trees.cpp @@ -0,0 +1,94 @@ +// Copyright (C) 2012, Michele Caini. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// Two Graphs Common Spanning Trees Algorithm +// Based on academic article of Mint, Read and Tarjan +// Efficient Algorithm for Common Spanning Tree Problem +// Electron. Lett., 28 April 1983, Volume 19, Issue 9, p.346-347 + + +#include +#include +#include +#include + + +using namespace std; + +typedef +boost::adjacency_list + < + boost::vecS, // OutEdgeList + boost::vecS, // VertexList + boost::undirectedS, // Directed + boost::no_property, // VertexProperties + boost::no_property, // EdgeProperties + boost::no_property, // GraphProperties + boost::listS // EdgeList + > +Graph +; + +typedef +boost::graph_traits::vertex_descriptor +vertex_descriptor; + +typedef +boost::graph_traits::edge_descriptor +edge_descriptor; + +typedef +boost::graph_traits::vertex_iterator +vertex_iterator; + +typedef +boost::graph_traits::edge_iterator +edge_iterator; + + +int main(int argc, char **argv) +{ + Graph iG, vG; + vector< edge_descriptor > iG_o; + vector< edge_descriptor > vG_o; + + iG_o.push_back(boost::add_edge(0, 1, iG).first); + iG_o.push_back(boost::add_edge(0, 2, iG).first); + iG_o.push_back(boost::add_edge(0, 3, iG).first); + iG_o.push_back(boost::add_edge(0, 4, iG).first); + iG_o.push_back(boost::add_edge(1, 2, iG).first); + iG_o.push_back(boost::add_edge(3, 4, iG).first); + + vG_o.push_back(boost::add_edge(1, 2, vG).first); + vG_o.push_back(boost::add_edge(2, 0, vG).first); + vG_o.push_back(boost::add_edge(2, 3, vG).first); + vG_o.push_back(boost::add_edge(4, 3, vG).first); + vG_o.push_back(boost::add_edge(0, 3, vG).first); + vG_o.push_back(boost::add_edge(0, 4, vG).first); + + vector inL(iG_o.size(), false); + + std::vector< std::vector > coll; + boost::tree_collector< + std::vector< std::vector >, + std::vector + > tree_collector(coll); + boost::two_graphs_common_spanning_trees + ( + iG, + iG_o, + vG, + vG_o, + tree_collector, + inL + ); + + std::vector< std::vector >::iterator it; + for(it = coll.begin(); it != coll.end(); ++it) { + // Here you can play with the trees that the algorithm has found. + } + + return 0; +} diff --git a/example/undirected.cpp b/example/undirected_adjacency_list.cpp similarity index 87% rename from example/undirected.cpp rename to example/undirected_adjacency_list.cpp index 97b14d990..49d312021 100644 --- a/example/undirected.cpp +++ b/example/undirected_adjacency_list.cpp @@ -26,12 +26,12 @@ undirected_graph_demo1() add_edge(zero, two, undigraph); add_edge(one, two, undigraph); - std::cout << "out_edges(0): "; + std::cout << "out_edges(0):"; for (boost::tie(out, out_end) = out_edges(zero, undigraph); out != out_end; ++out) - std::cout << *out; - std::cout << std::endl << "in_edges(0): "; + std::cout << ' ' << *out; + std::cout << std::endl << "in_edges(0):"; for (boost::tie(in, in_end) = in_edges(zero, undigraph); in != in_end; ++in) - std::cout << *in; + std::cout << ' ' << *in; std::cout << std::endl; } @@ -91,6 +91,14 @@ undirected_graph_demo2() #endif std::cout << "weight[(u,v)] = " << get(weight, e1) << std::endl; std::cout << "weight[(v,u)] = " << get(weight, e2) << std::endl; + + std::cout << "the edges incident to v: "; + typename boost::graph_traits::out_edge_iterator e, e_end; + typename boost::graph_traits::vertex_descriptor + s = vertex(0, undigraph); + for (boost::tie(e, e_end) = out_edges(s, undigraph); e != e_end; ++e) + std::cout << "(" << source(*e, undigraph) + << "," << target(*e, undigraph) << ")" << std::endl; } @@ -103,7 +111,7 @@ main() typedef adjacency_list < vecS, vecS, directedS, no_property, Weight > DirectedGraph; undirected_graph_demo1 < UndirectedGraph > (); - undirected_graph_demo2 < UndirectedGraph > (); directed_graph_demo < DirectedGraph > (); + undirected_graph_demo2 < UndirectedGraph > (); return 0; } diff --git a/example/undirected.expected b/example/undirected_adjacency_list.expected similarity index 79% rename from example/undirected.expected rename to example/undirected_adjacency_list.expected index 015a7afc9..b02c64016 100644 --- a/example/undirected.expected +++ b/example/undirected_adjacency_list.expected @@ -1,3 +1,5 @@ +out_edges(0): (0,1) (0,2) +in_edges(0): (1,0) (2,0) in a directed graph is (u,v) == (v,u) ? 0 weight[(u,v)] = 1.2 weight[(v,u)] = 2.4 diff --git a/example/undirected_graph.cpp b/example/undirected_graph.cpp new file mode 100644 index 000000000..d926c7b51 --- /dev/null +++ b/example/undirected_graph.cpp @@ -0,0 +1,30 @@ +//======================================================================= +// Copyright 2012 +// Authors: David Doria +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +//======================================================================= + +#include +#include + +typedef boost::undirected_graph Graph; + +int main(int,char*[]) +{ + // Create a graph object + Graph g; + + // Add vertices + boost::graph_traits::vertex_descriptor v0 = g.add_vertex(); + boost::graph_traits::vertex_descriptor v1 = g.add_vertex(); + boost::graph_traits::vertex_descriptor v2 = g.add_vertex(); + + // Add edges + g.add_edge(v0, v1); + g.add_edge(v1, v2); + + return 0; +} diff --git a/example/vf2_sub_graph_iso_example.cpp b/example/vf2_sub_graph_iso_example.cpp new file mode 100755 index 000000000..8e17d2a70 --- /dev/null +++ b/example/vf2_sub_graph_iso_example.cpp @@ -0,0 +1,40 @@ +//======================================================================= +// Copyright (C) 2012 Flavio De Lorenzi (fdlorenzi@gmail.com) +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +//======================================================================= + +#include +#include +using namespace boost; + + +int main() { + + typedef adjacency_list graph_type; + + // Build graph1 + int num_vertices1 = 8; graph_type graph1(num_vertices1); + add_edge(0, 6, graph1); add_edge(0, 7, graph1); + add_edge(1, 5, graph1); add_edge(1, 7, graph1); + add_edge(2, 4, graph1); add_edge(2, 5, graph1); add_edge(2, 6, graph1); + add_edge(3, 4, graph1); + + // Build graph2 + int num_vertices2 = 9; graph_type graph2(num_vertices2); + add_edge(0, 6, graph2); add_edge(0, 8, graph2); + add_edge(1, 5, graph2); add_edge(1, 7, graph2); + add_edge(2, 4, graph2); add_edge(2, 7, graph2); add_edge(2, 8, graph2); + add_edge(3, 4, graph2); add_edge(3, 5, graph2); add_edge(3, 6, graph2); + + // Create callback to print mappings + vf2_print_callback callback(graph1, graph2); + + // Print out all subgraph isomorphism mappings between graph1 and graph2. + // Vertices and edges are assumed to be always equivalent. + vf2_subgraph_iso(graph1, graph2, callback); + + return 0; +} diff --git a/example/vf2_sub_graph_iso_multi_example.cpp b/example/vf2_sub_graph_iso_multi_example.cpp new file mode 100755 index 000000000..6f9e34a2a --- /dev/null +++ b/example/vf2_sub_graph_iso_multi_example.cpp @@ -0,0 +1,89 @@ +//======================================================================= +// Copyright (C) 2012 Flavio De Lorenzi (fdlorenzi@gmail.com) +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +//======================================================================= + +#include +#include +using namespace boost; + +int main() { + typedef property edge_property; + typedef property > vertex_property; + + // Using a vecS graphs => the index maps are implicit. + typedef adjacency_list graph_type; + + // Build graph1 + graph_type graph1; + + add_vertex(vertex_property('a'), graph1); + add_vertex(vertex_property('a'), graph1); + add_vertex(vertex_property('a'), graph1); + + add_edge(0, 1, edge_property('b'), graph1); + add_edge(0, 1, edge_property('b'), graph1); + add_edge(0, 1, edge_property('d'), graph1); + + add_edge(1, 2, edge_property('s'), graph1); + + add_edge(2, 2, edge_property('l'), graph1); + add_edge(2, 2, edge_property('l'), graph1); + + // Build graph2 + graph_type graph2; + + add_vertex(vertex_property('a'), graph2); + add_vertex(vertex_property('a'), graph2); + add_vertex(vertex_property('a'), graph2); + add_vertex(vertex_property('a'), graph2); + add_vertex(vertex_property('a'), graph2); + add_vertex(vertex_property('a'), graph2); + + add_edge(0, 1, edge_property('a'), graph2); + add_edge(0, 1, edge_property('a'), graph2); + add_edge(0, 1, edge_property('b'), graph2); + + add_edge(1, 2, edge_property('s'), graph2); + + add_edge(2, 3, edge_property('b'), graph2); + add_edge(2, 3, edge_property('d'), graph2); + add_edge(2, 3, edge_property('b'), graph2); + + add_edge(3, 4, edge_property('s'), graph2); + + add_edge(4, 4, edge_property('l'), graph2); + add_edge(4, 4, edge_property('l'), graph2); + + add_edge(4, 5, edge_property('c'), graph2); + add_edge(4, 5, edge_property('c'), graph2); + add_edge(4, 5, edge_property('c'), graph2); + + add_edge(5, 0, edge_property('s'), graph2); + + // create predicates + typedef property_map::type vertex_name_map_t; + typedef property_map_equivalent vertex_comp_t; + vertex_comp_t vertex_comp = + make_property_map_equivalent(get(vertex_name, graph1), get(vertex_name, graph2)); + + typedef property_map::type edge_name_map_t; + typedef property_map_equivalent edge_comp_t; + edge_comp_t edge_comp = + make_property_map_equivalent(get(edge_name, graph1), get(edge_name, graph2)); + + // Create callback + vf2_print_callback callback(graph1, graph2); + + // Print out all subgraph isomorphism mappings between graph1 and graph2. + // Function vertex_order_by_mult is used to compute the order of + // vertices of graph1. This is the order in which the vertices are examined + // during the matching process. + vf2_subgraph_iso(graph1, graph2, callback, vertex_order_by_mult(graph1), + edges_equivalent(edge_comp).vertices_equivalent(vertex_comp)); + + return 0; +} diff --git a/include/boost/graph/adj_list_serialize.hpp b/include/boost/graph/adj_list_serialize.hpp index c1ff4111d..01db50282 100644 --- a/include/boost/graph/adj_list_serialize.hpp +++ b/include/boost/graph/adj_list_serialize.hpp @@ -61,6 +61,8 @@ inline void save( ar << serialization::make_nvp("v" , indices[target(e,graph)]); ar << serialization::make_nvp("edge_property", get(edge_all_t(), graph, e) ); } + + ar << serialization::make_nvp("graph_property", get_property(graph, graph_all_t()) ); } @@ -95,6 +97,7 @@ inline void load( boost::tie(e,inserted) = add_edge(verts[u], verts[v], graph); ar >> serialization::make_nvp("edge_property", get(edge_all_t(), graph, e) ); } + ar >> serialization::make_nvp("graph_property", get_property(graph, graph_all_t()) ); } template diff --git a/include/boost/graph/adjacency_list.hpp b/include/boost/graph/adjacency_list.hpp index 5034fec5a..d7fbc06d8 100644 --- a/include/boost/graph/adjacency_list.hpp +++ b/include/boost/graph/adjacency_list.hpp @@ -51,11 +51,6 @@ namespace boost { // adjacency_list, and the container_gen traits class which is used // to map the selectors to the container type used to implement the // graph. - // - // The main container_gen traits class uses partial specialization, - // so we also include a workaround. - -#if !defined BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION #if !defined BOOST_NO_SLIST struct slistS {}; @@ -130,93 +125,6 @@ namespace boost { typedef boost::unordered_multiset type; }; -#else // !defined BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION - -#if !defined BOOST_NO_SLIST - struct slistS { - template - struct bind_ { typedef BOOST_STD_EXTENSION_NAMESPACE::slist type; }; - }; -#endif - - struct vecS { - template - struct bind_ { typedef std::vector type; }; - }; - - struct listS { - template - struct bind_ { typedef std::list type; }; - }; - - struct setS { - template - struct bind_ { typedef std::set > type; }; - }; - - - struct mapS { - template - struct bind_ { typedef std::set > type; }; - }; - - struct multisetS { - template - struct bind_ { typedef std::multiset > type; }; - }; - - struct multimapS { - template - struct bind_ { typedef std::multiset > type; }; - }; - - struct hash_setS { - template - struct bind_ { typedef boost::unordered_set type; }; - }; - - struct hash_mapS { - template - struct bind_ { typedef boost::unordered_set type; }; - }; - - struct hash_multisetS { - template - struct bind_ { typedef boost::unordered_multiset type; }; - }; - - struct hash_multimapS { - template - struct bind_ { typedef boost::unordered_multiset type; }; - }; - - template struct container_selector { - typedef vecS type; - }; - -#define BOOST_CONTAINER_SELECTOR(NAME) \ - template <> struct container_selector { \ - typedef NAME type; \ - } - - BOOST_CONTAINER_SELECTOR(vecS); - BOOST_CONTAINER_SELECTOR(listS); - BOOST_CONTAINER_SELECTOR(mapS); - BOOST_CONTAINER_SELECTOR(setS); - BOOST_CONTAINER_SELECTOR(multisetS); - BOOST_CONTAINER_SELECTOR(hash_mapS); -#if !defined BOOST_NO_SLIST - BOOST_CONTAINER_SELECTOR(slistS); -#endif - - template - struct container_gen { - typedef typename container_selector::type Select; - typedef typename Select:: template bind_::type type; - }; - -#endif // !defined BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION - template struct parallel_edge_traits { }; @@ -280,6 +188,7 @@ namespace boost { } // namespace detail + template struct is_distributed_selector: mpl::false_ {}; //=========================================================================== @@ -354,13 +263,7 @@ namespace boost { adjacency_list, VertexListS, OutEdgeListS, DirectedS, -#if !defined(BOOST_GRAPH_NO_BUNDLED_PROPERTIES) - typename detail::retag_property_list::type, - typename detail::retag_property_list::type, -#else VertexProperty, EdgeProperty, -#endif GraphProperty, EdgeListS>::type, // Support for named vertices public graph::maybe_named_graph< @@ -371,25 +274,14 @@ namespace boost { VertexProperty> { public: -#if !defined(BOOST_GRAPH_NO_BUNDLED_PROPERTIES) - typedef typename graph_detail::graph_prop::property graph_property_type; - typedef typename graph_detail::graph_prop::bundle graph_bundled; - - typedef typename graph_detail::vertex_prop::property vertex_property_type; - typedef typename graph_detail::vertex_prop::bundle vertex_bundled; - - typedef typename graph_detail::edge_prop::property edge_property_type; - typedef typename graph_detail::edge_prop::bundle edge_bundled; -#else typedef GraphProperty graph_property_type; - typedef no_graph_bundle graph_bundled; + typedef typename lookup_one_property::type graph_bundled; typedef VertexProperty vertex_property_type; - typedef no_vertex_bundle vertex_bundled; + typedef typename lookup_one_property::type vertex_bundled; typedef EdgeProperty edge_property_type; - typedef no_edge_bundle edge_bundled; -#endif + typedef typename lookup_one_property::type edge_bundled; private: typedef adjacency_list self; @@ -437,7 +329,6 @@ namespace boost { : Base(num_vertices), m_property(new graph_property_type(p)) { } -#if !defined(BOOST_MSVC) || BOOST_MSVC >= 1300 // Required by Iterator Constructible Graph template adjacency_list(EdgeIterator first, EdgeIterator last, @@ -455,7 +346,6 @@ namespace boost { const GraphProperty& p = GraphProperty()) : Base(n, first, last, ep_iter), m_property(new graph_property_type(p)) { } -#endif void swap(adjacency_list& x) { // Is there a more efficient way to do this? @@ -502,20 +392,20 @@ namespace boost { #define ADJLIST adjacency_list template - inline void set_property(ADJLIST& g, Tag, Value const& value) { - get_property_value(*g.m_property, Tag()) = value; + inline void set_property(ADJLIST& g, Tag tag, Value const& value) { + get_property_value(*g.m_property, tag) = value; } template inline typename graph_property::type& - get_property(ADJLIST& g, Tag) { - return get_property_value(*g.m_property, Tag()); + get_property(ADJLIST& g, Tag tag) { + return get_property_value(*g.m_property, tag); } template inline typename graph_property::type const& - get_property(ADJLIST const& g, Tag) { - return get_property_value(*g.m_property, Tag()); + get_property(ADJLIST const& g, Tag tag) { + return get_property_value(*g.m_property, tag); } // dwa 09/25/00 - needed to be more explicit so reverse_graph would work. @@ -545,58 +435,6 @@ namespace boost { return e.m_target; } - // Support for bundled properties -#ifndef BOOST_GRAPH_NO_BUNDLED_PROPERTIES - template - inline - typename property_map, T Bundle::*>::type - get(T Bundle::* p, adjacency_list& g) - { - typedef typename property_map, T Bundle::*>::type - result_type; - return result_type(&g, p); - } - - template - inline - typename property_map, T Bundle::*>::const_type - get(T Bundle::* p, adjacency_list const & g) - { - typedef typename property_map, T Bundle::*>::const_type - result_type; - return result_type(&g, p); - } - - template - inline T - get(T Bundle::* p, adjacency_list const & g, const Key& key) - { - return get(get(p, g), key); - } - - template - inline void - put(T Bundle::* p, adjacency_list& g, const Key& key, const T& value) - { - put(get(p, g), key, value); - } - -#endif - // Mutability Traits template struct graph_mutability_traits { diff --git a/include/boost/graph/adjacency_list_io.hpp b/include/boost/graph/adjacency_list_io.hpp index 91b0b465d..aaba8a43c 100644 --- a/include/boost/graph/adjacency_list_io.hpp +++ b/include/boost/graph/adjacency_list_io.hpp @@ -40,7 +40,7 @@ namespace boost { template std::istream& operator >> ( std::istream& in, property& p ) { - in >> p.m_value >> *(static_cast(&p)); // houpla !! + in >> p.m_value >> p.m_base; // houpla !! return in; } @@ -65,7 +65,7 @@ template void get ( property& p, const V& v, Stag s ) { - get( *(static_cast(&p)),v,s ); + get( p.m_base,v,s ); } template @@ -82,7 +82,7 @@ void getSubset ( property& p, const property& s ) { get( p, s.m_value, Stag() ); - getSubset( p, Snext(s) ); + getSubset( p, s.m_base ); } template PropertyPrinter& operator () ( std::ostream& out, const Val& v ) { - typename property_map::type ps = get(Tag(), *graph); + typename property_map::const_type ps = get(Tag(), *graph); out << ps[ v ] <<" "; PropertyPrinter print(*graph); print(out, v); @@ -248,7 +248,7 @@ struct PropertyPrinter > template PropertyPrinter& operator () ( std::ostream& out, const Val& v ) { - typename property_map::type ps = get(Tag(), *graph); + typename property_map::const_type ps = get(Tag(), *graph); out << ps[ v ] <<" "; PropertyPrinter print(*graph); print(out, v); diff --git a/include/boost/graph/adjacency_matrix.hpp b/include/boost/graph/adjacency_matrix.hpp index 6fb1f4865..b1078d977 100644 --- a/include/boost/graph/adjacency_matrix.hpp +++ b/include/boost/graph/adjacency_matrix.hpp @@ -14,13 +14,14 @@ #include #include #include -#include +#include #include #include #include #include #include #include +#include #include #include #include @@ -29,7 +30,10 @@ #include #include #include -#include +#include +#include +#include +#include namespace boost { @@ -439,9 +443,7 @@ namespace boost { // graph type. Instead, use directedS, which also provides the // functionality required for a Bidirectional Graph (in_edges, // in_degree, etc.). -#if !defined(_MSC_VER) || _MSC_VER > 1300 BOOST_STATIC_ASSERT(type_traits::ice_not<(is_same::value)>::value); -#endif typedef typename mpl::if_::type @@ -476,41 +478,27 @@ namespace boost { typedef adjacency_matrix_traits Traits; public: -#if !defined(BOOST_MSVC) || BOOST_MSVC > 1300 // The bidirectionalS tag is not allowed with the adjacency_matrix // graph type. Instead, use directedS, which also provides the // functionality required for a Bidirectional Graph (in_edges, // in_degree, etc.). BOOST_STATIC_ASSERT(!(is_same::value)); -#endif - -#if !defined(BOOST_GRAPH_NO_BUNDLED_PROPERTIES) - typedef typename graph_detail::graph_prop::property graph_property_type; - typedef typename graph_detail::graph_prop::bundle graph_bundled; - - typedef typename graph_detail::vertex_prop::property vertex_property_type; - typedef typename graph_detail::vertex_prop::bundle vertex_bundled; - typedef typename graph_detail::edge_prop::property edge_property_type; - typedef typename graph_detail::edge_prop::bundle edge_bundled; -#else typedef GraphProperty graph_property_type; - typedef no_graph_bundle graph_bundled; + typedef typename lookup_one_property::type graph_bundled; typedef VertexProperty vertex_property_type; - typedef no_vertex_bundle vertex_bundled; + typedef typename lookup_one_property::type vertex_bundled; typedef EdgeProperty edge_property_type; - typedef no_edge_bundle edge_bundled; -#endif + typedef typename lookup_one_property::type edge_bundled; public: // should be private typedef typename mpl::if_::type, std::pair, char>::type StoredEdge; -#if (defined(BOOST_MSVC) && BOOST_MSVC <= 1300) || defined(BOOST_NO_STD_ALLOCATOR) +#if defined(BOOST_NO_STD_ALLOCATOR) typedef std::vector Matrix; #else - // This causes internal compiler error for MSVC typedef typename Allocator::template rebind::other Alloc; typedef std::vector Matrix; #endif @@ -640,16 +628,16 @@ namespace boost { #ifndef BOOST_GRAPH_NO_BUNDLED_PROPERTIES // Directly access a vertex or edge bundle vertex_bundled& operator[](vertex_descriptor v) - { return get(vertex_bundle, *this)[v]; } + { return get(vertex_bundle, *this, v); } const vertex_bundled& operator[](vertex_descriptor v) const - { return get(vertex_bundle, *this)[v]; } + { return get(vertex_bundle, *this, v); } edge_bundled& operator[](edge_descriptor e) - { return get(edge_bundle, *this)[e]; } + { return get(edge_bundle, *this, e); } const edge_bundled& operator[](edge_descriptor e) const - { return get(edge_bundle, *this)[e]; } + { return get(edge_bundle, *this, e); } graph_bundled& operator[](graph_bundle_t) { return get_property(*this); } @@ -982,7 +970,7 @@ namespace boost { inline typename adjacency_matrix::vertex_descriptor add_vertex(adjacency_matrix& g) { // UNDER CONSTRUCTION - assert(false); + BOOST_ASSERT(false); return *vertices(g).first; } @@ -991,7 +979,7 @@ namespace boost { inline typename adjacency_matrix::vertex_descriptor add_vertex(const VP2& /*vp*/, adjacency_matrix& g) { // UNDER CONSTRUCTION - assert(false); + BOOST_ASSERT(false); return *vertices(g).first; } @@ -1001,7 +989,7 @@ namespace boost { adjacency_matrix& /*g*/) { // UNDER CONSTRUCTION - assert(false); + BOOST_ASSERT(false); } // O(V) @@ -1035,326 +1023,211 @@ namespace boost { //========================================================================= // Functions required by the PropertyGraph concept - // O(1) - template - inline void - set_property(adjacency_matrix& g, Tag, const Value& value) - { - get_property_value(g.m_property, Tag()) = value; - } - template - inline typename graph_property, Tag>::type& - get_property(adjacency_matrix& g, Tag) - { - return get_property_value(g.m_property, Tag()); - } + typename Prop, typename Kind> + struct adj_mat_pm_helper; template - inline const typename graph_property, Tag>::type& - get_property(const adjacency_matrix& g, Tag) - { - return get_property_value(g.m_property, Tag()); - } + typename Prop> + struct adj_mat_pm_helper { + typedef typename graph_traits >::vertex_descriptor arg_type; + typedef typed_identity_property_map vi_map_type; + typedef iterator_property_map::iterator, vi_map_type> all_map_type; + typedef iterator_property_map::const_iterator, vi_map_type> all_map_const_type; + typedef transform_value_property_map< + detail::lookup_one_property_f, + all_map_type> + type; + typedef transform_value_property_map< + detail::lookup_one_property_f, + all_map_const_type> + const_type; + typedef typename property_traits::reference single_nonconst_type; + typedef typename property_traits::reference single_const_type; + + static type get_nonconst(adjacency_matrix& g, Prop prop) { + return type(prop, all_map_type(g.m_vertex_properties.begin(), vi_map_type())); + } - //========================================================================= - // Vertex Property Map + static const_type get_const(const adjacency_matrix& g, Prop prop) { + return const_type(prop, all_map_const_type(g.m_vertex_properties.begin(), vi_map_type())); + } - template - class adj_matrix_vertex_property_map - : public put_get_helper > - { - public: - typedef T value_type; - typedef R reference; - typedef Vertex key_type; - typedef boost::lvalue_property_map_tag category; - adj_matrix_vertex_property_map() { } - adj_matrix_vertex_property_map(GraphPtr g) : m_g(g) { } - inline reference operator[](key_type v) const { - return get_property_value(m_g->m_vertex_properties[v], Tag()); + static single_nonconst_type get_nonconst_one(adjacency_matrix& g, Prop prop, arg_type v) { + return lookup_one_property::lookup(g.m_vertex_properties[v], prop); } - GraphPtr m_g; - }; - template - struct adj_matrix_vertex_id_map - : public boost::put_get_helper > - { - typedef Vertex value_type; - typedef Vertex reference; - typedef Vertex key_type; - typedef boost::readable_property_map_tag category; - adj_matrix_vertex_id_map() { } - template - inline adj_matrix_vertex_id_map(const Graph&) { } - inline value_type operator[](key_type v) const { return v; } + static single_const_type get_const_one(const adjacency_matrix& g, Prop prop, arg_type v) { + return lookup_one_property::lookup(g.m_vertex_properties[v], prop); + } }; - namespace detail { - - struct adj_matrix_any_vertex_pa { - template - struct bind_ { - typedef typename property_value::type Value; - typedef typename boost::graph_traits::vertex_descriptor Vertex; - - typedef adj_matrix_vertex_property_map type; - typedef adj_matrix_vertex_property_map const_type; - }; - }; - struct adj_matrix_id_vertex_pa { - template - struct bind_ { - typedef typename Graph::vertex_descriptor Vertex; - typedef adj_matrix_vertex_id_map type; - typedef adj_matrix_vertex_id_map const_type; - }; - }; - - template - struct adj_matrix_choose_vertex_pa_helper { - typedef adj_matrix_any_vertex_pa type; - }; - template <> - struct adj_matrix_choose_vertex_pa_helper { - typedef adj_matrix_id_vertex_pa type; - }; - - template - struct adj_matrix_choose_vertex_pa { - typedef typename adj_matrix_choose_vertex_pa_helper::type Helper; - typedef typename Helper::template bind_ Bind; - typedef typename Bind::type type; - typedef typename Bind::const_type const_type; - }; - - struct adj_matrix_vertex_property_selector { - template - struct bind_ { - typedef adj_matrix_choose_vertex_pa Choice; - typedef typename Choice::type type; - typedef typename Choice::const_type const_type; - }; + template + struct adj_mat_pm_helper { + typedef typename graph_traits >::edge_descriptor edge_descriptor; + + template + struct lookup_property_from_edge { + Tag tag; + lookup_property_from_edge(Tag tag): tag(tag) {} + typedef typename boost::mpl::if_::type ep_type_nonref; + typedef ep_type_nonref& ep_type; + typedef typename lookup_one_property::type& result_type; + result_type operator()(edge_descriptor e) const { + return lookup_one_property::lookup(*static_cast(e.get_property()), tag); + } }; - } // namespace detail - - template <> - struct vertex_property_selector { - typedef detail::adj_matrix_vertex_property_selector type; - }; + typedef function_property_map< + lookup_property_from_edge, + typename graph_traits >::edge_descriptor> type; + typedef function_property_map< + lookup_property_from_edge, + typename graph_traits >::edge_descriptor> const_type; + typedef edge_descriptor arg_type; + typedef typename lookup_property_from_edge::result_type single_nonconst_type; + typedef typename lookup_property_from_edge::result_type single_const_type; + + static type get_nonconst(adjacency_matrix& g, Tag tag) { + return type(tag); + } - //========================================================================= - // Edge Property Map + static const_type get_const(const adjacency_matrix& g, Tag tag) { + return const_type(tag); + } + static single_nonconst_type get_nonconst_one(adjacency_matrix& g, Tag tag, edge_descriptor e) { + return lookup_one_property::lookup(*static_cast(e.get_property()), tag); + } - template - class adj_matrix_edge_property_map - : public put_get_helper > - { - public: - typedef T value_type; - typedef R reference; - typedef detail::matrix_edge_desc_impl key_type; - typedef boost::lvalue_property_map_tag category; - inline reference operator[](key_type e) const { - Property& p = *(Property*)e.get_property(); - return get_property_value(p, Tag()); + static single_const_type get_const_one(const adjacency_matrix& g, Tag tag, edge_descriptor e) { + return lookup_one_property::lookup(*static_cast(e.get_property()), tag); } }; - struct adj_matrix_edge_property_selector { - template - struct bind_ { - typedef typename property_value::type T; - typedef typename Graph::vertex_descriptor Vertex; - typedef adj_matrix_edge_property_map type; - typedef adj_matrix_edge_property_map const_type; - }; - }; - template <> - struct edge_property_selector { - typedef adj_matrix_edge_property_selector type; - }; - //========================================================================= - // Functions required by PropertyGraph + template + struct property_map, Tag> + : adj_mat_pm_helper, Tag>::type> {}; - namespace detail { + template + typename property_map, Tag>::type + get(Tag tag, adjacency_matrix& g) { + return property_map, Tag>::get_nonconst(g, tag); + } - template - typename boost::property_map, - Property>::type - get_dispatch(adjacency_matrix& g, Property, - vertex_property_tag) - { - typedef adjacency_matrix Graph; - typedef typename boost::property_map, - Property>::type PA; - return PA(&g); - } - template - typename boost::property_map, - Property>::type - get_dispatch(adjacency_matrix&, Property, - edge_property_tag) - { - typedef typename boost::property_map, - Property>::type PA; - return PA(); - } - template - typename boost::property_map, - Property>::const_type - get_dispatch(const adjacency_matrix& g, Property, - vertex_property_tag) - { - typedef adjacency_matrix Graph; - typedef typename boost::property_map, - Property>::const_type PA; - return PA(&g); - } - template - typename boost::property_map, - Property>::const_type - get_dispatch(const adjacency_matrix&, Property, - edge_property_tag) - { - typedef typename boost::property_map, - Property>::const_type PA; - return PA(); - } + template + typename property_map, Tag>::const_type + get(Tag tag, const adjacency_matrix& g) { + return property_map, Tag>::get_const(g, tag); + } - } // namespace detail + template + typename property_map, Tag>::single_nonconst_type + get(Tag tag, adjacency_matrix& g, typename property_map, Tag>::arg_type a) { + return property_map, Tag>::get_nonconst_one(g, tag, a); + } - template - inline - typename property_map, Property>::type - get(Property p, adjacency_matrix& g) - { - typedef typename property_kind::type Kind; - return detail::get_dispatch(g, p, Kind()); + template + typename property_map, Tag>::single_const_type + get(Tag tag, const adjacency_matrix& g, typename property_map, Tag>::arg_type a) { + return property_map, Tag>::get_const_one(g, tag, a); + } + + template + void + put(Tag tag, + adjacency_matrix& g, + typename property_map, Tag>::arg_type a, + typename property_map, Tag>::single_const_type val) { + property_map, Tag>::get_nonconst_one(g, tag, a) = val; } - template - inline - typename property_map, Property>::const_type - get(Property p, const adjacency_matrix& g) + // O(1) + template + inline void + set_property(adjacency_matrix& g, Tag tag, const Value& value) { - typedef typename property_kind::type Kind; - return detail::get_dispatch(g, p, Kind()); + get_property_value(g.m_property, tag) = value; } - template - inline - typename property_traits< - typename property_map, Property>::const_type - >::value_type - get(Property p, const adjacency_matrix& g, - const Key& key) + template + inline typename graph_property, Tag>::type& + get_property(adjacency_matrix& g, Tag tag) { - return get(get(p, g), key); + return get_property_value(g.m_property, tag); } - template - inline void - put(Property p, adjacency_matrix& g, - const Key& key, const Value& value) + template + inline const typename graph_property, Tag>::type& + get_property(const adjacency_matrix& g, Tag tag) { - typedef adjacency_matrix Graph; - typedef typename boost::property_map::type Map; - Map pmap = get(p, g); - put(pmap, key, value); + return get_property_value(g.m_property, tag); } //========================================================================= - // Other Functions + // Vertex Property Map template - typename adjacency_matrix::vertex_descriptor - vertex(typename adjacency_matrix::vertices_size_type n, - const adjacency_matrix&) - { - return n; + struct property_map, vertex_index_t> { + typedef typename adjacency_matrix::vertex_descriptor Vertex; + typedef typed_identity_property_map type; + typedef type const_type; + }; + + template + typename property_map, vertex_index_t>::const_type + get(vertex_index_t, adjacency_matrix&) { + return typename property_map, vertex_index_t>::const_type(); } - // Support for bundled properties -#ifndef BOOST_GRAPH_NO_BUNDLED_PROPERTIES - template - inline - typename property_map, - T Bundle::*>::type - get(T Bundle::* p, adjacency_matrix& g) - { - typedef typename property_map, - T Bundle::*>::type - result_type; - return result_type(&g, p); + template + typename adjacency_matrix::vertex_descriptor + get(vertex_index_t, + adjacency_matrix&, + typename adjacency_matrix::vertex_descriptor v) { + return v; } - template - inline - typename property_map, - T Bundle::*>::const_type - get(T Bundle::* p, adjacency_matrix const & g) - { - typedef typename property_map, - T Bundle::*>::const_type - result_type; - return result_type(&g, p); + template + typename property_map, vertex_index_t>::const_type + get(vertex_index_t, const adjacency_matrix&) { + return typename property_map, vertex_index_t>::const_type(); } - template - inline T - get(T Bundle::* p, adjacency_matrix const & g, - const Key& key) - { - return get(get(p, g), key); + template + typename adjacency_matrix::vertex_descriptor + get(vertex_index_t, + const adjacency_matrix&, + typename adjacency_matrix::vertex_descriptor v) { + return v; } - template - inline void - put(T Bundle::* p, adjacency_matrix& g, - const Key& key, const T& value) + //========================================================================= + // Other Functions + + template + typename adjacency_matrix::vertex_descriptor + vertex(typename adjacency_matrix::vertices_size_type n, + const adjacency_matrix&) { - put(get(p, g), key, value); + return n; } -#endif - -#define ADJMAT_PARAMS \ - typename D, typename VP, typename EP, typename GP, typename A -#define ADJMAT adjacency_matrix -template -struct graph_mutability_traits { - typedef mutable_edge_property_graph_tag category; +template +struct graph_mutability_traits > { + typedef mutable_edge_property_graph_tag category; }; -#undef ADJMAT_PARAMS -#undef ADJMAT } // namespace boost diff --git a/include/boost/graph/astar_search.hpp b/include/boost/graph/astar_search.hpp index ae60113da..435ccf03b 100644 --- a/include/boost/graph/astar_search.hpp +++ b/include/boost/graph/astar_search.hpp @@ -22,10 +22,13 @@ #include #include #include +#include #include +#include #include #include - +#include +#include namespace boost { @@ -34,7 +37,7 @@ namespace boost { struct AStarHeuristicConcept { void constraints() { - function_requires< CopyConstructibleConcept >(); + BOOST_CONCEPT_ASSERT(( CopyConstructibleConcept )); h(u); } Heuristic h; @@ -58,7 +61,7 @@ namespace boost { struct AStarVisitorConcept { void constraints() { - function_requires< CopyConstructibleConcept >(); + BOOST_CONCEPT_ASSERT(( CopyConstructibleConcept )); vis.initialize_vertex(u, g); vis.discover_vertex(u, g); vis.examine_vertex(u, g); @@ -158,8 +161,10 @@ namespace boost { template void tree_edge(Edge e, const Graph& g) { - m_decreased = relax(e, g, m_weight, m_predecessor, m_distance, - m_combine, m_compare); + using boost::get; + bool m_decreased = + relax(e, g, m_weight, m_predecessor, m_distance, + m_combine, m_compare); if(m_decreased) { m_vis.edge_relaxed(e, g); @@ -173,8 +178,10 @@ namespace boost { template void gray_target(Edge e, const Graph& g) { - m_decreased = relax(e, g, m_weight, m_predecessor, m_distance, - m_combine, m_compare); + using boost::get; + bool m_decreased = + relax(e, g, m_weight, m_predecessor, m_distance, + m_combine, m_compare); if(m_decreased) { put(m_cost, target(e, g), @@ -189,8 +196,10 @@ namespace boost { template void black_target(Edge e, const Graph& g) { - m_decreased = relax(e, g, m_weight, m_predecessor, m_distance, - m_combine, m_compare); + using boost::get; + bool m_decreased = + relax(e, g, m_weight, m_predecessor, m_distance, + m_combine, m_compare); if(m_decreased) { m_vis.edge_relaxed(e, g); @@ -216,7 +225,6 @@ namespace boost { ColorMap m_color; BinaryFunction m_combine; BinaryPredicate m_compare; - bool m_decreased; C m_zero; }; @@ -260,6 +268,77 @@ namespace boost { breadth_first_visit(g, s, Q, bfs_vis, color); } + namespace graph_detail { + template + struct select1st { + typedef std::pair argument_type; + typedef A result_type; + A operator()(const std::pair& p) const {return p.first;} + }; + } + + template + inline void + astar_search_no_init_tree + (const VertexListGraph &g, + typename graph_traits::vertex_descriptor s, + AStarHeuristic h, AStarVisitor vis, + PredecessorMap predecessor, CostMap cost, + DistanceMap distance, WeightMap weight, + CompareFunction compare, CombineFunction combine, + CostInf /*inf*/, CostZero zero) + { + typedef typename graph_traits::vertex_descriptor + Vertex; + typedef typename property_traits::value_type Distance; + typedef d_ary_heap_indirect< + std::pair, + 4, + null_property_map, std::size_t>, + function_property_map, std::pair >, + CompareFunction> + MutableQueue; + MutableQueue Q( + make_function_property_map >(graph_detail::select1st()), + null_property_map, std::size_t>(), + compare); + + vis.discover_vertex(s, g); + Q.push(std::make_pair(get(cost, s), s)); + while (!Q.empty()) { + Vertex v; + Distance v_rank; + boost::tie(v_rank, v) = Q.top(); + Q.pop(); + vis.examine_vertex(v, g); + BGL_FORALL_OUTEDGES_T(v, e, g, VertexListGraph) { + Vertex w = target(e, g); + vis.examine_edge(e, g); + Distance e_weight = get(weight, e); + if (compare(e_weight, zero)) + BOOST_THROW_EXCEPTION(negative_edge()); + bool decreased = + relax(e, g, weight, predecessor, distance, + combine, compare); + Distance w_d = combine(get(distance, v), e_weight); + if (decreased) { + vis.edge_relaxed(e, g); + Distance w_rank = combine(get(distance, w), h(w)); + put(cost, w, w_rank); + vis.discover_vertex(w, g); + Q.push(std::make_pair(w_rank, w)); + } else { + vis.edge_not_relaxed(e, g); + } + } + vis.finish_vertex(v, g); + } + } // Non-named parameter interface template + inline void + astar_search_tree + (const VertexListGraph &g, + typename graph_traits::vertex_descriptor s, + AStarHeuristic h, AStarVisitor vis, + PredecessorMap predecessor, CostMap cost, + DistanceMap distance, WeightMap weight, + CompareFunction compare, CombineFunction combine, + CostInf inf, CostZero zero) + { + + typename graph_traits::vertex_iterator ui, ui_end; + for (boost::tie(ui, ui_end) = vertices(g); ui != ui_end; ++ui) { + put(distance, *ui, inf); + put(cost, *ui, inf); + put(predecessor, *ui, *ui); + vis.initialize_vertex(*ui, g); + } + put(distance, s, zero); + put(cost, s, h(s)); + + astar_search_no_init_tree + (g, s, h, vis, predecessor, cost, distance, weight, + compare, combine, inf, zero); + + } + // Named parameter interfaces template ::map_type distance_map_type; typedef typename boost::property_traits::value_type D; + const D inf = arg_pack[_distance_inf || detail::get_max()]; astar_search (g, s, h, @@ -336,8 +450,48 @@ namespace boost { detail::override_const_property(arg_pack, _vertex_index_map, g, vertex_index), detail::make_color_map_from_arg_pack(g, arg_pack), arg_pack[_distance_compare | std::less()], - arg_pack[_distance_combine | closed_plus()], - arg_pack[_distance_inf | (std::numeric_limits::max)()], + arg_pack[_distance_combine | closed_plus(inf)], + inf, + arg_pack[_distance_zero | D()]); + } + + // Named parameter interfaces + template + void + astar_search_tree + (const VertexListGraph &g, + typename graph_traits::vertex_descriptor s, + AStarHeuristic h, const bgl_named_params& params) + { + using namespace boost::graph::keywords; + typedef bgl_named_params params_type; + BOOST_GRAPH_DECLARE_CONVERTED_PARAMETERS(params_type, params) + + // Distance type is the value type of the distance map if there is one, + // otherwise the value type of the weight map. + typedef + typename detail::override_const_property_result< + arg_pack_type, tag::weight_map, edge_weight_t, VertexListGraph>::type + weight_map_type; + typedef typename boost::property_traits::value_type W; + typedef + typename detail::map_maker::map_type + distance_map_type; + typedef typename boost::property_traits::value_type D; + const D inf = arg_pack[_distance_inf || detail::get_max()]; + + astar_search_tree + (g, s, h, + arg_pack[_visitor | make_astar_visitor(null_visitor())], + arg_pack[_predecessor_map | dummy_property_map()], + detail::make_property_map_from_arg_pack_gen(D())(g, arg_pack), + detail::make_property_map_from_arg_pack_gen(W())(g, arg_pack), + detail::override_const_property(arg_pack, _weight_map, g, edge_weight), + arg_pack[_distance_compare | std::less()], + arg_pack[_distance_combine | closed_plus(inf)], + inf, arg_pack[_distance_zero | D()]); } @@ -358,6 +512,7 @@ namespace boost { arg_pack_type, tag::weight_map, edge_weight_t, VertexListGraph>::type weight_map_type; typedef typename boost::property_traits::value_type D; + const D inf = arg_pack[_distance_inf || detail::get_max()]; astar_search_no_init (g, s, h, arg_pack[_visitor | make_astar_visitor(null_visitor())], @@ -365,11 +520,42 @@ namespace boost { detail::make_property_map_from_arg_pack_gen(D())(g, arg_pack), detail::make_property_map_from_arg_pack_gen(D())(g, arg_pack), detail::override_const_property(arg_pack, _weight_map, g, edge_weight), - detail::override_const_property(arg_pack, _vertex_index_map, g, vertex_index), detail::make_color_map_from_arg_pack(g, arg_pack), + detail::override_const_property(arg_pack, _vertex_index_map, g, vertex_index), + arg_pack[_distance_compare | std::less()], + arg_pack[_distance_combine | closed_plus(inf)], + inf, + arg_pack[_distance_zero | D()]); + } + + template + void + astar_search_no_init_tree + (const VertexListGraph &g, + typename graph_traits::vertex_descriptor s, + AStarHeuristic h, const bgl_named_params& params) + { + using namespace boost::graph::keywords; + typedef bgl_named_params params_type; + BOOST_GRAPH_DECLARE_CONVERTED_PARAMETERS(params_type, params) + typedef + typename detail::override_const_property_result< + arg_pack_type, tag::weight_map, edge_weight_t, VertexListGraph>::type + weight_map_type; + typedef typename boost::property_traits::value_type D; + const D inf = arg_pack[_distance_inf || detail::get_max()]; + astar_search_no_init_tree + (g, s, h, + arg_pack[_visitor | make_astar_visitor(null_visitor())], + arg_pack[_predecessor_map | dummy_property_map()], + detail::make_property_map_from_arg_pack_gen(D())(g, arg_pack), + detail::make_property_map_from_arg_pack_gen(D())(g, arg_pack), + detail::override_const_property(arg_pack, _weight_map, g, edge_weight), arg_pack[_distance_compare | std::less()], - arg_pack[_distance_combine | closed_plus()], - arg_pack[_distance_inf | (std::numeric_limits::max)()], + arg_pack[_distance_combine | closed_plus(inf)], + inf, arg_pack[_distance_zero | D()]); } diff --git a/include/boost/graph/bandwidth.hpp b/include/boost/graph/bandwidth.hpp index 0bfeefb99..e8e7bf2cf 100644 --- a/include/boost/graph/bandwidth.hpp +++ b/include/boost/graph/bandwidth.hpp @@ -21,15 +21,14 @@ namespace boost { VertexIndexMap index) { BOOST_USING_STD_MAX(); - typedef typename graph_traits::vertices_size_type size_type; - size_type b = 0; + using std::abs; + typedef typename graph_traits::vertices_size_type vertices_size_type; + vertices_size_type b = 0; typename graph_traits::out_edge_iterator e, end; for (boost::tie(e, end) = out_edges(i, g); e != end; ++e) { int f_i = get(index, i); int f_j = get(index, target(*e, g)); - using namespace std; // to call abs() unqualified - if(f_i > f_j) - b = max BOOST_PREVENT_MACRO_SUBSTITUTION (b, size_type(f_i - f_j)); + b = max BOOST_PREVENT_MACRO_SUBSTITUTION (b, vertices_size_type(abs(f_i - f_j))); } return b; } @@ -47,10 +46,15 @@ namespace boost { bandwidth(const Graph& g, VertexIndexMap index) { BOOST_USING_STD_MAX(); - typename graph_traits::vertices_size_type b = 0; - typename graph_traits::vertex_iterator i, end; - for (boost::tie(i, end) = vertices(g); i != end; ++i) - b = max BOOST_PREVENT_MACRO_SUBSTITUTION (b, ith_bandwidth(*i, g, index)); + using std::abs; + typedef typename graph_traits::vertices_size_type vertices_size_type; + vertices_size_type b = 0; + typename graph_traits::edge_iterator i, end; + for (boost::tie(i, end) = edges(g); i != end; ++i) { + int f_i = get(index, source(*i, g)); + int f_j = get(index, target(*i, g)); + b = max BOOST_PREVENT_MACRO_SUBSTITUTION (b, vertices_size_type(abs(f_i - f_j))); + } return b; } diff --git a/include/boost/graph/bellman_ford_shortest_paths.hpp b/include/boost/graph/bellman_ford_shortest_paths.hpp index 8fc02529a..7873067a1 100644 --- a/include/boost/graph/bellman_ford_shortest_paths.hpp +++ b/include/boost/graph/bellman_ford_shortest_paths.hpp @@ -29,13 +29,14 @@ #include #include #include +#include namespace boost { template struct BellmanFordVisitorConcept { void constraints() { - function_requires< CopyConstructibleConcept >(); + BOOST_CONCEPT_ASSERT(( CopyConstructibleConcept )); vis.examine_edge(e, g); vis.edge_relaxed(e, g); vis.edge_not_relaxed(e, g); @@ -95,14 +96,12 @@ namespace boost { BinaryPredicate compare, BellmanFordVisitor v) { - function_requires >(); + BOOST_CONCEPT_ASSERT(( EdgeListGraphConcept )); typedef graph_traits GTraits; typedef typename GTraits::edge_descriptor Edge; typedef typename GTraits::vertex_descriptor Vertex; - function_requires >(); - function_requires >(); - typedef typename property_traits::value_type D_value; - typedef typename property_traits::value_type W_value; + BOOST_CONCEPT_ASSERT(( ReadWritePropertyMapConcept )); + BOOST_CONCEPT_ASSERT(( ReadablePropertyMapConcept )); typename GTraits::edge_iterator i, end; @@ -170,7 +169,7 @@ namespace boost { bool bellman_dispatch2 (VertexAndEdgeListGraph& g, - detail::error_property_not_found, + param_not_found, Size N, WeightMap weight, PredecessorMap pred, DistanceMap distance, const bgl_named_params& params) { @@ -229,7 +228,7 @@ namespace boost { (VertexAndEdgeListGraph& g, const bgl_named_params& params) { - function_requires >(); + BOOST_CONCEPT_ASSERT(( VertexListGraphConcept )); return detail::bellman_dispatch (g, num_vertices(g), choose_const_pmap(get_param(params, edge_weight), g, edge_weight), diff --git a/include/boost/graph/betweenness_centrality.hpp b/include/boost/graph/betweenness_centrality.hpp index 052f0633c..d596d5a28 100644 --- a/include/boost/graph/betweenness_centrality.hpp +++ b/include/boost/graph/betweenness_centrality.hpp @@ -296,7 +296,6 @@ namespace detail { namespace graph { ShortestPaths shortest_paths) { typedef typename graph_traits::vertex_iterator vertex_iterator; - typedef typename graph_traits::edge_iterator edge_iterator; typedef typename graph_traits::vertex_descriptor vertex_descriptor; // Initialize centrality @@ -421,7 +420,6 @@ namespace detail { namespace graph { VertexIndexMap vertex_index) { typedef typename graph_traits::degree_size_type degree_size_type; - typedef typename graph_traits::vertex_descriptor vertex_descriptor; typedef typename graph_traits::edge_descriptor edge_descriptor; typedef typename mpl::if_c<(is_same::value), @@ -457,7 +455,6 @@ namespace detail { namespace graph { VertexIndexMap vertex_index) { typedef typename graph_traits::degree_size_type degree_size_type; - typedef typename graph_traits::vertex_descriptor vertex_descriptor; typedef typename graph_traits::edge_descriptor edge_descriptor; typedef typename mpl::if_c<(is_same::value), @@ -498,14 +495,14 @@ namespace detail { namespace graph { }; template<> - struct brandes_betweenness_centrality_dispatch1 + struct brandes_betweenness_centrality_dispatch1 { template static void run(const Graph& g, CentralityMap centrality, EdgeCentralityMap edge_centrality_map, VertexIndexMap vertex_index, - error_property_not_found) + param_not_found) { brandes_betweenness_centrality_dispatch2(g, centrality, edge_centrality_map, vertex_index); @@ -532,7 +529,7 @@ brandes_betweenness_centrality(const Graph& g, { typedef bgl_named_params named_params; - typedef typename property_value::type ew; + typedef typename get_param_type::type ew; detail::graph::brandes_betweenness_centrality_dispatch1::run( g, choose_param(get_param(params, vertex_centrality), diff --git a/include/boost/graph/biconnected_components.hpp b/include/boost/graph/biconnected_components.hpp index 034596364..1669f6952 100644 --- a/include/boost/graph/biconnected_components.hpp +++ b/include/boost/graph/biconnected_components.hpp @@ -20,6 +20,8 @@ #include #include #include +#include +#include namespace boost { @@ -27,27 +29,35 @@ namespace boost { template struct biconnected_components_visitor : public dfs_visitor<> { biconnected_components_visitor - (ComponentMap comp, std::size_t& c, DiscoverTimeMap dtm, + (ComponentMap comp, std::size_t& c, + std::size_t& children_of_root, DiscoverTimeMap dtm, std::size_t& dfs_time, LowPointMap lowpt, PredecessorMap pred, - OutputIterator out, Stack& S, DFSVisitor vis) - : comp(comp), c(c), dtm(dtm), dfs_time(dfs_time), lowpt(lowpt), - pred(pred), out(out), S(S), vis(vis) { } + OutputIterator out, Stack& S, + ArticulationVector& is_articulation_point, IndexMap index_map, + DFSVisitor vis) + : comp(comp), c(c), children_of_root(children_of_root), + dtm(dtm), dfs_time(dfs_time), lowpt(lowpt), + pred(pred), out(out), S(S), + is_articulation_point(is_articulation_point), + index_map(index_map), vis(vis) { } template void initialize_vertex(const Vertex& u, Graph& g) { + put(pred, u, u); vis.initialize_vertex(u, g); } template void start_vertex(const Vertex& u, Graph& g) { - put(pred, u, u); + children_of_root = 0; vis.start_vertex(u, g); } @@ -68,8 +78,14 @@ namespace boost template void tree_edge(const Edge& e, Graph& g) { + typename boost::graph_traits::vertex_descriptor src = source(e, g); + typename boost::graph_traits::vertex_descriptor tgt = target(e, g); + S.push(e); - put(pred, target(e, g), source(e, g)); + put(pred, tgt, src); + if ( get(pred, src) == src ) { + ++children_of_root; + } vis.tree_edge(e, g); } @@ -78,11 +94,13 @@ namespace boost { BOOST_USING_STD_MIN(); - if ( target(e, g) != get(pred, source(e, g)) ) { + typename boost::graph_traits::vertex_descriptor src = source(e, g); + typename boost::graph_traits::vertex_descriptor tgt = target(e, g); + if ( tgt != get(pred, src) ) { S.push(e); - put(lowpt, source(e, g), - min BOOST_PREVENT_MACRO_SUBSTITUTION(get(lowpt, source(e, g)), - get(dtm, target(e, g)))); + put(lowpt, src, + min BOOST_PREVENT_MACRO_SUBSTITUTION(get(lowpt, src), + get(dtm, tgt))); } vis.back_edge(e, g); } @@ -98,55 +116,42 @@ namespace boost { BOOST_USING_STD_MIN(); Vertex parent = get(pred, u); - const std::size_t dtm_of_dubious_parent = get(dtm, parent); - bool is_art_point = false; - if ( dtm_of_dubious_parent > get(dtm, u) ) { - parent = get(pred, parent); - is_art_point = true; - put(pred, get(pred, u), u); - put(pred, u, parent); - } - - if ( parent == u ) { // at top - if ( get(dtm, u) + 1 == dtm_of_dubious_parent ) - is_art_point = false; + if (parent == u) { // Root of tree is special + is_articulation_point[get(index_map, u)] = (children_of_root > 1); } else { put(lowpt, parent, min BOOST_PREVENT_MACRO_SUBSTITUTION(get(lowpt, parent), - get(lowpt, u))); - - if (get(lowpt, u) >= get(dtm, parent)) { - if ( get(dtm, parent) > get(dtm, get(pred, parent)) ) { - put(pred, u, get(pred, parent)); - put(pred, parent, u); - } - + get(lowpt, u))); + if ( get(lowpt, u) >= get(dtm, parent) ) { + is_articulation_point[get(index_map, parent)] = true; while ( get(dtm, source(S.top(), g)) >= get(dtm, u) ) { put(comp, S.top(), c); S.pop(); } + BOOST_ASSERT (source(S.top(), g) == parent); + BOOST_ASSERT (target(S.top(), g) == u); put(comp, S.top(), c); - S.pop(); + S.pop(); ++c; - if ( S.empty() ) { - put(pred, u, parent); - put(pred, parent, u); - } } } - if ( is_art_point ) + if ( is_articulation_point[get(index_map, u)] ) { *out++ = u; + } vis.finish_vertex(u, g); } ComponentMap comp; std::size_t& c; + std::size_t& children_of_root; DiscoverTimeMap dtm; std::size_t& dfs_time; LowPointMap lowpt; PredecessorMap pred; OutputIterator out; Stack& S; + ArticulationVector& is_articulation_point; + IndexMap index_map; DFSVisitor vis; }; @@ -160,24 +165,26 @@ namespace boost { typedef typename graph_traits::vertex_descriptor vertex_t; typedef typename graph_traits::edge_descriptor edge_t; - function_requires >(); - function_requires >(); - function_requires >(); - function_requires >(); - function_requires >(); - function_requires >(); + BOOST_CONCEPT_ASSERT(( VertexListGraphConcept )); + BOOST_CONCEPT_ASSERT(( IncidenceGraphConcept )); + BOOST_CONCEPT_ASSERT(( WritablePropertyMapConcept )); + BOOST_CONCEPT_ASSERT(( ReadWritePropertyMapConcept )); + BOOST_CONCEPT_ASSERT(( ReadWritePropertyMapConcept )); + BOOST_CONCEPT_ASSERT(( ReadWritePropertyMapConcept )); std::size_t num_components = 0; + std::size_t children_of_root; std::size_t dfs_time = 0; - std::stack S; + std::stack S; + std::vector is_articulation_point(num_vertices(g)); - biconnected_components_visitor, - DFSVisitor> - vis(comp, num_components, dtm, dfs_time, lowpt, pred, out, - S, dfs_vis); + biconnected_components_visitor, + std::vector, VertexIndexMap, DFSVisitor> + vis(comp, num_components, children_of_root, dtm, dfs_time, + lowpt, pred, out, S, is_articulation_point, index_map, dfs_vis); depth_first_search(g, visitor(vis).vertex_index_map(index_map)); @@ -203,7 +210,7 @@ namespace boost }; template <> - struct bicomp_dispatch3 + struct bicomp_dispatch3 { template& params, - error_property_not_found) + param_not_found) { typedef typename graph_traits::vertex_descriptor vertex_t; std::vector pred(num_vertices(g)); @@ -237,8 +244,7 @@ namespace boost DiscoverTimeMap dtm, const bgl_named_params& params, LowPointMap lowpt) { - typedef typename property_value< bgl_named_params, - vertex_predecessor_t>::type dispatch_type; + typedef typename get_param_type< vertex_predecessor_t, bgl_named_params >::type dispatch_type; return bicomp_dispatch3::apply (g, comp, out, index_map, dtm, lowpt, params, @@ -248,7 +254,7 @@ namespace boost template <> - struct bicomp_dispatch2 + struct bicomp_dispatch2 { template apply (const Graph& g, ComponentMap comp, OutputIterator out, VertexIndexMap index_map, DiscoverTimeMap dtm, const bgl_named_params& params, - error_property_not_found) + param_not_found) { typedef typename graph_traits::vertices_size_type vertices_size_type; std::vector lowpt(num_vertices(g)); vertices_size_type vst(0); - typedef typename property_value< bgl_named_params, - vertex_predecessor_t>::type dispatch_type; + typedef typename get_param_type< vertex_predecessor_t, bgl_named_params >::type dispatch_type; return bicomp_dispatch3::apply (g, comp, out, index_map, dtm, @@ -282,8 +287,7 @@ namespace boost ComponentMap comp, OutputIterator out, VertexIndexMap index_map, const bgl_named_params& params, DiscoverTimeMap dtm) { - typedef typename property_value< bgl_named_params, - vertex_lowpoint_t>::type dispatch_type; + typedef typename get_param_type< vertex_lowpoint_t, bgl_named_params >::type dispatch_type; return bicomp_dispatch2::apply (g, comp, out, index_map, dtm, params, @@ -292,21 +296,20 @@ namespace boost }; template <> - struct bicomp_dispatch1 + struct bicomp_dispatch1 { template static std::pair apply(const Graph& g, ComponentMap comp, OutputIterator out, VertexIndexMap index_map, - const bgl_named_params& params, error_property_not_found) + const bgl_named_params& params, param_not_found) { typedef typename graph_traits::vertices_size_type vertices_size_type; std::vector discover_time(num_vertices(g)); vertices_size_type vst(0); - typedef typename property_value< bgl_named_params, - vertex_lowpoint_t>::type dispatch_type; + typedef typename get_param_type< vertex_lowpoint_t, bgl_named_params >::type dispatch_type; return bicomp_dispatch2::apply (g, comp, out, index_map, @@ -323,14 +326,14 @@ namespace boost biconnected_components(const Graph& g, ComponentMap comp, OutputIterator out, DiscoverTimeMap dtm, LowPointMap lowpt) { - typedef detail::error_property_not_found dispatch_type; + typedef param_not_found dispatch_type; return detail::bicomp_dispatch3::apply (g, comp, out, get(vertex_index, g), dtm, lowpt, bgl_named_params(0), - detail::error_property_not_found()); + param_not_found()); } template & params) { - typedef typename property_value< bgl_named_params, - vertex_discover_time_t>::type dispatch_type; + typedef typename get_param_type< vertex_discover_time_t, bgl_named_params >::type dispatch_type; return detail::bicomp_dispatch1::apply(g, comp, out, choose_const_pmap(get_param(params, vertex_index), g, vertex_index), diff --git a/include/boost/graph/bipartite.hpp b/include/boost/graph/bipartite.hpp index f902fd3e7..74316fd53 100644 --- a/include/boost/graph/bipartite.hpp +++ b/include/boost/graph/bipartite.hpp @@ -198,7 +198,6 @@ namespace boost { /// General types and variables typedef typename property_traits ::value_type partition_color_t; typedef typename graph_traits ::vertex_descriptor vertex_descriptor_t; - typedef typename graph_traits ::vertex_iterator vertex_iterator_t; /// Declare dfs visitor // detail::empty_recorder recorder; @@ -212,8 +211,6 @@ namespace boost { depth_first_search (graph, vertex_index_map (index_map).visitor (make_dfs_visitor (std::make_pair ( detail::colorize_bipartition (partition_map), std::make_pair (detail::check_bipartition (partition_map), put_property (partition_map, color_traits ::white (), on_start_vertex ())))))); - - // depth_first_search (graph, vertex_index_map (index_map).visitor (dfs_visitor)); } catch (detail::bipartite_visitor_error error) { @@ -284,11 +281,9 @@ namespace boost { typedef std::vector predecessors_t; typedef iterator_property_map predecessor_map_t; - typedef predecessor_recorder predecessor_recorder_t; predecessors_t predecessors (num_vertices (graph), graph_traits ::null_vertex ()); predecessor_map_t predecessor_map (predecessors.begin (), index_map); - predecessor_recorder_t predecessor_recorder (predecessor_map); /// Initialize predecessor map for (boost::tie (vertex_iter, vertex_end) = vertices (graph); vertex_iter != vertex_end; ++vertex_iter) diff --git a/include/boost/graph/boykov_kolmogorov_max_flow.hpp b/include/boost/graph/boykov_kolmogorov_max_flow.hpp index 8559bd771..1edc1323e 100644 --- a/include/boost/graph/boykov_kolmogorov_max_flow.hpp +++ b/include/boost/graph/boykov_kolmogorov_max_flow.hpp @@ -33,7 +33,7 @@ #define BOOST_BOYKOV_KOLMOGOROV_MAX_FLOW_HPP #include -#include +#include #include #include #include @@ -47,6 +47,7 @@ #include #include #include +#include // The algorithm impelemented here is described in: // @@ -125,14 +126,14 @@ class bk_max_flow { // the residual capacity equal to the capacity edge_iterator ei, e_end; for(boost::tie(ei, e_end) = edges(m_g); ei != e_end; ++ei) { - m_res_cap_map[*ei] = m_cap_map[*ei]; - assert(m_rev_edge_map[m_rev_edge_map[*ei]] == *ei); //check if the reverse edge map is build up properly + put(m_res_cap_map, *ei, get(m_cap_map, *ei)); + BOOST_ASSERT(get(m_rev_edge_map, get(m_rev_edge_map, *ei)) == *ei); //check if the reverse edge map is build up properly } //init the search trees with the two terminals set_tree(m_source, tColorTraits::black()); set_tree(m_sink, tColorTraits::white()); - m_time_map[m_source] = 1; - m_time_map[m_sink] = 1; + put(m_time_map, m_source, 1); + put(m_time_map, m_sink, 1); } tEdgeVal max_flow(){ @@ -168,8 +169,8 @@ class bk_max_flow { edge_descriptor from_source = *ei; vertex_descriptor current_node = target(from_source, m_g); if(current_node == m_sink){ - tEdgeVal cap = m_res_cap_map[from_source]; - m_res_cap_map[from_source] = 0; + tEdgeVal cap = get(m_res_cap_map, from_source); + put(m_res_cap_map, from_source, 0); m_flow += cap; continue; } @@ -177,52 +178,52 @@ class bk_max_flow { bool is_there; boost::tie(to_sink, is_there) = lookup_edge(current_node, m_sink, m_g); if(is_there){ - tEdgeVal cap_from_source = m_res_cap_map[from_source]; - tEdgeVal cap_to_sink = m_res_cap_map[to_sink]; + tEdgeVal cap_from_source = get(m_res_cap_map, from_source); + tEdgeVal cap_to_sink = get(m_res_cap_map, to_sink); if(cap_from_source > cap_to_sink){ set_tree(current_node, tColorTraits::black()); add_active_node(current_node); set_edge_to_parent(current_node, from_source); - m_dist_map[current_node] = 1; - m_time_map[current_node] = 1; + put(m_dist_map, current_node, 1); + put(m_time_map, current_node, 1); // add stuff to flow and update residuals. we dont need to // update reverse_edges, as incoming/outgoing edges to/from // source/sink don't count for max-flow - m_res_cap_map[from_source] -= cap_to_sink; - m_res_cap_map[to_sink] = 0; + put(m_res_cap_map, from_source, get(m_res_cap_map, from_source) - cap_to_sink); + put(m_res_cap_map, to_sink, 0); m_flow += cap_to_sink; } else if(cap_to_sink > 0){ set_tree(current_node, tColorTraits::white()); add_active_node(current_node); set_edge_to_parent(current_node, to_sink); - m_dist_map[current_node] = 1; - m_time_map[current_node] = 1; + put(m_dist_map, current_node, 1); + put(m_time_map, current_node, 1); // add stuff to flow and update residuals. we dont need to update // reverse_edges, as incoming/outgoing edges to/from source/sink // don't count for max-flow - m_res_cap_map[to_sink] -= cap_from_source; - m_res_cap_map[from_source] = 0; + put(m_res_cap_map, to_sink, get(m_res_cap_map, to_sink) - cap_from_source); + put(m_res_cap_map, from_source, 0); m_flow += cap_from_source; } - } else if(m_res_cap_map[from_source]){ + } else if(get(m_res_cap_map, from_source)){ // there is no sink connect, so we can't augment this path, but to // avoid adding m_source to the active nodes, we just activate this // node and set the approciate things set_tree(current_node, tColorTraits::black()); set_edge_to_parent(current_node, from_source); - m_dist_map[current_node] = 1; - m_time_map[current_node] = 1; + put(m_dist_map, current_node, 1); + put(m_time_map, current_node, 1); add_active_node(current_node); } } for(boost::tie(ei, e_end) = out_edges(m_sink, m_g); ei != e_end; ++ei){ - edge_descriptor to_sink = m_rev_edge_map[*ei]; + edge_descriptor to_sink = get(m_rev_edge_map, *ei); vertex_descriptor current_node = source(to_sink, m_g); - if(m_res_cap_map[to_sink]){ + if(get(m_res_cap_map, to_sink)){ set_tree(current_node, tColorTraits::white()); set_edge_to_parent(current_node, to_sink); - m_dist_map[current_node] = 1; - m_time_map[current_node] = 1; + put(m_dist_map, current_node, 1); + put(m_time_map, current_node, 1); add_active_node(current_node); } } @@ -235,13 +236,13 @@ class bk_max_flow { * target(returnVal, m_g) is the beginning of the path found in the sink-tree */ std::pair grow(){ - assert(m_orphans.empty()); + BOOST_ASSERT(m_orphans.empty()); vertex_descriptor current_node; while((current_node = get_next_active_node()) != graph_traits::null_vertex()){ //if there is one - assert(get_tree(current_node) != tColorTraits::gray() && - (has_parent(current_node) || - current_node == m_source || - current_node == m_sink)); + BOOST_ASSERT(get_tree(current_node) != tColorTraits::gray() && + (has_parent(current_node) || + current_node == m_source || + current_node == m_sink)); if(get_tree(current_node) == tColorTraits::black()){ //source tree growing @@ -252,24 +253,24 @@ class bk_max_flow { } for(; m_last_grow_edge_it != m_last_grow_edge_end; ++m_last_grow_edge_it) { edge_descriptor out_edge = *m_last_grow_edge_it; - if(m_res_cap_map[out_edge] > 0){ //check if we have capacity left on this edge + if(get(m_res_cap_map, out_edge) > 0){ //check if we have capacity left on this edge vertex_descriptor other_node = target(out_edge, m_g); if(get_tree(other_node) == tColorTraits::gray()){ //it's a free node set_tree(other_node, tColorTraits::black()); //aquire other node to our search tree set_edge_to_parent(other_node, out_edge); //set us as parent - m_dist_map[other_node] = m_dist_map[current_node] + 1; //and update the distance-heuristic - m_time_map[other_node] = m_time_map[current_node]; + put(m_dist_map, other_node, get(m_dist_map, current_node) + 1); //and update the distance-heuristic + put(m_time_map, other_node, get(m_time_map, current_node)); add_active_node(other_node); } else if(get_tree(other_node) == tColorTraits::black()) { // we do this to get shorter paths. check if we are nearer to // the source as its parent is if(is_closer_to_terminal(current_node, other_node)){ set_edge_to_parent(other_node, out_edge); - m_dist_map[other_node] = m_dist_map[current_node] + 1; - m_time_map[other_node] = m_time_map[current_node]; + put(m_dist_map, other_node, get(m_dist_map, current_node) + 1); + put(m_time_map, other_node, get(m_time_map, current_node)); } } else{ - assert(get_tree(other_node)==tColorTraits::white()); + BOOST_ASSERT(get_tree(other_node)==tColorTraits::white()); //kewl, found a path from one to the other search tree, return // the connecting edge in src->sink dir return std::make_pair(out_edge, true); @@ -278,31 +279,31 @@ class bk_max_flow { } //for all out-edges } //source-tree-growing else{ - assert(get_tree(current_node) == tColorTraits::white()); + BOOST_ASSERT(get_tree(current_node) == tColorTraits::white()); out_edge_iterator ei, e_end; if(current_node != m_last_grow_vertex){ m_last_grow_vertex = current_node; boost::tie(m_last_grow_edge_it, m_last_grow_edge_end) = out_edges(current_node, m_g); } for(; m_last_grow_edge_it != m_last_grow_edge_end; ++m_last_grow_edge_it){ - edge_descriptor in_edge = m_rev_edge_map[*m_last_grow_edge_it]; - if(m_res_cap_map[in_edge] > 0){ //check if there is capacity left + edge_descriptor in_edge = get(m_rev_edge_map, *m_last_grow_edge_it); + if(get(m_res_cap_map, in_edge) > 0){ //check if there is capacity left vertex_descriptor other_node = source(in_edge, m_g); if(get_tree(other_node) == tColorTraits::gray()){ //it's a free node set_tree(other_node, tColorTraits::white()); //aquire that node to our search tree set_edge_to_parent(other_node, in_edge); //set us as parent add_active_node(other_node); //activate that node - m_dist_map[other_node] = m_dist_map[current_node] + 1; //set its distance - m_time_map[other_node] = m_time_map[current_node]; //and time + put(m_dist_map, other_node, get(m_dist_map, current_node) + 1); //set its distance + put(m_time_map, other_node, get(m_time_map, current_node));//and time } else if(get_tree(other_node) == tColorTraits::white()){ if(is_closer_to_terminal(current_node, other_node)){ //we are closer to the sink than its parent is, so we "adopt" him set_edge_to_parent(other_node, in_edge); - m_dist_map[other_node] = m_dist_map[current_node] + 1; - m_time_map[other_node] = m_time_map[current_node]; + put(m_dist_map, other_node, get(m_dist_map, current_node) + 1); + put(m_time_map, other_node, get(m_time_map, current_node)); } } else{ - assert(get_tree(other_node)==tColorTraits::black()); + BOOST_ASSERT(get_tree(other_node)==tColorTraits::black()); //kewl, found a path from one to the other search tree, // return the connecting edge in src->sink dir return std::make_pair(in_edge, true); @@ -332,26 +333,26 @@ class bk_max_flow { * and so we process the nearest verts to the terminals first */ void augment(edge_descriptor e) { - assert(get_tree(target(e, m_g)) == tColorTraits::white()); - assert(get_tree(source(e, m_g)) == tColorTraits::black()); - assert(m_orphans.empty()); + BOOST_ASSERT(get_tree(target(e, m_g)) == tColorTraits::white()); + BOOST_ASSERT(get_tree(source(e, m_g)) == tColorTraits::black()); + BOOST_ASSERT(m_orphans.empty()); const tEdgeVal bottleneck = find_bottleneck(e); //now we push the found flow through the path //for each edge we saturate we have to look for the verts that belong to that edge, one of them becomes an orphans //now process the connecting edge - m_res_cap_map[e] -= bottleneck; - assert(m_res_cap_map[e] >= 0); - m_res_cap_map[m_rev_edge_map[e]] += bottleneck; + put(m_res_cap_map, e, get(m_res_cap_map, e) - bottleneck); + BOOST_ASSERT(get(m_res_cap_map, e) >= 0); + put(m_res_cap_map, get(m_rev_edge_map, e), get(m_res_cap_map, get(m_rev_edge_map, e)) + bottleneck); //now we follow the path back to the source vertex_descriptor current_node = source(e, m_g); while(current_node != m_source){ edge_descriptor pred = get_edge_to_parent(current_node); - m_res_cap_map[pred] -= bottleneck; - assert(m_res_cap_map[pred] >= 0); - m_res_cap_map[m_rev_edge_map[pred]] += bottleneck; - if(m_res_cap_map[pred] == 0){ + put(m_res_cap_map, pred, get(m_res_cap_map, pred) - bottleneck); + BOOST_ASSERT(get(m_res_cap_map, pred) >= 0); + put(m_res_cap_map, get(m_rev_edge_map, pred), get(m_res_cap_map, get(m_rev_edge_map, pred)) + bottleneck); + if(get(m_res_cap_map, pred) == 0){ set_no_parent(current_node); m_orphans.push_front(current_node); } @@ -361,10 +362,10 @@ class bk_max_flow { current_node = target(e, m_g); while(current_node != m_sink){ edge_descriptor pred = get_edge_to_parent(current_node); - m_res_cap_map[pred] -= bottleneck; - assert(m_res_cap_map[pred] >= 0); - m_res_cap_map[m_rev_edge_map[pred]] += bottleneck; - if(m_res_cap_map[pred] == 0){ + put(m_res_cap_map, pred, get(m_res_cap_map, pred) - bottleneck); + BOOST_ASSERT(get(m_res_cap_map, pred) >= 0); + put(m_res_cap_map, get(m_rev_edge_map, pred), get(m_res_cap_map, get(m_rev_edge_map, pred)) + bottleneck); + if(get(m_res_cap_map, pred) == 0){ set_no_parent(current_node); m_orphans.push_front(current_node); } @@ -380,19 +381,19 @@ class bk_max_flow { */ inline tEdgeVal find_bottleneck(edge_descriptor e){ BOOST_USING_STD_MIN(); - tEdgeVal minimum_cap = m_res_cap_map[e]; + tEdgeVal minimum_cap = get(m_res_cap_map, e); vertex_descriptor current_node = source(e, m_g); //first go back in the source tree while(current_node != m_source){ edge_descriptor pred = get_edge_to_parent(current_node); - minimum_cap = min BOOST_PREVENT_MACRO_SUBSTITUTION(minimum_cap, m_res_cap_map[pred]); + minimum_cap = min BOOST_PREVENT_MACRO_SUBSTITUTION(minimum_cap, get(m_res_cap_map, pred)); current_node = source(pred, m_g); } //then go forward in the sink-tree current_node = target(e, m_g); while(current_node != m_sink){ edge_descriptor pred = get_edge_to_parent(current_node); - minimum_cap = min BOOST_PREVENT_MACRO_SUBSTITUTION(minimum_cap, m_res_cap_map[pred]); + minimum_cap = min BOOST_PREVENT_MACRO_SUBSTITUTION(minimum_cap, get(m_res_cap_map, pred)); current_node = target(pred, m_g); } return minimum_cap; @@ -420,13 +421,13 @@ class bk_max_flow { edge_descriptor new_parent_edge; out_edge_iterator ei, e_end; for(boost::tie(ei, e_end) = out_edges(current_node, m_g); ei != e_end; ++ei){ - const edge_descriptor in_edge = m_rev_edge_map[*ei]; - assert(target(in_edge, m_g) == current_node); //we should be the target of this edge - if(m_res_cap_map[in_edge] > 0){ + const edge_descriptor in_edge = get(m_rev_edge_map, *ei); + BOOST_ASSERT(target(in_edge, m_g) == current_node); //we should be the target of this edge + if(get(m_res_cap_map, in_edge) > 0){ vertex_descriptor other_node = source(in_edge, m_g); if(get_tree(other_node) == tColorTraits::black() && has_source_connect(other_node)){ - if(m_dist_map[other_node] < min_distance){ - min_distance = m_dist_map[other_node]; + if(get(m_dist_map, other_node) < min_distance){ + min_distance = get(m_dist_map, other_node); new_parent_edge = in_edge; } } @@ -434,18 +435,18 @@ class bk_max_flow { } if(min_distance != (std::numeric_limits::max)()){ set_edge_to_parent(current_node, new_parent_edge); - m_dist_map[current_node] = min_distance + 1; - m_time_map[current_node] = m_time; + put(m_dist_map, current_node, min_distance + 1); + put(m_time_map, current_node, m_time); } else{ - m_time_map[current_node] = 0; + put(m_time_map, current_node, 0); for(boost::tie(ei, e_end) = out_edges(current_node, m_g); ei != e_end; ++ei){ - edge_descriptor in_edge = m_rev_edge_map[*ei]; + edge_descriptor in_edge = get(m_rev_edge_map, *ei); vertex_descriptor other_node = source(in_edge, m_g); - if(get_tree(other_node) == tColorTraits::black() && has_parent(other_node)){ - if(m_res_cap_map[in_edge] > 0){ + if(get_tree(other_node) == tColorTraits::black() && other_node != m_source){ + if(get(m_res_cap_map, in_edge) > 0){ add_active_node(other_node); } - if(source(get_edge_to_parent(other_node), m_g) == current_node){ + if(has_parent(other_node) && source(get_edge_to_parent(other_node), m_g) == current_node){ //we are the parent of that node //it has to find a new parent, too set_no_parent(other_node); @@ -458,35 +459,35 @@ class bk_max_flow { } //source-tree-adoption else{ //now we should be in the sink-tree, check that... - assert(get_tree(current_node) == tColorTraits::white()); + BOOST_ASSERT(get_tree(current_node) == tColorTraits::white()); out_edge_iterator ei, e_end; edge_descriptor new_parent_edge; tDistanceVal min_distance = (std::numeric_limits::max)(); for(boost::tie(ei, e_end) = out_edges(current_node, m_g); ei != e_end; ++ei){ const edge_descriptor out_edge = *ei; - if(m_res_cap_map[out_edge] > 0){ + if(get(m_res_cap_map, out_edge) > 0){ const vertex_descriptor other_node = target(out_edge, m_g); if(get_tree(other_node) == tColorTraits::white() && has_sink_connect(other_node)) - if(m_dist_map[other_node] < min_distance){ - min_distance = m_dist_map[other_node]; + if(get(m_dist_map, other_node) < min_distance){ + min_distance = get(m_dist_map, other_node); new_parent_edge = out_edge; } } } if(min_distance != (std::numeric_limits::max)()){ set_edge_to_parent(current_node, new_parent_edge); - m_dist_map[current_node] = min_distance + 1; - m_time_map[current_node] = m_time; + put(m_dist_map, current_node, min_distance + 1); + put(m_time_map, current_node, m_time); } else{ - m_time_map[current_node] = 0; + put(m_time_map, current_node, 0); for(boost::tie(ei, e_end) = out_edges(current_node, m_g); ei != e_end; ++ei){ const edge_descriptor out_edge = *ei; const vertex_descriptor other_node = target(out_edge, m_g); - if(get_tree(other_node) == tColorTraits::white() && has_parent(other_node)){ - if(m_res_cap_map[out_edge] > 0){ + if(get_tree(other_node) == tColorTraits::white() && other_node != m_sink){ + if(get(m_res_cap_map, out_edge) > 0){ add_active_node(other_node); } - if(target(get_edge_to_parent(other_node), m_g) == current_node){ + if(has_parent(other_node) && target(get_edge_to_parent(other_node), m_g) == current_node){ //we were it's parent, so it has to find a new one, too set_no_parent(other_node); m_child_orphans.push(other_node); @@ -511,9 +512,9 @@ class bk_max_flow { //if it has no parent, this node can't be active (if its not source or sink) if(!has_parent(v) && v != m_source && v != m_sink){ m_active_nodes.pop(); - m_in_active_list_map[v] = false; + put(m_in_active_list_map, v, false); } else{ - assert(get_tree(v) == tColorTraits::black() || get_tree(v) == tColorTraits::white()); + BOOST_ASSERT(get_tree(v) == tColorTraits::black() || get_tree(v) == tColorTraits::white()); return v; } } @@ -523,11 +524,14 @@ class bk_max_flow { * adds v as an active vertex, but only if its not in the list already */ inline void add_active_node(vertex_descriptor v){ - assert(get_tree(v) != tColorTraits::gray()); - if(m_in_active_list_map[v]){ + BOOST_ASSERT(get_tree(v) != tColorTraits::gray()); + if(get(m_in_active_list_map, v)){ + if (m_last_grow_vertex == v) { + m_last_grow_vertex = graph_traits::null_vertex(); + } return; } else{ - m_in_active_list_map[v] = true; + put(m_in_active_list_map, v, true); m_active_nodes.push(v); } } @@ -536,9 +540,9 @@ class bk_max_flow { * finish_node removes a node from the front of the active queue (its called in grow phase, if no more paths can be found using this node) */ inline void finish_node(vertex_descriptor v){ - assert(m_active_nodes.front() == v); + BOOST_ASSERT(m_active_nodes.front() == v); m_active_nodes.pop(); - m_in_active_list_map[v] = false; + put(m_in_active_list_map, v, false); m_last_grow_vertex = graph_traits::null_vertex(); } @@ -548,7 +552,7 @@ class bk_max_flow { * being no more active) */ inline void remove_active_node(vertex_descriptor v){ - assert(!has_parent(v)); + BOOST_ASSERT(!has_parent(v)); } /** @@ -556,7 +560,7 @@ class bk_max_flow { * white() for sink tree, gray() for no tree */ inline tColorValue get_tree(vertex_descriptor v) const { - return m_tree_map[v]; + return get(m_tree_map, v); } /** @@ -564,30 +568,30 @@ class bk_max_flow { * for sink tree, gray() for no tree */ inline void set_tree(vertex_descriptor v, tColorValue t){ - m_tree_map[v] = t; + put(m_tree_map, v, t); } /** * returns edge to parent vertex of v; */ inline edge_descriptor get_edge_to_parent(vertex_descriptor v) const{ - return m_pre_map[v]; + return get(m_pre_map, v); } /** * returns true if the edge stored in m_pre_map[v] is a valid entry */ inline bool has_parent(vertex_descriptor v) const{ - return m_has_parent_map[v]; + return get(m_has_parent_map, v); } /** * sets edge to parent vertex of v; */ inline void set_edge_to_parent(vertex_descriptor v, edge_descriptor f_edge_to_parent){ - assert(m_res_cap_map[f_edge_to_parent] > 0); - m_pre_map[v] = f_edge_to_parent; - m_has_parent_map[v] = true; + BOOST_ASSERT(get(m_res_cap_map, f_edge_to_parent) > 0); + put(m_pre_map, v, f_edge_to_parent); + put(m_has_parent_map, v, true); } /** @@ -595,7 +599,7 @@ class bk_max_flow { * entry an additional map) */ inline void set_no_parent(vertex_descriptor v){ - m_has_parent_map[v] = false; + put(m_has_parent_map, v, false); } /** @@ -607,13 +611,13 @@ class bk_max_flow { tDistanceVal current_distance = 0; vertex_descriptor current_vertex = v; while(true){ - if(m_time_map[current_vertex] == m_time){ + if(get(m_time_map, current_vertex) == m_time){ //we found a node which was already checked this round. use it for distance calculations - current_distance += m_dist_map[current_vertex]; + current_distance += get(m_dist_map, current_vertex); break; } if(current_vertex == m_sink){ - m_time_map[m_sink] = m_time; + put(m_time_map, m_sink, m_time); break; } if(has_parent(current_vertex)){ @@ -626,9 +630,10 @@ class bk_max_flow { } } current_vertex=v; - while(m_time_map[current_vertex] != m_time){ - m_dist_map[current_vertex] = current_distance--; - m_time_map[current_vertex] = m_time; + while(get(m_time_map, current_vertex) != m_time){ + put(m_dist_map, current_vertex, current_distance); + --current_distance; + put(m_time_map, current_vertex, m_time); current_vertex = target(get_edge_to_parent(current_vertex), m_g); } return true; @@ -643,13 +648,13 @@ class bk_max_flow { tDistanceVal current_distance = 0; vertex_descriptor current_vertex = v; while(true){ - if(m_time_map[current_vertex] == m_time){ + if(get(m_time_map, current_vertex) == m_time){ //we found a node which was already checked this round. use it for distance calculations - current_distance += m_dist_map[current_vertex]; + current_distance += get(m_dist_map, current_vertex); break; } if(current_vertex == m_source){ - m_time_map[m_source] = m_time; + put(m_time_map, m_source, m_time); break; } if(has_parent(current_vertex)){ @@ -662,9 +667,10 @@ class bk_max_flow { } } current_vertex=v; - while(m_time_map[current_vertex] != m_time){ - m_dist_map[current_vertex] = current_distance-- ; - m_time_map[current_vertex] = m_time; + while(get(m_time_map, current_vertex) != m_time){ + put(m_dist_map, current_vertex, current_distance); + --current_distance; + put(m_time_map, current_vertex, m_time); current_vertex = source(get_edge_to_parent(current_vertex), m_g); } return true; @@ -675,7 +681,8 @@ class bk_max_flow { */ inline bool is_closer_to_terminal(vertex_descriptor p, vertex_descriptor q){ //checks the timestamps first, to build no cycles, and after that the real distance - return (m_time_map[q] <= m_time_map[p] && m_dist_map[q] > m_dist_map[p]+1); + return (get(m_time_map, q) <= get(m_time_map, p) && + get(m_dist_map, q) > get(m_dist_map, p)+1); } //////// @@ -740,17 +747,17 @@ boykov_kolmogorov_max_flow(Graph& g, typedef typename graph_traits::edge_descriptor edge_descriptor; //as this method is the last one before we instantiate the solver, we do the concept checks here - function_requires >(); //to have vertices(), num_vertices(), - function_requires >(); //to have edges() - function_requires >(); //to have source(), target() and out_edges() - function_requires >(); //read flow-values from edges - function_requires >(); //write flow-values to residuals - function_requires >(); //read out reverse edges - function_requires >(); //store predecessor there - function_requires >(); //write corresponding tree - function_requires >(); //write distance to source/sink - function_requires >(); //get index 0...|V|-1 - assert(num_vertices(g) >= 2 && src != sink); + BOOST_CONCEPT_ASSERT(( VertexListGraphConcept )); //to have vertices(), num_vertices(), + BOOST_CONCEPT_ASSERT(( EdgeListGraphConcept )); //to have edges() + BOOST_CONCEPT_ASSERT(( IncidenceGraphConcept )); //to have source(), target() and out_edges() + BOOST_CONCEPT_ASSERT(( ReadablePropertyMapConcept )); //read flow-values from edges + BOOST_CONCEPT_ASSERT(( ReadWritePropertyMapConcept )); //write flow-values to residuals + BOOST_CONCEPT_ASSERT(( ReadablePropertyMapConcept )); //read out reverse edges + BOOST_CONCEPT_ASSERT(( ReadWritePropertyMapConcept )); //store predecessor there + BOOST_CONCEPT_ASSERT(( ReadWritePropertyMapConcept )); //write corresponding tree + BOOST_CONCEPT_ASSERT(( ReadWritePropertyMapConcept )); //write distance to source/sink + BOOST_CONCEPT_ASSERT(( ReadablePropertyMapConcept )); //get index 0...|V|-1 + BOOST_ASSERT(num_vertices(g) >= 2 && src != sink); detail::bk_max_flow< Graph, CapacityEdgeMap, ResidualCapacityEdgeMap, ReverseEdgeMap, diff --git a/include/boost/graph/breadth_first_search.hpp b/include/boost/graph/breadth_first_search.hpp index 79fde8cd6..b0d10ad5f 100644 --- a/include/boost/graph/breadth_first_search.hpp +++ b/include/boost/graph/breadth_first_search.hpp @@ -24,6 +24,7 @@ #include #include #include +#include #ifdef BOOST_GRAPH_USE_MPI #include @@ -34,7 +35,7 @@ namespace boost { template struct BFSVisitorConcept { void constraints() { - function_requires< CopyConstructibleConcept >(); + BOOST_CONCEPT_ASSERT(( CopyConstructibleConcept )); vis.initialize_vertex(u, g); vis.discover_vertex(u, g); vis.examine_vertex(u, g); @@ -52,25 +53,28 @@ namespace boost { }; + // Multiple-source version template + class ColorMap, class SourceIterator> void breadth_first_visit (const IncidenceGraph& g, - typename graph_traits::vertex_descriptor s, + SourceIterator sources_begin, SourceIterator sources_end, Buffer& Q, BFSVisitor vis, ColorMap color) { - function_requires< IncidenceGraphConcept >(); + BOOST_CONCEPT_ASSERT(( IncidenceGraphConcept )); typedef graph_traits GTraits; typedef typename GTraits::vertex_descriptor Vertex; - typedef typename GTraits::edge_descriptor Edge; - function_requires< BFSVisitorConcept >(); - function_requires< ReadWritePropertyMapConcept >(); + BOOST_CONCEPT_ASSERT(( BFSVisitorConcept )); + BOOST_CONCEPT_ASSERT(( ReadWritePropertyMapConcept )); typedef typename property_traits::value_type ColorValue; typedef color_traits Color; typename GTraits::out_edge_iterator ei, ei_end; - put(color, s, Color::gray()); vis.discover_vertex(s, g); - Q.push(s); + for (; sources_begin != sources_end; ++sources_begin) { + Vertex s = *sources_begin; + put(color, s, Color::gray()); vis.discover_vertex(s, g); + Q.push(s); + } while (! Q.empty()) { Vertex u = Q.top(); Q.pop(); vis.examine_vertex(u, g); for (boost::tie(ei, ei_end) = out_edges(u, g); ei != ei_end; ++ei) { @@ -88,12 +92,25 @@ namespace boost { } // end while } // breadth_first_visit + // Single-source version + template + void breadth_first_visit + (const IncidenceGraph& g, + typename graph_traits::vertex_descriptor s, + Buffer& Q, BFSVisitor vis, ColorMap color) + { + typename graph_traits::vertex_descriptor sources[1] = {s}; + breadth_first_visit(g, sources, sources + 1, Q, vis, color); + } + - template void breadth_first_search (const VertexListGraph& g, - typename graph_traits::vertex_descriptor s, + SourceIterator sources_begin, SourceIterator sources_end, Buffer& Q, BFSVisitor vis, ColorMap color) { // Initialization @@ -104,7 +121,18 @@ namespace boost { vis.initialize_vertex(*i, g); put(color, *i, Color::white()); } - breadth_first_visit(g, s, Q, vis, color); + breadth_first_visit(g, sources_begin, sources_end, Q, vis, color); + } + + template + void breadth_first_search + (const VertexListGraph& g, + typename graph_traits::vertex_descriptor s, + Buffer& Q, BFSVisitor vis, ColorMap color) + { + typename graph_traits::vertex_descriptor sources[1] = {s}; + breadth_first_search(g, sources, sources + 1, Q, vis, color); } namespace graph { struct bfs_visitor_event_not_overridden {}; } @@ -219,8 +247,7 @@ namespace boost { ColorMap color, BFSVisitor vis, const bgl_named_params& params, - BOOST_GRAPH_ENABLE_IF_MODELS(VertexListGraph, vertex_list_graph_tag, - void)* = 0) + boost::mpl::false_) { typedef graph_traits Traits; // Buffer default @@ -242,8 +269,7 @@ namespace boost { ColorMap color, BFSVisitor vis, const bgl_named_params& params, - BOOST_GRAPH_ENABLE_IF_MODELS(DistributedGraph, distributed_graph_tag, - void)* = 0); + boost::mpl::true_); #endif // BOOST_GRAPH_USE_MPI //------------------------------------------------------------------------- @@ -264,18 +290,22 @@ namespace boost { (g, s, color, choose_param(get_param(params, graph_visitor), make_bfs_visitor(null_visitor())), - params); + params, + boost::mpl::bool_< + boost::is_base_and_derived< + distributed_graph_tag, + typename graph_traits::traversal_category>::value>()); } }; template <> - struct bfs_dispatch { + struct bfs_dispatch { template static void apply (VertexListGraph& g, typename graph_traits::vertex_descriptor s, const bgl_named_params& params, - detail::error_property_not_found) + param_not_found) { null_visitor null_vis; @@ -287,13 +317,17 @@ namespace boost { g, vertex_index)), choose_param(get_param(params, graph_visitor), make_bfs_visitor(null_vis)), - params); + params, + boost::mpl::bool_< + boost::is_base_and_derived< + distributed_graph_tag, + typename graph_traits::traversal_category>::value>()); } }; } // namespace detail - +#if 1 // Named Parameter Variant template void breadth_first_search @@ -306,11 +340,11 @@ namespace boost { // graph is not really const since we may write to property maps // of the graph. VertexListGraph& ng = const_cast(g); - typedef typename property_value< bgl_named_params, - vertex_color_t>::type C; + typedef typename get_param_type< vertex_color_t, bgl_named_params >::type C; detail::bfs_dispatch::apply(ng, s, params, get_param(params, vertex_color)); } +#endif // This version does not initialize colors, user has to. @@ -342,6 +376,33 @@ namespace boost { ); } + namespace graph { + namespace detail { + template + struct breadth_first_search_impl { + typedef void result_type; + template + void operator()(const Graph& g, const Source& source, const ArgPack& arg_pack) { + using namespace boost::graph::keywords; + typename boost::graph_traits::vertex_descriptor sources[1] = {source}; + boost::queue::vertex_descriptor> Q; + boost::breadth_first_search(g, + &sources[0], + &sources[1], + boost::unwrap_ref(arg_pack[_buffer | boost::ref(Q)]), + arg_pack[_visitor | make_bfs_visitor(null_visitor())], + boost::detail::make_color_map_from_arg_pack(g, arg_pack)); + } + }; + } + BOOST_GRAPH_MAKE_FORWARDING_FUNCTION(breadth_first_search, 2, 4) + } + +#if 0 + // Named Parameter Variant + BOOST_GRAPH_MAKE_OLD_STYLE_PARAMETER_FUNCTION(breadth_first_search, 2) +#endif + } // namespace boost #ifdef BOOST_GRAPH_USE_MPI diff --git a/include/boost/graph/bron_kerbosch_all_cliques.hpp b/include/boost/graph/bron_kerbosch_all_cliques.hpp index 35479316a..b663cf95f 100644 --- a/include/boost/graph/bron_kerbosch_all_cliques.hpp +++ b/include/boost/graph/bron_kerbosch_all_cliques.hpp @@ -11,6 +11,8 @@ #include #include +#include + #include #include @@ -151,7 +153,7 @@ namespace detail const Container& in, Container& out) { - function_requires< GraphConcept >(); + BOOST_CONCEPT_ASSERT(( GraphConcept )); typename graph_traits::directed_category cat; typename Container::const_iterator i, end = in.end(); @@ -174,8 +176,8 @@ namespace detail Visitor vis, std::size_t min) { - function_requires< GraphConcept >(); - function_requires< CliqueVisitorConcept >(); + BOOST_CONCEPT_ASSERT(( GraphConcept )); + BOOST_CONCEPT_ASSERT(( CliqueVisitorConcept )); typedef typename graph_traits::vertex_descriptor Vertex; // Is there vertex in nots that is connected to all vertices @@ -222,7 +224,7 @@ namespace detail // otherwise, iterate over candidates and and test // for maxmimal cliquiness. - typename Container::iterator i, j, end = cands.end(); + typename Container::iterator i, j; for(i = cands.begin(); i != cands.end(); ) { Vertex candidate = *i; @@ -266,15 +268,14 @@ template inline void bron_kerbosch_all_cliques(const Graph& g, Visitor vis, std::size_t min) { - function_requires< IncidenceGraphConcept >(); - function_requires< VertexListGraphConcept >(); - function_requires< VertexIndexGraphConcept >(); - function_requires< AdjacencyMatrixConcept >(); // Structural requirement only + BOOST_CONCEPT_ASSERT(( IncidenceGraphConcept )); + BOOST_CONCEPT_ASSERT(( VertexListGraphConcept )); + BOOST_CONCEPT_ASSERT(( AdjacencyMatrixConcept )); // Structural requirement only typedef typename graph_traits::vertex_descriptor Vertex; typedef typename graph_traits::vertex_iterator VertexIterator; typedef std::vector VertexSet; typedef std::deque Clique; - function_requires< CliqueVisitorConcept >(); + BOOST_CONCEPT_ASSERT(( CliqueVisitorConcept )); // NOTE: We're using a deque to implement the clique, because it provides // constant inserts and removals at the end and also a constant size. diff --git a/include/boost/graph/chrobak_payne_drawing.hpp b/include/boost/graph/chrobak_payne_drawing.hpp index 9e3a2f368..0e1f05255 100644 --- a/include/boost/graph/chrobak_payne_drawing.hpp +++ b/include/boost/graph/chrobak_payne_drawing.hpp @@ -11,8 +11,8 @@ #include #include +#include #include -#include //for next and prior #include #include @@ -34,12 +34,22 @@ namespace boost VertexToVertexMap left, VertexToVertexMap right) { - if (v != graph_traits::null_vertex()) - { + typedef typename graph_traits::vertex_descriptor vertex_descriptor; + // Suggestion of explicit stack from Aaron Windsor to avoid system stack + // overflows. + typedef std::pair stack_entry; + std::stack st; + st.push(stack_entry(v, offset)); + while (!st.empty()) { + vertex_descriptor v = st.top().first; + std::size_t offset = st.top().second; + st.pop(); + if (v != graph_traits::null_vertex()) { x[v] += delta_x[v] + offset; - accumulate_offsets(left[v], x[v], g, x, delta_x, left, right); - accumulate_offsets(right[v], x[v], g, x, delta_x, left, right); + st.push(stack_entry(left[v], x[v])); + st.push(stack_entry(right[v], x[v])); } + } } } /*namespace detail*/ } /*namespace graph*/ @@ -63,7 +73,6 @@ namespace boost { typedef typename graph_traits::vertex_descriptor vertex_t; - typedef typename graph_traits::edge_descriptor edge_t; typedef typename graph_traits::vertex_iterator vertex_iterator_t; typedef typename PlanarEmbedding::value_type::const_iterator edge_permutation_iterator_t; @@ -230,7 +239,7 @@ namespace boost (*ordering_begin,0,g,x,delta_x,left,right); vertex_iterator_t vi, vi_end; - for(tie(vi,vi_end) = vertices(g); vi != vi_end; ++vi) + for(boost::tie(vi,vi_end) = vertices(g); vi != vi_end; ++vi) { vertex_t v(*vi); drawing[v].x = x[v]; diff --git a/include/boost/graph/closeness_centrality.hpp b/include/boost/graph/closeness_centrality.hpp index 77cea7b0e..3ddf284b5 100644 --- a/include/boost/graph/closeness_centrality.hpp +++ b/include/boost/graph/closeness_centrality.hpp @@ -9,6 +9,7 @@ #include #include +#include namespace boost { @@ -25,9 +26,9 @@ struct closeness_measure result_type operator ()(distance_type d, const Graph&) { - function_requires< NumericValueConcept >(); - function_requires< NumericValueConcept >(); - function_requires< AdaptableUnaryFunctionConcept >(); + BOOST_CONCEPT_ASSERT(( NumericValueConcept )); + BOOST_CONCEPT_ASSERT(( NumericValueConcept )); + BOOST_CONCEPT_ASSERT(( AdaptableUnaryFunctionConcept )); return (d == base_type::infinite_distance()) ? base_type::zero_result() : rec(result_type(d)); @@ -75,12 +76,12 @@ closeness_centrality(const Graph& g, Measure measure, Combinator combine) { - function_requires< VertexListGraphConcept >(); + BOOST_CONCEPT_ASSERT(( VertexListGraphConcept )); typedef typename graph_traits::vertex_descriptor Vertex; - function_requires< ReadablePropertyMapConcept >(); + BOOST_CONCEPT_ASSERT(( ReadablePropertyMapConcept )); typedef typename property_traits::value_type Distance; - function_requires< NumericValueConcept >(); - function_requires< DistanceMeasureConcept >(); + BOOST_CONCEPT_ASSERT(( NumericValueConcept )); + BOOST_CONCEPT_ASSERT(( DistanceMeasureConcept )); Distance n = detail::combine_distances(g, dist, combine, Distance(0)); return measure(n, g); @@ -90,9 +91,9 @@ template inline typename Measure::result_type closeness_centrality(const Graph& g, DistanceMap dist, Measure measure) { - function_requires< GraphConcept >(); + BOOST_CONCEPT_ASSERT(( GraphConcept )); typedef typename graph_traits::vertex_descriptor Vertex; - function_requires< ReadablePropertyMapConcept >(); + BOOST_CONCEPT_ASSERT(( ReadablePropertyMapConcept )); typedef typename property_traits::value_type Distance; return closeness_centrality(g, dist, measure, std::plus()); @@ -116,17 +117,16 @@ all_closeness_centralities(const Graph& g, CentralityMap cent, Measure measure) { - function_requires< VertexListGraphConcept >(); + BOOST_CONCEPT_ASSERT(( VertexListGraphConcept )); typedef typename graph_traits::vertex_descriptor Vertex; - function_requires< ReadablePropertyMapConcept >(); + BOOST_CONCEPT_ASSERT(( ReadablePropertyMapConcept )); typedef typename property_traits::value_type DistanceMap; - function_requires< ReadablePropertyMapConcept >(); - function_requires< WritablePropertyMapConcept >(); - typedef typename property_traits::value_type Distance; + BOOST_CONCEPT_ASSERT(( ReadablePropertyMapConcept )); + BOOST_CONCEPT_ASSERT(( WritablePropertyMapConcept )); typedef typename property_traits::value_type Centrality; typename graph_traits::vertex_iterator i, end; - for(tie(i, end) = vertices(g); i != end; ++i) { + for(boost::tie(i, end) = vertices(g); i != end; ++i) { DistanceMap dm = get(dist, *i); Centrality c = closeness_centrality(g, dm, measure); put(cent, *i, c); @@ -141,12 +141,11 @@ all_closeness_centralities(const Graph& g, DistanceMatrixMap dist, CentralityMap cent) { - function_requires< GraphConcept >(); + BOOST_CONCEPT_ASSERT(( GraphConcept )); typedef typename graph_traits::vertex_descriptor Vertex; - function_requires< ReadablePropertyMapConcept >(); + BOOST_CONCEPT_ASSERT(( ReadablePropertyMapConcept )); typedef typename property_traits::value_type DistanceMap; - function_requires< ReadablePropertyMapConcept >(); - typedef typename property_traits::value_type Distance; + BOOST_CONCEPT_ASSERT(( ReadablePropertyMapConcept )); typedef typename property_traits::value_type Result; all_closeness_centralities(g, dist, cent, measure_closeness(g, DistanceMap())); diff --git a/include/boost/graph/clustering_coefficient.hpp b/include/boost/graph/clustering_coefficient.hpp index 15574f041..5345ed999 100644 --- a/include/boost/graph/clustering_coefficient.hpp +++ b/include/boost/graph/clustering_coefficient.hpp @@ -7,10 +7,11 @@ #ifndef BOOST_GRAPH_CLUSTERING_COEFFICIENT_HPP #define BOOST_GRAPH_CLUSTERING_COEFFICIENT_HPP -#include +#include #include #include #include +#include namespace boost { @@ -20,7 +21,7 @@ namespace detail inline typename graph_traits::degree_size_type possible_edges(const Graph& g, std::size_t k, directed_tag) { - function_requires< GraphConcept >(); + BOOST_CONCEPT_ASSERT(( GraphConcept )); typedef typename graph_traits::degree_size_type T; return T(k) * (T(k) - 1); } @@ -37,12 +38,12 @@ namespace detail template inline typename graph_traits::degree_size_type count_edges(const Graph& g, - typename Graph::vertex_descriptor u, - typename Graph::vertex_descriptor v, + typename graph_traits::vertex_descriptor u, + typename graph_traits::vertex_descriptor v, directed_tag) { - function_requires< AdjacencyMatrixConcept >(); + BOOST_CONCEPT_ASSERT(( AdjacencyMatrixConcept )); return (lookup_edge(u, v, g).second ? 1 : 0) + (lookup_edge(v, u, g).second ? 1 : 0); } @@ -51,11 +52,11 @@ namespace detail template inline typename graph_traits::degree_size_type count_edges(const Graph& g, - typename Graph::vertex_descriptor u, - typename Graph::vertex_descriptor v, + typename graph_traits::vertex_descriptor u, + typename graph_traits::vertex_descriptor v, undirected_tag) { - function_requires< AdjacencyMatrixConcept >(); + BOOST_CONCEPT_ASSERT(( AdjacencyMatrixConcept )); return lookup_edge(u, v, g).second ? 1 : 0; } } @@ -64,7 +65,7 @@ template inline typename graph_traits::degree_size_type num_paths_through_vertex(const Graph& g, Vertex v) { - function_requires< AdjacencyGraphConcept >(); + BOOST_CONCEPT_ASSERT(( AdjacencyGraphConcept )); typedef typename graph_traits::directed_category Directed; typedef typename graph_traits::adjacency_iterator AdjacencyIterator; @@ -81,8 +82,8 @@ template inline typename graph_traits::degree_size_type num_triangles_on_vertex(const Graph& g, Vertex v) { - function_requires< IncidenceGraphConcept >(); - function_requires< AdjacencyGraphConcept >(); + BOOST_CONCEPT_ASSERT(( IncidenceGraphConcept )); + BOOST_CONCEPT_ASSERT(( AdjacencyGraphConcept )); typedef typename graph_traits::degree_size_type Degree; typedef typename graph_traits::directed_category Directed; typedef typename graph_traits::adjacency_iterator AdjacencyIterator; @@ -119,10 +120,10 @@ template inline typename property_traits::value_type all_clustering_coefficients(const Graph& g, ClusteringMap cm) { - function_requires< VertexListGraphConcept >(); + BOOST_CONCEPT_ASSERT(( VertexListGraphConcept )); typedef typename graph_traits::vertex_descriptor Vertex; typedef typename graph_traits::vertex_iterator VertexIterator; - function_requires< WritablePropertyMapConcept >(); + BOOST_CONCEPT_ASSERT(( WritablePropertyMapConcept )); typedef typename property_traits::value_type Coefficient; Coefficient sum(0); @@ -139,10 +140,10 @@ template inline typename property_traits::value_type mean_clustering_coefficient(const Graph& g, ClusteringMap cm) { - function_requires< VertexListGraphConcept >(); + BOOST_CONCEPT_ASSERT(( VertexListGraphConcept )); typedef typename graph_traits::vertex_descriptor Vertex; typedef typename graph_traits::vertex_iterator VertexIterator; - function_requires< ReadablePropertyMapConcept >(); + BOOST_CONCEPT_ASSERT(( ReadablePropertyMapConcept )); typedef typename property_traits::value_type Coefficient; Coefficient cc(0); diff --git a/include/boost/graph/compressed_sparse_row_graph.hpp b/include/boost/graph/compressed_sparse_row_graph.hpp index 9b5a4d52c..7b91d4d6c 100644 --- a/include/boost/graph/compressed_sparse_row_graph.hpp +++ b/include/boost/graph/compressed_sparse_row_graph.hpp @@ -17,7 +17,7 @@ #include #include #include -#include +#include #include #if 0 #include // For some debugging code below @@ -37,16 +37,15 @@ #include #include #include +#include #include +#include #include #include #include -#include - -#ifdef BOOST_GRAPH_NO_BUNDLED_PROPERTIES -# error The Compressed Sparse Row graph only supports bundled properties. -# error You will need a compiler that conforms better to the C++ standard. -#endif +#include +#include +#include namespace boost { @@ -139,7 +138,7 @@ namespace detail { typedef boost::iterator_facade, T, std::random_access_iterator_tag, const T&> base_type; T saved_value; const T& dereference() const {return saved_value;} - bool equal(default_construct_iterator i) const {return true;} + bool equal(default_construct_iterator /*i*/) const {return true;} void increment() {} void decrement() {} void advance(typename base_type::difference_type) {} @@ -193,10 +192,15 @@ class compressed_sparse_row_graph > inherited_vertex_properties; + // Some tests to prevent use of "void" is a property type (as was done in some test cases): + BOOST_STATIC_ASSERT((!is_same::value)); + BOOST_STATIC_ASSERT((!is_same::value)); + BOOST_STATIC_ASSERT((!is_same::value)); + public: // For Property Graph - typedef typename graph_detail::graph_prop::property graph_property_type; - typedef typename graph_detail::graph_prop::bundle graph_bundled; + typedef GraphProperty graph_property_type; + typedef typename lookup_one_property::type graph_bundled; typedef detail::compressed_sparse_row_structure forward_type; @@ -643,8 +647,6 @@ class compressed_sparse_row_graph::vertex_descriptor vertex_t; - typedef typename boost::graph_traits::vertices_size_type vertex_num; - typedef typename boost::graph_traits::edges_size_type edge_num; typedef std::vector > edge_vector_t; edge_vector_t new_edges(first, last); if (new_edges.empty()) return; @@ -667,8 +669,6 @@ class compressed_sparse_row_graph::vertex_descriptor vertex_t; - typedef typename boost::graph_traits::vertices_size_type vertex_num; - typedef typename boost::graph_traits::edges_size_type edge_num; typedef std::pair vertex_pair; typedef std::vector< boost::tuple::property graph_property_type; - typedef typename graph_detail::graph_prop::bundle graph_bundled; + typedef GraphProperty graph_property_type; + typedef typename lookup_one_property::type graph_bundled; // typedef GraphProperty graph_property_type; typedef detail::compressed_sparse_row_structure forward_type; @@ -933,6 +933,7 @@ class compressed_sparse_row_graph - void - add_edges_sorted_internal( - BidirectionalIteratorOrig first_sorted, - BidirectionalIteratorOrig last_sorted, - EPIterOrig ep_iter_sorted, - const GlobalToLocal& global_to_local) { - m_forward.add_edges_sorted_internal(first_sorted, last_sorted, ep_iter_sorted, global_to_local); - } - - template - void - add_edges_sorted_internal( - BidirectionalIteratorOrig first_sorted, - BidirectionalIteratorOrig last_sorted, - EPIterOrig ep_iter_sorted) { - m_forward.add_edges_sorted_internal(first_sorted, last_sorted, ep_iter_sorted, typed_identity_property_map()); - } - - // Add edges from a sorted (smallest sources first) range of pairs - template - void - add_edges_sorted_internal( - BidirectionalIteratorOrig first_sorted, - BidirectionalIteratorOrig last_sorted) { - m_forward.add_edges_sorted_internal(first_sorted, last_sorted, detail::default_construct_iterator()); - } - - template - void - add_edges_sorted_internal_global( - BidirectionalIteratorOrig first_sorted, - BidirectionalIteratorOrig last_sorted, - const GlobalToLocal& global_to_local) { - m_forward.add_edges_sorted_internal(first_sorted, last_sorted, detail::default_construct_iterator(), global_to_local); - } - - template - void - add_edges_sorted_internal_global( - BidirectionalIteratorOrig first_sorted, - BidirectionalIteratorOrig last_sorted, - EPIterOrig ep_iter_sorted, - const GlobalToLocal& global_to_local) { - m_forward.add_edges_sorted_internal(first_sorted, last_sorted, ep_iter_sorted, global_to_local); - } - - // Add edges from a range of (source, target) pairs that are unsorted - template - inline void - add_edges_internal(InputIterator first, InputIterator last, - const GlobalToLocal& global_to_local) { - typedef compressed_sparse_row_graph Graph; - typedef typename boost::graph_traits::vertex_descriptor vertex_t; - typedef typename boost::graph_traits::vertices_size_type vertex_num; - typedef typename boost::graph_traits::edges_size_type edge_num; - typedef std::vector > edge_vector_t; - edge_vector_t new_edges(first, last); - if (new_edges.empty()) return; - std::sort(new_edges.begin(), new_edges.end()); - this->add_edges_sorted_internal_global(new_edges.begin(), new_edges.end(), global_to_local); - } - - template - inline void - add_edges_internal(InputIterator first, InputIterator last) { - this->add_edges_internal(first, last, typed_identity_property_map()); - } - - // Add edges from a range of (source, target) pairs and edge properties that - // are unsorted - template - inline void - add_edges_internal(InputIterator first, InputIterator last, - EPIterator ep_iter, EPIterator ep_iter_end, - const GlobalToLocal& global_to_local) { - typedef compressed_sparse_row_graph Graph; - typedef typename boost::graph_traits::vertex_descriptor vertex_t; - typedef typename boost::graph_traits::vertices_size_type vertex_num; - typedef typename boost::graph_traits::edges_size_type edge_num; - typedef std::pair vertex_pair; - typedef std::vector< - boost::tuple > - edge_vector_t; - edge_vector_t new_edges - (boost::make_zip_iterator(boost::make_tuple(first, ep_iter)), - boost::make_zip_iterator(boost::make_tuple(last, ep_iter_end))); - if (new_edges.empty()) return; - std::sort(new_edges.begin(), new_edges.end(), - boost::detail::compare_first< - std::less >()); - m_forward.add_edges_sorted_internal - (boost::make_transform_iterator( - new_edges.begin(), - boost::detail::my_tuple_get_class<0, vertex_pair>()), - boost::make_transform_iterator( - new_edges.end(), - boost::detail::my_tuple_get_class<0, vertex_pair>()), - boost::make_transform_iterator( - new_edges.begin(), - boost::detail::my_tuple_get_class - <1, edge_bundled>()), - global_to_local); - } - - // Add edges from a range of (source, target) pairs and edge properties that - // are unsorted - template - inline void - add_edges_internal(InputIterator first, InputIterator last, - EPIterator ep_iter, EPIterator ep_iter_end) { - this->add_edges_internal(first, last, ep_iter, ep_iter_end, typed_identity_property_map()); + set_up_backward_property_links(); } using inherited_vertex_properties::operator[]; @@ -1134,7 +1018,6 @@ add_vertices(typename BOOST_DIR_CSR_GRAPH_TYPE::vertices_size_type count, BOOST_ Vertex old_num_verts_plus_one = g.m_forward.m_rowstart.size(); EdgeIndex numedges = g.m_forward.m_rowstart.back(); g.m_forward.m_rowstart.resize(old_num_verts_plus_one + count, numedges); - g.m_backward.m_rowstart.resize(old_num_verts_plus_one + count, numedges); g.vertex_properties().resize(num_vertices(g)); return old_num_verts_plus_one - 1; } @@ -1282,7 +1165,6 @@ inline std::pair in_edges(Vertex v, const BOOST_BIDIR_CSR_GRAPH_TYPE& g) { - typedef typename BOOST_BIDIR_CSR_GRAPH_TYPE::edge_descriptor ed; typedef typename BOOST_BIDIR_CSR_GRAPH_TYPE::in_edge_iterator it; EdgeIndex v_row_start = g.m_backward.m_rowstart[v]; EdgeIndex next_row_start = g.m_backward.m_rowstart[v + 1]; @@ -1342,7 +1224,7 @@ inline typename BOOST_CSR_GRAPH_TYPE::edge_descriptor edge_from_index(EdgeIndex idx, const BOOST_CSR_GRAPH_TYPE& g) { typedef typename std::vector::const_iterator row_start_iter; - assert (idx < num_edges(g)); + BOOST_ASSERT (idx < num_edges(g)); row_start_iter src_plus_1 = std::upper_bound(g.m_forward.m_rowstart.begin(), g.m_forward.m_rowstart.end(), @@ -1383,56 +1265,147 @@ edges(const BOOST_CSR_GRAPH_TYPE& g) // Graph properties template inline void -set_property(BOOST_CSR_GRAPH_TYPE& g, Tag, const Value& value) +set_property(BOOST_CSR_GRAPH_TYPE& g, Tag tag, const Value& value) { - get_property_value(g.m_property, Tag()) = value; + get_property_value(g.m_property, tag) = value; } template inline typename graph_property::type& -get_property(BOOST_CSR_GRAPH_TYPE& g, Tag) +get_property(BOOST_CSR_GRAPH_TYPE& g, Tag tag) { - return get_property_value(g.m_property, Tag()); + return get_property_value(g.m_property, tag); } template inline const typename graph_property::type& -get_property(const BOOST_CSR_GRAPH_TYPE& g, Tag) +get_property(const BOOST_CSR_GRAPH_TYPE& g, Tag tag) { - return get_property_value(g.m_property, Tag()); + return get_property_value(g.m_property, tag); +} + +template +struct csr_property_map_helper {}; +// Kind == void for invalid property tags, so we can use that to SFINAE out + +template +struct csr_property_map_helper { + typedef vertex_all_t all_tag; + typedef typename property_traits::type>::key_type key_type; + typedef VertexProperty plist_type; + typedef typename property_map::type all_type; + typedef typename property_map::const_type all_const_type; + typedef transform_value_property_map, all_type> type; + typedef transform_value_property_map, all_const_type> const_type; +}; + +template +struct csr_property_map_helper { + typedef edge_all_t all_tag; + typedef typename property_traits::type>::key_type key_type; + typedef EdgeProperty plist_type; + typedef typename property_map::type all_type; + typedef typename property_map::const_type all_const_type; + typedef transform_value_property_map, all_type> type; + typedef transform_value_property_map, all_const_type> const_type; +}; + +template +struct csr_property_map_helper { + typedef graph_all_t all_tag; + typedef BOOST_CSR_GRAPH_TYPE* key_type; + typedef GraphProperty plist_type; + typedef typename property_map::type all_type; + typedef typename property_map::const_type all_const_type; + typedef transform_value_property_map, all_type> type; + typedef transform_value_property_map, all_const_type> const_type; +}; + +// disable_if isn't truly necessary but required to avoid ambiguity with specializations below +template +struct property_map >::type>: + csr_property_map_helper< + BOOST_CSR_GRAPH_TYPE, + Tag, + typename detail::property_kind_from_graph + ::type> {}; + +template +typename property_map::type +get(Tag tag, BOOST_CSR_GRAPH_TYPE& g) { + return typename property_map::type(tag, get(typename property_map::all_tag(), g)); +} + +template +typename property_map::const_type +get(Tag tag, const BOOST_CSR_GRAPH_TYPE& g) { + return typename property_map::const_type(tag, get(typename property_map::all_tag(), g)); +} + +template +typename property_traits::type>::reference +get(Tag tag, BOOST_CSR_GRAPH_TYPE& g, typename property_map::key_type k) { + typedef typename property_map::all_tag all_tag; + typedef typename property_map::type outer_pm; + return lookup_one_property::value_type, Tag>::lookup(get(all_tag(), g, k), tag); +} + +template +typename property_traits::const_type>::reference +get(Tag tag, const BOOST_CSR_GRAPH_TYPE& g, typename property_map::key_type k) { + typedef typename property_map::all_tag all_tag; + typedef typename property_map::const_type outer_pm; + return lookup_one_property::value_type, Tag>::lookup(get(all_tag(), g, k), tag); +} + +template +void +put(Tag tag, + BOOST_CSR_GRAPH_TYPE& g, + typename property_map::key_type k, + typename lookup_one_property::plist_type, Tag>::type val) { + typedef typename property_map::all_tag all_tag; + lookup_one_property::plist_type, Tag>::lookup(get(all_tag(), g, k), tag) = val; } template -struct property_map +struct property_map >::type> { typedef typed_identity_property_map type; typedef type const_type; }; template -struct property_map +struct property_map >::type> { typedef detail::csr_edge_index_map type; typedef type const_type; }; template -struct property_map +struct property_map >::type> { typedef typename BOOST_CSR_GRAPH_TYPE::inherited_vertex_properties::vertex_map_type type; typedef typename BOOST_CSR_GRAPH_TYPE::inherited_vertex_properties::const_vertex_map_type const_type; }; template -struct property_map +struct property_map >::type> { typedef typename BOOST_CSR_GRAPH_TYPE::forward_type::inherited_edge_properties::edge_map_type type; typedef typename BOOST_CSR_GRAPH_TYPE::forward_type::inherited_edge_properties::const_edge_map_type const_type; }; +template +struct property_map >::type> +{ + typedef boost::ref_property_map type; + typedef boost::ref_property_map const_type; +}; + template inline typed_identity_property_map get(vertex_index_t, const BOOST_CSR_GRAPH_TYPE&) @@ -1448,6 +1421,21 @@ get(vertex_index_t, return v; } +template +inline typed_identity_property_map +get(vertex_index_t, BOOST_CSR_GRAPH_TYPE&) +{ + return typed_identity_property_map(); +} + +template +inline Vertex +get(vertex_index_t, + BOOST_CSR_GRAPH_TYPE&, Vertex v) +{ + return v; +} + template inline typename property_map::const_type get(edge_index_t, const BOOST_CSR_GRAPH_TYPE&) @@ -1466,125 +1454,144 @@ get(edge_index_t, const BOOST_CSR_GRAPH_TYPE&, } template -inline typename property_map::type -get(vertex_bundle_t, BOOST_CSR_GRAPH_TYPE& g) +inline typename property_map::const_type +get(edge_index_t, BOOST_CSR_GRAPH_TYPE&) +{ + typedef typename property_map::const_type + result_type; + return result_type(); +} + +template +inline EdgeIndex +get(edge_index_t, BOOST_CSR_GRAPH_TYPE&, + typename BOOST_CSR_GRAPH_TYPE::edge_descriptor e) +{ + return e.idx; +} + +template +inline typename property_map::type +get(vertex_all_t, BOOST_CSR_GRAPH_TYPE& g) { return g.get_vertex_bundle(get(vertex_index, g)); } template -inline typename property_map::const_type -get(vertex_bundle_t, const BOOST_CSR_GRAPH_TYPE& g) +inline typename property_map::const_type +get(vertex_all_t, const BOOST_CSR_GRAPH_TYPE& g) { return g.get_vertex_bundle(get(vertex_index, g)); } template inline VertexProperty& -get(vertex_bundle_t, +get(vertex_all_t, BOOST_CSR_GRAPH_TYPE& g, Vertex v) { - return get(vertex_bundle, g)[v]; + return get(vertex_all, g)[v]; } template inline const VertexProperty& -get(vertex_bundle_t, +get(vertex_all_t, const BOOST_CSR_GRAPH_TYPE& g, Vertex v) { - return get(vertex_bundle, g)[v]; + return get(vertex_all, g)[v]; } template inline void -put(vertex_bundle_t, +put(vertex_all_t, BOOST_CSR_GRAPH_TYPE& g, Vertex v, const VertexProperty& val) { - put(get(vertex_bundle, g), v, val); + put(get(vertex_all, g), v, val); } template -inline typename property_map::type -get(edge_bundle_t, BOOST_CSR_GRAPH_TYPE& g) +inline typename property_map::type +get(edge_all_t, BOOST_CSR_GRAPH_TYPE& g) { return g.m_forward.get_edge_bundle(get(edge_index, g)); } template -inline typename property_map::const_type -get(edge_bundle_t, const BOOST_CSR_GRAPH_TYPE& g) +inline typename property_map::const_type +get(edge_all_t, const BOOST_CSR_GRAPH_TYPE& g) { return g.m_forward.get_edge_bundle(get(edge_index, g)); } template inline EdgeProperty& -get(edge_bundle_t, +get(edge_all_t, BOOST_CSR_GRAPH_TYPE& g, const typename BOOST_CSR_GRAPH_TYPE::edge_descriptor& e) { - return get(edge_bundle, g)[e]; + return get(edge_all, g)[e]; } template inline const EdgeProperty& -get(edge_bundle_t, +get(edge_all_t, const BOOST_CSR_GRAPH_TYPE& g, const typename BOOST_CSR_GRAPH_TYPE::edge_descriptor& e) { - return get(edge_bundle, g)[e]; + return get(edge_all, g)[e]; } template inline void -put(edge_bundle_t, +put(edge_all_t, BOOST_CSR_GRAPH_TYPE& g, const typename BOOST_CSR_GRAPH_TYPE::edge_descriptor& e, const EdgeProperty& val) { - put(get(edge_bundle, g), e, val); + put(get(edge_all, g), e, val); } -template -inline -typename property_map::type -get(T Bundle::* p, BOOST_CSR_GRAPH_TYPE& g) +template +inline typename property_map::type +get(graph_all_t, BOOST_CSR_GRAPH_TYPE& g) { - typedef typename property_map::type - result_type; - return result_type(&g, p); + return typename property_map::type(g.m_property); } -template -inline -typename property_map::const_type -get(T Bundle::* p, BOOST_CSR_GRAPH_TYPE const & g) +template +inline typename property_map::const_type +get(graph_all_t, const BOOST_CSR_GRAPH_TYPE& g) { - typedef typename property_map::const_type - result_type; - return result_type(&g, p); + return typename property_map::const_type(g.m_property); } -template -inline T -get(T Bundle::* p, BOOST_CSR_GRAPH_TYPE const & g, - const Key& key) +template +inline GraphProperty& +get(graph_all_t, + BOOST_CSR_GRAPH_TYPE& g, + BOOST_CSR_GRAPH_TYPE*) { - return get(get(p, g), key); + return g.m_property; } -template +template +inline const GraphProperty& +get(graph_all_t, + const BOOST_CSR_GRAPH_TYPE& g, + BOOST_CSR_GRAPH_TYPE*) +{ + return g.m_property; +} + +template inline void -put(T Bundle::* p, BOOST_CSR_GRAPH_TYPE& g, - const Key& key, const T& value) +put(graph_all_t, + BOOST_CSR_GRAPH_TYPE& g, + BOOST_CSR_GRAPH_TYPE*, + const GraphProperty& val) { - put(get(p, g), key, value); + g.m_property = val; } #undef BOOST_CSR_GRAPH_TYPE diff --git a/include/boost/graph/connected_components.hpp b/include/boost/graph/connected_components.hpp index 90015e670..9279110f1 100644 --- a/include/boost/graph/connected_components.hpp +++ b/include/boost/graph/connected_components.hpp @@ -17,6 +17,7 @@ #include #include #include +#include namespace boost { @@ -64,7 +65,7 @@ namespace boost { if (num_vertices(g) == 0) return 0; typedef typename graph_traits::vertex_descriptor Vertex; - function_requires< WritablePropertyMapConcept >(); + BOOST_CONCEPT_ASSERT(( WritablePropertyMapConcept )); typedef typename boost::graph_traits::directed_category directed; BOOST_STATIC_ASSERT((boost::is_same::value)); @@ -84,8 +85,8 @@ namespace boost { 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_CONCEPT_ASSERT(( WritablePropertyMapConcept )); + // typedef typename boost::graph_traits::directed_category directed; // BOOST_STATIC_ASSERT((boost::is_same::value)); typedef typename property_traits::value_type comp_type; diff --git a/include/boost/graph/copy.hpp b/include/boost/graph/copy.hpp index 402e75f24..21bb0fb01 100644 --- a/include/boost/graph/copy.hpp +++ b/include/boost/graph/copy.hpp @@ -44,6 +44,7 @@ #include #include #include +#include #include #include #include @@ -53,6 +54,48 @@ namespace boost { namespace detail { + // Hack to make transpose_graph work with the same interface as before + template + struct remove_reverse_edge_descriptor { + typedef Desc type; + static Desc convert(const Desc& d, const Graph&) {return d;} + }; + + template + struct remove_reverse_edge_descriptor > { + typedef Desc type; + static Desc convert(const reverse_graph_edge_descriptor& d, const Graph& g) { + return get(edge_underlying, g, d); + } + }; + + // Add a reverse_graph_edge_descriptor wrapper if the Graph is a + // reverse_graph but the edge descriptor is from the original graph (this + // case comes from the fact that transpose_graph uses reverse_graph + // internally but doesn't expose the different edge descriptor type to the + // user). + template + struct add_reverse_edge_descriptor { + typedef Desc type; + static Desc convert(const Desc& d) {return d;} + }; + + template + struct add_reverse_edge_descriptor > { + typedef reverse_graph_edge_descriptor type; + static reverse_graph_edge_descriptor convert(const Desc& d) { + return reverse_graph_edge_descriptor(d); + } + }; + + template + struct add_reverse_edge_descriptor, boost::reverse_graph > { + typedef reverse_graph_edge_descriptor type; + static reverse_graph_edge_descriptor convert(const reverse_graph_edge_descriptor& d) { + return d; + } + }; + // Default edge and vertex property copiers template @@ -63,7 +106,7 @@ namespace boost { template void operator()(const Edge1& e1, Edge2& e2) const { - put(edge_all_map2, e2, get(edge_all_map1, e1)); + put(edge_all_map2, e2, get(edge_all_map1, add_reverse_edge_descriptor::convert(e1))); } typename property_map::const_type edge_all_map1; mutable typename property_map::type edge_all_map2; @@ -112,6 +155,7 @@ namespace boost { CopyVertex copy_vertex, CopyEdge copy_edge, Orig2CopyVertexIndexMap orig2copy, IndexMap) { + typedef remove_reverse_edge_descriptor::edge_descriptor> cvt; typename graph_traits::vertex_iterator vi, vi_end; for (boost::tie(vi, vi_end) = vertices(g_in); vi != vi_end; ++vi) { typename graph_traits::vertex_descriptor @@ -126,7 +170,7 @@ namespace boost { boost::tie(new_e, inserted) = add_edge(get(orig2copy, source(*ei, g_in)), get(orig2copy, target(*ei, g_in)), g_out); - copy_edge(*ei, new_e); + copy_edge(cvt::convert(*ei, g_in), new_e); } } }; @@ -141,6 +185,7 @@ namespace boost { CopyVertex copy_vertex, CopyEdge copy_edge, Orig2CopyVertexIndexMap orig2copy, IndexMap) { + typedef remove_reverse_edge_descriptor::edge_descriptor> cvt; typename graph_traits::vertex_iterator vi, vi_end; for (boost::tie(vi, vi_end) = vertices(g_in); vi != vi_end; ++vi) { typename graph_traits::vertex_descriptor @@ -156,7 +201,7 @@ namespace boost { boost::tie(new_e, inserted) = add_edge(get(orig2copy, source(*ei, g_in)), get(orig2copy, target(*ei, g_in)), g_out); - copy_edge(*ei, new_e); + copy_edge(cvt::convert(*ei, g_in), new_e); } } } @@ -173,6 +218,7 @@ namespace boost { Orig2CopyVertexIndexMap orig2copy, IndexMap index_map) { + typedef remove_reverse_edge_descriptor::edge_descriptor> cvt; typedef color_traits Color; std::vector color(num_vertices(g_in), Color::white()); @@ -192,7 +238,7 @@ namespace boost { boost::tie(new_e, inserted) = add_edge(get(orig2copy, source(*ei,g_in)), get(orig2copy, target(*ei,g_in)), g_out); - copy_edge(*ei, new_e); + copy_edge(cvt::convert(*ei, g_in), new_e); } } color[get(index_map, *vi)] = Color::black(); @@ -234,7 +280,7 @@ namespace boost { typedef choose_copier_parameter type; }; template <> - struct choose_edge_copy { + struct choose_edge_copy { typedef choose_default_edge_copier type; }; template @@ -268,7 +314,7 @@ namespace boost { typedef choose_copier_parameter type; }; template <> - struct choose_vertex_copy { + struct choose_vertex_copy { typedef choose_default_vertex_copier type; }; template @@ -350,15 +396,28 @@ namespace boost { : g_out(graph), orig2copy(c), copy_vertex(cv), copy_edge(ce) { } template - void examine_vertex(Vertex u, const Graph& g_in) const { + typename graph_traits::vertex_descriptor copy_one_vertex(Vertex u) const { typename graph_traits::vertex_descriptor new_u = add_vertex(g_out); put(orig2copy, u, new_u); copy_vertex(u, new_u); + return new_u; + } + + template + void tree_edge(Edge e, const Graph& g_in) const { + // For a tree edge, the target vertex has not been copied yet. + typename graph_traits::edge_descriptor new_e; + bool inserted; + boost::tie(new_e, inserted) = add_edge(get(orig2copy, source(e, g_in)), + this->copy_one_vertex(target(e, g_in)), + g_out); + copy_edge(e, new_e); } template - void examine_edge(Edge e, const Graph& g_in) const { + void non_tree_edge(Edge e, const Graph& g_in) const { + // For a non-tree edge, the target vertex has already been copied. typename graph_traits::edge_descriptor new_e; bool inserted; boost::tie(new_e, inserted) = add_edge(get(orig2copy, source(e, g_in)), @@ -387,8 +446,10 @@ namespace boost { { graph_copy_visitor vis(g_out, orig2copy, copy_vertex, copy_edge); + typename graph_traits::vertex_descriptor src_copy + = vis.copy_one_vertex(src); breadth_first_search(g_in, src, params.visitor(vis)); - return get(orig2copy, src); + return src_copy; } } // namespace detail diff --git a/include/boost/graph/core_numbers.hpp b/include/boost/graph/core_numbers.hpp index 7ef08261c..9384f5d66 100644 --- a/include/boost/graph/core_numbers.hpp +++ b/include/boost/graph/core_numbers.hpp @@ -11,10 +11,10 @@ #ifndef BOOST_GRAPH_CORE_NUMBERS_HPP #define BOOST_GRAPH_CORE_NUMBERS_HPP -#include -#include +#include #include #include +#include /* * core_numbers @@ -46,7 +46,7 @@ namespace boost { struct CoreNumbersVisitorConcept { void constraints() { - function_requires< CopyConstructibleConcept >(); + BOOST_CONCEPT_ASSERT(( CopyConstructibleConcept )); vis.examine_vertex(u,g); vis.finish_vertex(u,g); vis.examine_edge(e,g); @@ -158,7 +158,8 @@ namespace boost { if (get(c,u) > v_cn) { // remove the edge put(c,u,get(c,u)-get(wm,*oi)); - Q.update(u); + if (Q.contains(u)) + Q.update(u); } } vis.finish_vertex(v,g); @@ -174,13 +175,14 @@ namespace boost { { typedef typename property_traits::value_type D; typedef std::less Cmp; - typedef indirect_cmp IndirectCmp; - IndirectCmp icmp(c, Cmp()); // build the mutable queue typedef typename graph_traits::vertex_descriptor vertex; - typedef mutable_queue, IndirectCmp, - IndexMap> MutableQueue; - MutableQueue Q(num_vertices(g), icmp, im); + std::vector index_in_heap_data(num_vertices(g)); + typedef iterator_property_map::iterator, IndexMap> + index_in_heap_map_type; + index_in_heap_map_type index_in_heap_map(index_in_heap_data.begin(), im); + typedef d_ary_heap_indirect MutableQueue; + MutableQueue Q(c, index_in_heap_map, Cmp()); typename graph_traits::vertex_iterator vi,vi_end; for (boost::tie(vi,vi_end) = vertices(g); vi!=vi_end; ++vi) { Q.push(*vi); @@ -314,7 +316,6 @@ namespace boost { core_numbers(Graph& g, CoreMap c, EdgeWeightMap wm, VertexIndexMap vim, CoreNumVisitor vis) { - typedef typename graph_traits::vertices_size_type size_type; detail::compute_in_degree_map(g,c,wm); return detail::core_numbers_dispatch(g,c,wm,vim,vis); } diff --git a/include/boost/graph/cuthill_mckee_ordering.hpp b/include/boost/graph/cuthill_mckee_ordering.hpp index 52dc982a1..e16595c6c 100644 --- a/include/boost/graph/cuthill_mckee_ordering.hpp +++ b/include/boost/graph/cuthill_mckee_ordering.hpp @@ -75,7 +75,6 @@ namespace boost { { //create queue, visitor...don't forget namespaces! - typedef typename property_traits::value_type ds_type; typedef typename graph_traits::vertex_descriptor Vertex; typedef typename boost::sparse::sparse_ordering_queue queue; typedef typename detail::bfs_rcm_visitor Visitor; @@ -137,7 +136,6 @@ namespace boost { return permutation; typedef typename boost::graph_traits::vertex_descriptor Vertex; - typedef typename boost::graph_traits::vertex_iterator VerIter; typedef typename property_traits::value_type ColorValue; typedef color_traits Color; @@ -172,7 +170,6 @@ namespace boost { if (boost::graph::has_no_vertices(G)) return permutation; - typedef out_degree_property_map DegreeMap; std::vector colors(num_vertices(G)); return cuthill_mckee_ordering(G, permutation, make_iterator_property_map(&colors[0], diff --git a/include/boost/graph/cycle_canceling.hpp b/include/boost/graph/cycle_canceling.hpp new file mode 100644 index 000000000..46a4b864c --- /dev/null +++ b/include/boost/graph/cycle_canceling.hpp @@ -0,0 +1,181 @@ +//======================================================================= +// Copyright 2013 University of Warsaw. +// Authors: Piotr Wygocki +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +//======================================================================= +// +// +//This algorithm is described in "Network Flows: Theory, Algorithms, and Applications" +// by Ahuja, Magnanti, Orlin. + +#ifndef BOOST_GRAPH_CYCLE_CANCELING_HPP +#define BOOST_GRAPH_CYCLE_CANCELING_HPP + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost { + + +namespace detail { + +template +class RecordEdgeMapAndCycleVertex + : public bellman_visitor > { + typedef edge_predecessor_recorder PredRec; +public: + RecordEdgeMapAndCycleVertex(PredEdgeMap pred, Vertex & v) : + bellman_visitor(PredRec(pred)), m_v(v), m_pred(pred) {} + + template + void edge_not_minimized(Edge e, const Graph & g) const { + typename graph_traits::vertices_size_type n = num_vertices(g) + 1; + + //edge e is not minimized but does not have to be on the negative weight cycle + //to find vertex on negative wieight cycle we move n+1 times backword in the PredEdgeMap graph. + while(n > 0) { + e = get(m_pred, source(e, g)); + --n; + } + m_v = source(e, g); + } +private: + Vertex & m_v; + PredEdgeMap m_pred; +}; + +} //detail + + +template +void cycle_canceling(const Graph &g, Weight weight, Reversed rev, ResidualCapacity residual_capacity, Pred pred, Distance distance) { + typedef filtered_graph > ResGraph; + ResGraph gres = detail::residual_graph(g, residual_capacity); + + typedef graph_traits ResGTraits; + typedef graph_traits GTraits; + typedef typename ResGTraits::edge_descriptor edge_descriptor; + typedef typename ResGTraits::vertex_descriptor vertex_descriptor; + + typename GTraits::vertices_size_type N = num_vertices(g); + + BGL_FORALL_VERTICES_T(v, g, Graph) { + put(pred, v, edge_descriptor()); + put(distance, v, 0); + } + + vertex_descriptor cycleStart; + while(!bellman_ford_shortest_paths(gres, N, + weight_map(weight). + distance_map(distance). + visitor(detail::RecordEdgeMapAndCycleVertex(pred, cycleStart)))) { + + detail::augment(g, cycleStart, cycleStart, pred, residual_capacity, rev); + + BGL_FORALL_VERTICES_T(v, g, Graph) { + put(pred, v, edge_descriptor()); + put(distance, v, 0); + } + } +} + + +//in this namespace argument dispatching takes place +namespace detail { + +template +void cycle_canceling_dispatch2( + const Graph &g, + Weight weight, + Reversed rev, + ResidualCapacity residual_capacity, + Pred pred, + Distance dist, + const bgl_named_params& params) { + cycle_canceling(g, weight, rev, residual_capacity, pred, dist); +} + +//setting default distance map +template +void cycle_canceling_dispatch2( + Graph &g, + Weight weight, + Reversed rev, + ResidualCapacity residual_capacity, + Pred pred, + param_not_found, + const bgl_named_params& params) { + typedef typename property_traits::value_type D; + + std::vector d_map(num_vertices(g)); + + cycle_canceling(g, weight, rev, residual_capacity, pred, + make_iterator_property_map(d_map.begin(), choose_const_pmap(get_param(params, vertex_index), g, vertex_index))); +} + +template +void cycle_canceling_dispatch1( + Graph &g, + Weight weight, + Reversed rev, + ResidualCapacity residual_capacity, + Pred pred, + const bgl_named_params& params) { + cycle_canceling_dispatch2(g, weight, rev,residual_capacity, pred, + get_param(params, vertex_distance), params); +} + +//setting default predecessors map +template +void cycle_canceling_dispatch1( + Graph &g, + Weight weight, + Reversed rev, + ResidualCapacity residual_capacity, + param_not_found, + const bgl_named_params& params) { + typedef typename graph_traits::edge_descriptor edge_descriptor; + std::vector p_map(num_vertices(g)); + + cycle_canceling_dispatch2(g, weight, rev, residual_capacity, + make_iterator_property_map(p_map.begin(), choose_const_pmap(get_param(params, vertex_index), g, vertex_index)), + get_param(params, vertex_distance), params); +} + +}//detail + +template +void cycle_canceling(Graph &g, + const bgl_named_params& params) { + cycle_canceling_dispatch1(g, + choose_const_pmap(get_param(params, edge_weight), g, edge_weight), + choose_const_pmap(get_param(params, edge_reverse), g, edge_reverse), + choose_pmap(get_param(params, edge_residual_capacity), + g, edge_residual_capacity), + get_param(params, vertex_predecessor), + params); +} + +template +void cycle_canceling(Graph &g) { + bgl_named_params params(0); + cycle_canceling(g, params); +} + + +} + +#endif /* BOOST_GRAPH_CYCLE_CANCELING_HPP */ + diff --git a/include/boost/graph/dag_shortest_paths.hpp b/include/boost/graph/dag_shortest_paths.hpp index a46de9145..325d1516c 100644 --- a/include/boost/graph/dag_shortest_paths.hpp +++ b/include/boost/graph/dag_shortest_paths.hpp @@ -88,14 +88,16 @@ namespace boost { { typedef typename property_traits::value_type D; dummy_property_map p_map; + D inf = + choose_param(get_param(params, distance_inf_t()), + (std::numeric_limits::max)()); dag_shortest_paths (g, s, distance, weight, color, choose_param(get_param(params, vertex_predecessor), p_map), vis, choose_param(get_param(params, distance_compare_t()), std::less()), - choose_param(get_param(params, distance_combine_t()), closed_plus()), - choose_param(get_param(params, distance_inf_t()), - (std::numeric_limits::max)()), + choose_param(get_param(params, distance_combine_t()), closed_plus(inf)), + inf, choose_param(get_param(params, distance_zero_t()), D())); } diff --git a/include/boost/graph/degree_centrality.hpp b/include/boost/graph/degree_centrality.hpp index 24ecb6c51..f6cc7a22f 100644 --- a/include/boost/graph/degree_centrality.hpp +++ b/include/boost/graph/degree_centrality.hpp @@ -8,6 +8,7 @@ #define BOOST_GRAPH_DEGREE_CENTRALITY_HPP #include +#include namespace boost { @@ -28,7 +29,7 @@ struct influence_measure inline degree_type operator ()(vertex_type v, const Graph& g) { - function_requires< IncidenceGraphConcept >(); + BOOST_CONCEPT_ASSERT(( IncidenceGraphConcept )); return out_degree(v, g); } }; @@ -49,7 +50,7 @@ struct prestige_measure inline degree_type operator ()(vertex_type v, const Graph& g) { - function_requires< BidirectionalGraphConcept >(); + BOOST_CONCEPT_ASSERT(( BidirectionalGraphConcept )); return in_degree(v, g); } }; @@ -64,7 +65,7 @@ template inline typename Measure::degree_type degree_centrality(const Graph& g, Vertex v, Measure measure) { - function_requires< DegreeMeasureConcept >(); + BOOST_CONCEPT_ASSERT(( DegreeMeasureConcept )); return measure(v, g); } @@ -94,14 +95,14 @@ template inline void all_degree_centralities(const Graph& g, CentralityMap cent, Measure measure) { - function_requires< VertexListGraphConcept >(); + BOOST_CONCEPT_ASSERT(( VertexListGraphConcept )); typedef typename graph_traits::vertex_descriptor Vertex; typedef typename graph_traits::vertex_iterator VertexIterator; - function_requires< WritablePropertyMapConcept >(); + BOOST_CONCEPT_ASSERT(( WritablePropertyMapConcept )); typedef typename property_traits::value_type Centrality; VertexIterator i, end; - for(tie(i, end) = vertices(g); i != end; ++i) { + for(boost::tie(i, end) = vertices(g); i != end; ++i) { Centrality c = degree_centrality(g, *i, measure); put(cent, *i, c); } diff --git a/include/boost/graph/depth_first_search.hpp b/include/boost/graph/depth_first_search.hpp index 74fe2c029..b002d3674 100644 --- a/include/boost/graph/depth_first_search.hpp +++ b/include/boost/graph/depth_first_search.hpp @@ -21,6 +21,10 @@ #include #include #include +#include +#include +#include +#include #include #include @@ -31,7 +35,7 @@ namespace boost { class DFSVisitorConcept { public: void constraints() { - function_requires< CopyConstructibleConcept >(); + BOOST_CONCEPT_ASSERT(( CopyConstructibleConcept )); vis.initialize_vertex(u, g); vis.start_vertex(u, g); vis.discover_vertex(u, g); @@ -39,6 +43,7 @@ namespace boost { vis.tree_edge(e, g); vis.back_edge(e, g); vis.forward_or_cross_edge(e, g); + // vis.finish_edge(e, g); // Optional for user vis.finish_vertex(u, g); } private: @@ -55,6 +60,25 @@ namespace boost { bool operator()(const T&, const T2&) const { return false; } }; + BOOST_TTI_HAS_MEMBER_FUNCTION(finish_edge) + + template struct do_call_finish_edge { + template + static void call_finish_edge(Vis& vis, const E& e, const G& g) { + vis.finish_edge(e, g); + } + }; + + template <> struct do_call_finish_edge { + template + static void call_finish_edge(Vis&, const E&, const G&) {} + }; + + template + void call_finish_edge(Vis& vis, const E& e, const G& g) { // Only call if method exists + do_call_finish_edge::value>::call_finish_edge(vis, e, g); + } + // Define BOOST_RECURSIVE_DFS to use older, recursive version. // It is retained for a while in order to perform performance @@ -80,39 +104,38 @@ namespace boost { DFSVisitor& vis, ColorMap color, TerminatorFunc func = TerminatorFunc()) { - function_requires >(); - function_requires >(); + BOOST_CONCEPT_ASSERT(( IncidenceGraphConcept )); + BOOST_CONCEPT_ASSERT(( DFSVisitorConcept )); typedef typename graph_traits::vertex_descriptor Vertex; - function_requires< ReadWritePropertyMapConcept >(); + typedef typename graph_traits::edge_descriptor Edge; + BOOST_CONCEPT_ASSERT(( ReadWritePropertyMapConcept )); typedef typename property_traits::value_type ColorValue; - function_requires< ColorValueConcept >(); + BOOST_CONCEPT_ASSERT(( ColorValueConcept )); typedef color_traits Color; typedef typename graph_traits::out_edge_iterator Iter; - typedef std::pair > VertexInfo; + typedef std::pair, std::pair > > VertexInfo; + boost::optional src_e; Iter ei, ei_end; std::vector stack; // Possible optimization for vector //stack.reserve(num_vertices(g)); - typedef typename unwrap_reference::type TF; - put(color, u, Color::gray()); vis.discover_vertex(u, g); boost::tie(ei, ei_end) = out_edges(u, g); - // Variable is needed to workaround a borland bug. - TF& fn = static_cast(func); - if (fn(u, g)) { + if (func(u, g)) { // If this vertex terminates the search, we push empty range - stack.push_back(std::make_pair(u, std::make_pair(ei_end, ei_end))); + stack.push_back(std::make_pair(u, std::make_pair(boost::optional(), std::make_pair(ei_end, ei_end)))); } else { - stack.push_back(std::make_pair(u, std::make_pair(ei, ei_end))); + stack.push_back(std::make_pair(u, std::make_pair(boost::optional(), std::make_pair(ei, ei_end)))); } while (!stack.empty()) { VertexInfo& back = stack.back(); u = back.first; - boost::tie(ei, ei_end) = back.second; + src_e = back.second.first; + boost::tie(ei, ei_end) = back.second.second; stack.pop_back(); while (ei != ei_end) { Vertex v = target(*ei, g); @@ -120,24 +143,28 @@ namespace boost { ColorValue v_color = get(color, v); if (v_color == Color::white()) { vis.tree_edge(*ei, g); - stack.push_back(std::make_pair(u, std::make_pair(++ei, ei_end))); + src_e = *ei; + stack.push_back(std::make_pair(u, std::make_pair(src_e, std::make_pair(++ei, ei_end)))); u = v; put(color, u, Color::gray()); vis.discover_vertex(u, g); boost::tie(ei, ei_end) = out_edges(u, g); - if (fn(u, g)) { + if (func(u, g)) { ei = ei_end; } - } else if (v_color == Color::gray()) { - vis.back_edge(*ei, g); - ++ei; } else { - vis.forward_or_cross_edge(*ei, g); + if (v_color == Color::gray()) { + vis.back_edge(*ei, g); + } else { + vis.forward_or_cross_edge(*ei, g); + } + call_finish_edge(vis, *ei, g); ++ei; } } put(color, u, Color::black()); vis.finish_vertex(u, g); + if (src_e) call_finish_edge(vis, src_e.get(), g); } } @@ -151,21 +178,18 @@ namespace boost { DFSVisitor& vis, // pass-by-reference here, important! ColorMap color, TerminatorFunc func) { - function_requires >(); - function_requires >(); + BOOST_CONCEPT_ASSERT(( IncidenceGraphConcept )); + BOOST_CONCEPT_ASSERT(( DFSVisitorConcept )); typedef typename graph_traits::vertex_descriptor Vertex; - function_requires< ReadWritePropertyMapConcept >(); + BOOST_CONCEPT_ASSERT(( ReadWritePropertyMapConcept )); typedef typename property_traits::value_type ColorValue; - function_requires< ColorValueConcept >(); + BOOST_CONCEPT_ASSERT(( ColorValueConcept )); typedef color_traits Color; typename graph_traits::out_edge_iterator ei, ei_end; put(color, u, Color::gray()); vis.discover_vertex(u, g); - typedef typename unwrap_reference::type TF; - // Variable is needed to workaround a borland bug. - TF& fn = static_cast(func); - if (!fn(u, g)) + if (!func(u, g)) for (boost::tie(ei, ei_end) = out_edges(u, g); ei != ei_end; ++ei) { Vertex v = target(*ei, g); vis.examine_edge(*ei, g); ColorValue v_color = get(color, v); @@ -173,6 +197,7 @@ namespace boost { depth_first_visit_impl(g, v, vis, color, func); } else if (v_color == Color::gray()) vis.back_edge(*ei, g); else vis.forward_or_cross_edge(*ei, g); + call_finish_edge(vis, *ei, g); } put(color, u, Color::black()); vis.finish_vertex(u, g); } @@ -187,7 +212,7 @@ namespace boost { typename graph_traits::vertex_descriptor start_vertex) { typedef typename graph_traits::vertex_descriptor Vertex; - function_requires >(); + BOOST_CONCEPT_ASSERT(( DFSVisitorConcept )); typedef typename property_traits::value_type ColorValue; typedef color_traits Color; @@ -197,7 +222,7 @@ namespace boost { put(color, u, Color::white()); vis.initialize_vertex(u, g); } - if (start_vertex != implicit_cast(*vertices(g).first)){ vis.start_vertex(start_vertex, g); + if (start_vertex != detail::get_default_starting_vertex(g)){ vis.start_vertex(start_vertex, g); detail::depth_first_visit_impl(g, start_vertex, vis, color, detail::nontruth2()); } @@ -220,7 +245,7 @@ namespace boost { if (verts.first == verts.second) return; - depth_first_search(g, vis, color, *verts.first); + depth_first_search(g, vis, color, detail::get_default_starting_vertex(g)); } template @@ -257,6 +282,10 @@ namespace boost { void forward_or_cross_edge(Edge u, const Graph& g) { invoke_visitors(m_vis, u, g, ::boost::on_forward_or_cross_edge()); } + template + void finish_edge(Edge u, const Graph& g) { + invoke_visitors(m_vis, u, g, ::boost::on_finish_edge()); + } template void finish_vertex(Vertex u, const Graph& g) { invoke_visitors(m_vis, u, g, ::boost::on_finish_vertex()); @@ -269,6 +298,7 @@ namespace boost { BOOST_GRAPH_EVENT_STUB(on_tree_edge,dfs) BOOST_GRAPH_EVENT_STUB(on_back_edge,dfs) BOOST_GRAPH_EVENT_STUB(on_forward_or_cross_edge,dfs) + BOOST_GRAPH_EVENT_STUB(on_finish_edge,dfs) BOOST_GRAPH_EVENT_STUB(on_finish_vertex,dfs) protected: @@ -281,27 +311,27 @@ 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 boost::graph_traits::vertex_iterator vi; - std::pair verts = vertices(g); - if (verts.first == verts.second) - return; - using namespace boost::graph::keywords; - typedef bgl_named_params params_type; - BOOST_GRAPH_DECLARE_CONVERTED_PARAMETERS(params_type, params) - depth_first_search - (g, - arg_pack[_visitor | make_dfs_visitor(null_visitor())], - boost::detail::make_color_map_from_arg_pack(g, arg_pack), - arg_pack[_root_vertex | *vertices(g).first] - ); + // Boost.Parameter named parameter variant + namespace graph { + namespace detail { + template + struct depth_first_search_impl { + typedef void result_type; + template + void operator()(const Graph& g, const ArgPack& arg_pack) const { + using namespace boost::graph::keywords; + boost::depth_first_search(g, + arg_pack[_visitor | make_dfs_visitor(null_visitor())], + boost::detail::make_color_map_from_arg_pack(g, arg_pack), + arg_pack[_root_vertex || boost::detail::get_default_starting_vertex_t(g)]); + } + }; + } + BOOST_GRAPH_MAKE_FORWARDING_FUNCTION(depth_first_search, 1, 4) } + BOOST_GRAPH_MAKE_OLD_STYLE_PARAMETER_FUNCTION(depth_first_search, 1) + template void depth_first_visit (const IncidenceGraph& g, diff --git a/include/boost/graph/detail/adjacency_list.hpp b/include/boost/graph/detail/adjacency_list.hpp index 0cbf5f4e9..9e6b623ee 100644 --- a/include/boost/graph/detail/adjacency_list.hpp +++ b/include/boost/graph/detail/adjacency_list.hpp @@ -17,6 +17,7 @@ #include #include #include +#include #include #include #include @@ -35,11 +36,13 @@ #include #include #include +#include -// Symbol truncation problems with MSVC, trying to shorten names. -#define stored_edge se_ -#define stored_edge_property sep_ -#define stored_edge_iter sei_ +#ifdef BOOST_NO_CXX11_RVALUE_REFERENCES +#define BOOST_GRAPH_MOVE_IF_POSSIBLE(x) (x) +#else +#define BOOST_GRAPH_MOVE_IF_POSSIBLE(x) (std::move((x))) +#endif /* Outline for this file: @@ -66,11 +69,6 @@ */ -#if BOOST_WORKAROUND(BOOST_MSVC, < 1300) -// Stay out of the way of the concept checking class -# define Graph Graph_ -#endif - namespace boost { namespace detail { @@ -259,6 +257,7 @@ namespace boost { template no_property stored_edge::s_prop; +#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES) || defined(BOOST_NO_CXX11_DEFAULTED_FUNCTIONS) template class stored_edge_property : public stored_edge { typedef stored_edge_property self; @@ -285,6 +284,25 @@ namespace boost { // a perfect fit for the job, but it is darn close. std::auto_ptr m_property; }; +#else + template + class stored_edge_property : public stored_edge { + typedef stored_edge_property self; + typedef stored_edge Base; + public: + typedef Property property_type; + inline stored_edge_property() { } + inline stored_edge_property(Vertex target, + const Property& p = Property()) + : stored_edge(target), m_property(new Property(p)) { } + stored_edge_property(self&& x) = default; + self& operator=(self&& x) = default; + inline Property& get_property() { return *m_property; } + inline const Property& get_property() const { return *m_property; } + protected: + std::unique_ptr m_property; + }; +#endif template @@ -318,14 +336,16 @@ namespace boost { public: typedef Property property_type; inline stored_ra_edge_iter() { } - inline stored_ra_edge_iter(Vertex v, Iter i = Iter(), - EdgeVec* edge_vec = 0) + inline explicit stored_ra_edge_iter(Vertex v) // Only used for comparisons + : stored_edge(v), m_i(0), m_vec(0){ } + inline stored_ra_edge_iter(Vertex v, Iter i, EdgeVec* edge_vec) : stored_edge(v), m_i(i - edge_vec->begin()), m_vec(edge_vec){ } - inline Property& get_property() { return (*m_vec)[m_i].get_property(); } + inline Property& get_property() { BOOST_ASSERT ((m_vec != 0)); return (*m_vec)[m_i].get_property(); } inline const Property& get_property() const { + BOOST_ASSERT ((m_vec != 0)); return (*m_vec)[m_i].get_property(); } - inline Iter get_iter() const { return m_vec->begin() + m_i; } + inline Iter get_iter() const { BOOST_ASSERT ((m_vec != 0)); return m_vec->begin() + m_i; } protected: std::size_t m_i; EdgeVec* m_vec; @@ -390,7 +410,7 @@ namespace boost { if (first != last) for (++i; i != last; ++i) if (!pred(*i)) { - *first.base() = *i.base(); + *first.base() = BOOST_GRAPH_MOVE_IF_POSSIBLE(*i.base()); ++first; } el.erase(first.base(), el.end()); @@ -438,7 +458,7 @@ namespace boost { self_loop_removed = false; } else if (!pred(*i)) { - *first.base() = *i.base(); + *first.base() = BOOST_GRAPH_MOVE_IF_POSSIBLE(*i.base()); ++first; } else { if (source(*i, g) == target(*i, g)) self_loop_removed = true; @@ -641,7 +661,6 @@ namespace boost { directed_graph_helper& g_) { typedef typename Config::graph_type graph_type; - typedef typename Config::edge_parallel_category Cat; graph_type& g = static_cast(g_); g.out_edge_list(u).clear(); // clear() should be a req of Sequence and AssociativeContainer, @@ -726,8 +745,10 @@ namespace boost { typename Config::OutEdgeList& out_el = g.out_edge_list(source(e, g)); typename Config::OutEdgeList::iterator out_i = out_el.begin(); + typename Config::EdgeIter edge_iter_to_erase; for (; out_i != out_el.end(); ++out_i) if (&(*out_i).get_property() == &p) { + edge_iter_to_erase = (*out_i).get_iter(); out_el.erase(out_i); break; } @@ -735,10 +756,10 @@ namespace boost { typename Config::OutEdgeList::iterator in_i = in_el.begin(); for (; in_i != in_el.end(); ++in_i) if (&(*in_i).get_property() == &p) { - g.m_edges.erase((*in_i).get_iter()); in_el.erase(in_i); - return; + break; } + g.m_edges.erase(edge_iter_to_erase); } }; @@ -759,8 +780,10 @@ namespace boost { no_property* p = (no_property*)e.get_property(); typename Config::OutEdgeList& out_el = g.out_edge_list(source(e, g)); typename Config::OutEdgeList::iterator out_i = out_el.begin(); + typename Config::EdgeIter edge_iter_to_erase; for (; out_i != out_el.end(); ++out_i) if (&(*out_i).get_property() == p) { + edge_iter_to_erase = (*out_i).get_iter(); out_el.erase(out_i); break; } @@ -768,10 +791,10 @@ namespace boost { typename Config::OutEdgeList::iterator in_i = in_el.begin(); for (; in_i != in_el.end(); ++in_i) if (&(*in_i).get_property() == p) { - g.m_edges.erase((*in_i).get_iter()); in_el.erase(in_i); - return; + break; } + g.m_edges.erase(edge_iter_to_erase); } }; @@ -784,7 +807,6 @@ namespace boost { typedef typename Graph::global_edgelist_selector EdgeListS; BOOST_STATIC_ASSERT((!is_same::value)); - typedef typename EdgeList::value_type StoredEdge; typename EdgeList::iterator i = el.begin(), end = el.end(); for (; i != end; ++i) { if ((*i).get_target() == v) { @@ -988,26 +1010,13 @@ namespace boost { BOOST_STATIC_ASSERT((!is_same::value)); typedef typename Config::graph_type graph_type; - typedef typename Config::edge_parallel_category Cat; graph_type& g = static_cast(g_); - typename Config::OutEdgeList& el = g.out_edge_list(u); - typename Config::OutEdgeList::iterator - ei = el.begin(), ei_end = el.end(); - for (; ei != ei_end; /* Increment below */ ) { - bool is_self_loop = (*ei).get_target() == u; - // Don't erase from our own incidence list in the case of a self-loop - // since we're clearing it anyway. - if (!is_self_loop) { - detail::erase_from_incidence_list - (g.out_edge_list((*ei).get_target()), u, Cat()); - typename Config::OutEdgeList::iterator ei_copy = ei; - ++ei; - if (!is_self_loop) g.m_edges.erase((*ei_copy).get_iter()); - } else { - ++ei; - } + while (true) { + typename Config::out_edge_iterator ei, ei_end; + boost::tie(ei, ei_end) = out_edges(u, g); + if (ei == ei_end) break; + remove_edge(*ei, g); } - g.out_edge_list(u).clear(); } // O(1) for allow_parallel_edge_tag // O(log(E/V)) for disallow_parallel_edge_tag @@ -1216,7 +1225,7 @@ namespace boost { std::pair rng = get_parallel_edge_sublist(e, g, (OutEdgeListS*)(0)); rng.first = std::find(rng.first, rng.second, e); - assert(rng.first != rng.second); + BOOST_ASSERT(rng.first != rng.second); remove_edge(rng.first); } @@ -1510,10 +1519,16 @@ namespace boost { typedef typename Config::edges_size_type edges_size_type; typedef typename Config::degree_size_type degree_size_type; typedef typename Config::StoredEdge StoredEdge; + typedef typename Config::vertex_property_type vertex_property_type; typedef typename Config::edge_property_type edge_property_type; + typedef typename Config::graph_property_type graph_property_type; typedef typename Config::global_edgelist_selector global_edgelist_selector; + + typedef typename lookup_one_property::type vertex_bundled; + typedef typename lookup_one_property::type edge_bundled; + typedef typename lookup_one_property::type graph_bundled; }; template @@ -1596,7 +1611,6 @@ namespace boost { typedef typename Config::graph_type Graph; typedef typename Config::StoredEdge StoredEdge; const Graph& cg = static_cast(g_); - typedef typename Config::out_edge_iterator out_edge_iterator; const typename Config::OutEdgeList& el = cg.out_edge_list(u); typename Config::OutEdgeList::const_iterator it = graph_detail:: find(el, StoredEdge(v)); @@ -1622,8 +1636,7 @@ namespace boost { typename Config::OutEdgeList::iterator first, last; typename Config::EdgeContainer fake_edge_container; boost::tie(first, last) = graph_detail:: - equal_range(el, StoredEdge(v, fake_edge_container.end(), - &fake_edge_container)); + equal_range(el, StoredEdge(v)); return std::make_pair(out_edge_iterator(first, u), out_edge_iterator(last, u)); } @@ -1644,43 +1657,43 @@ namespace boost { inline typename boost::property_map::type - get_dispatch(adj_list_helper&, Property, + get_dispatch(adj_list_helper&, Property p, boost::edge_property_tag) { typedef typename Config::graph_type Graph; typedef typename boost::property_map::type PA; - return PA(); + return PA(p); } template inline typename boost::property_map::const_type - get_dispatch(const adj_list_helper&, Property, + get_dispatch(const adj_list_helper&, Property p, boost::edge_property_tag) { typedef typename Config::graph_type Graph; typedef typename boost::property_map::const_type PA; - return PA(); + return PA(p); } template inline typename boost::property_map::type - get_dispatch(adj_list_helper& g, Property, + get_dispatch(adj_list_helper& g, Property p, boost::vertex_property_tag) { typedef typename Config::graph_type Graph; typedef typename boost::property_map::type PA; - return PA(&static_cast(g)); + return PA(&static_cast(g), p); } template inline typename boost::property_map::const_type - get_dispatch(const adj_list_helper& g, Property, + get_dispatch(const adj_list_helper& g, Property p, boost::vertex_property_tag) { typedef typename Config::graph_type Graph; typedef typename boost::property_map::const_type PA; const Graph& cg = static_cast(g); - return PA(&cg); + return PA(&cg, p); } } // namespace detail @@ -1690,7 +1703,7 @@ namespace boost { inline typename boost::property_map::type get(Property p, adj_list_helper& g) { - typedef typename property_kind::type Kind; + typedef typename detail::property_kind_from_graph, Property>::type Kind; return detail::get_dispatch(g, p, Kind()); } template @@ -1698,7 +1711,7 @@ namespace boost { typename boost::property_map::const_type get(Property p, const adj_list_helper& g) { - typedef typename property_kind::type Kind; + typedef typename detail::property_kind_from_graph, Property>::type Kind; return detail::get_dispatch(g, p, Kind()); } @@ -1911,7 +1924,7 @@ namespace boost { { typedef typename Config::stored_vertex stored_vertex; Derived& g = static_cast(g_); - g.removing_vertex(u); + g.removing_vertex(u, boost::graph_detail::iterator_stability(g_.m_vertices)); stored_vertex* su = (stored_vertex*)u; g.m_vertices.erase(su->m_position); delete su; @@ -2211,7 +2224,7 @@ namespace boost { { typedef typename Config::directed_category Cat; Graph& g = static_cast(g_); - g.removing_vertex(v); + g.removing_vertex(v, boost::graph_detail::iterator_stability(g_.m_vertices)); detail::remove_vertex_dispatch(g, v, Cat()); } // O(1) @@ -2426,15 +2439,15 @@ namespace boost { typedef Reference reference; typedef typename Graph::vertex_descriptor key_type; typedef boost::lvalue_property_map_tag category; - inline adj_list_vertex_property_map() { } - inline adj_list_vertex_property_map(const Graph*) { } + inline adj_list_vertex_property_map(const Graph* = 0, Tag tag = Tag()): m_tag(tag) { } inline Reference operator[](key_type v) const { StoredVertex* sv = (StoredVertex*)v; - return get_property_value(sv->m_property, Tag()); + return get_property_value(sv->m_property, m_tag); } inline Reference operator()(key_type v) const { return this->operator[](v); } + Tag m_tag; }; template @@ -2448,8 +2461,7 @@ namespace boost { typedef PropRef reference; typedef typename Graph::vertex_descriptor key_type; typedef boost::lvalue_property_map_tag category; - inline adj_list_vertex_all_properties_map() { } - inline adj_list_vertex_all_properties_map(const Graph*) { } + inline adj_list_vertex_all_properties_map(const Graph* = 0, vertex_all_t = vertex_all_t()) { } inline PropRef operator[](key_type v) const { StoredVertex* sv = (StoredVertex*)v; return sv->m_property; @@ -2472,15 +2484,15 @@ namespace boost { typedef Reference reference; typedef typename boost::graph_traits::vertex_descriptor key_type; typedef boost::lvalue_property_map_tag category; - vec_adj_list_vertex_property_map() { } - vec_adj_list_vertex_property_map(GraphPtr g) : m_g(g) { } + vec_adj_list_vertex_property_map(GraphPtr g = 0, Tag tag = Tag()) : m_g(g), m_tag(tag) { } inline Reference operator[](key_type v) const { - return get_property_value(m_g->m_vertices[v].m_property, Tag()); + return get_property_value(m_g->m_vertices[v].m_property, m_tag); } inline Reference operator()(key_type v) const { return this->operator[](v); } GraphPtr m_g; + Tag m_tag; }; template @@ -2494,8 +2506,7 @@ namespace boost { typedef PropertyRef reference; typedef typename boost::graph_traits::vertex_descriptor key_type; typedef boost::lvalue_property_map_tag category; - vec_adj_list_vertex_all_properties_map() { } - vec_adj_list_vertex_all_properties_map(GraphPtr g) : m_g(g) { } + vec_adj_list_vertex_all_properties_map(GraphPtr g = 0, vertex_all_t = vertex_all_t()) : m_g(g) { } inline PropertyRef operator[](key_type v) const { return m_g->m_vertices[v].m_property; } @@ -2541,7 +2552,7 @@ namespace boost { typedef boost::readable_property_map_tag category; inline vec_adj_list_vertex_id_map() { } template - inline vec_adj_list_vertex_id_map(const Graph&) { } + inline vec_adj_list_vertex_id_map(const Graph&, vertex_index_t) { } inline value_type operator[](key_type v) const { return v; } inline value_type operator()(key_type v) const { return v; } }; @@ -2578,21 +2589,14 @@ namespace boost { }; }; namespace detail { - template - struct adj_list_choose_vertex_pa_helper { - typedef adj_list_any_vertex_pa type; - }; - template <> - struct adj_list_choose_vertex_pa_helper { - typedef adj_list_all_vertex_pa type; - }; template - struct adj_list_choose_vertex_pa { - typedef typename adj_list_choose_vertex_pa_helper::type Helper; - typedef typename Helper::template bind_ Bind; - typedef typename Bind::type type; - typedef typename Bind::const_type const_type; - }; + struct adj_list_choose_vertex_pa + : boost::mpl::if_< + boost::is_same, + adj_list_all_vertex_pa, + adj_list_any_vertex_pa>::type + ::template bind_ + {}; template @@ -2608,12 +2612,9 @@ namespace boost { typedef vec_adj_list_all_vertex_pa type; }; template - struct vec_adj_list_choose_vertex_pa { - typedef typename vec_adj_list_choose_vertex_pa_helper::type Helper; - typedef typename Helper::template bind_ Bind; - typedef typename Bind::type type; - typedef typename Bind::const_type const_type; - }; + struct vec_adj_list_choose_vertex_pa + : vec_adj_list_choose_vertex_pa_helper::type::template bind_ + {}; } // namespace detail //========================================================================= @@ -2628,13 +2629,16 @@ namespace boost { Tag> > { + Tag tag; + explicit adj_list_edge_property_map(Tag tag = Tag()): tag(tag) {} + typedef Value value_type; typedef Ref reference; typedef detail::edge_desc_impl key_type; typedef boost::lvalue_property_map_tag category; inline Ref operator[](key_type e) const { Property& p = *(Property*)e.get_property(); - return get_property_value(p, Tag()); + return get_property_value(p, tag); } inline Ref operator()(key_type e) const { return this->operator[](e); @@ -2649,6 +2653,7 @@ namespace boost { PropPtr, Vertex> > { + explicit adj_list_edge_all_properties_map(edge_all_t = edge_all_t()) {} typedef Property value_type; typedef PropRef reference; typedef detail::edge_desc_impl key_type; @@ -2700,19 +2705,12 @@ namespace boost { typedef adj_list_all_edge_pmap type; }; template - struct adj_list_choose_edge_pmap { - typedef typename adj_list_choose_edge_pmap_helper::type Helper; - typedef typename Helper::template bind_ Bind; - typedef typename Bind::type type; - typedef typename Bind::const_type const_type; - }; + struct adj_list_choose_edge_pmap + : adj_list_choose_edge_pmap_helper::type::template bind_ + {}; struct adj_list_edge_property_selector { template - struct bind_ { - typedef adj_list_choose_edge_pmap Choice; - typedef typename Choice::type type; - typedef typename Choice::const_type const_type; - }; + struct bind_: adj_list_choose_edge_pmap {}; }; } // namespace detail @@ -2729,11 +2727,9 @@ namespace boost { struct adj_list_vertex_property_selector { template - struct bind_ { - typedef detail::adj_list_choose_vertex_pa Choice; - typedef typename Choice::type type; - typedef typename Choice::const_type const_type; - }; + struct bind_ + : detail::adj_list_choose_vertex_pa + {}; }; template <> struct vertex_property_selector { @@ -2742,11 +2738,7 @@ namespace boost { struct vec_adj_list_vertex_property_selector { template - struct bind_ { - typedef detail::vec_adj_list_choose_vertex_pa Choice; - typedef typename Choice::type type; - typedef typename Choice::const_type const_type; - }; + struct bind_: detail::vec_adj_list_choose_vertex_pa {}; }; template <> struct vertex_property_selector { @@ -2755,20 +2747,8 @@ namespace boost { } // namespace boost -#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) namespace boost { - #if BOOST_WORKAROUND( _STLPORT_VERSION, >= 0x500 ) - // STLport 5 already defines a hash specialization. - #else - template <> - struct hash< void* > // Need this when vertex_descriptor=void* - { - std::size_t - operator()(void* v) const { return (std::size_t)v; } - }; - #endif - template struct hash< boost::detail::stored_edge > { @@ -2800,18 +2780,8 @@ namespace boost { }; } -#endif -#undef stored_edge -#undef stored_edge_property -#undef stored_edge_iter - -#if BOOST_WORKAROUND(BOOST_MSVC, < 1300) -// Stay out of the way of the concept checking class -#undef Graph -#endif - #endif // BOOST_GRAPH_DETAIL_DETAIL_ADJACENCY_LIST_CCT /* diff --git a/include/boost/graph/detail/augment.hpp b/include/boost/graph/detail/augment.hpp new file mode 100644 index 000000000..3b20dcc4a --- /dev/null +++ b/include/boost/graph/detail/augment.hpp @@ -0,0 +1,63 @@ +//======================================================================= +// Copyright 2013 University of Warsaw. +// Authors: Piotr Wygocki +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +//======================================================================= + +#ifndef BOOST_GRAPH_AUGMENT_HPP +#define BOOST_GRAPH_AUGMENT_HPP + +#include + +namespace boost { +namespace detail { + +template +filtered_graph > +residual_graph(const Graph& g, ResCapMap residual_capacity) { + return filtered_graph > + (g, is_residual_edge(residual_capacity)); +} + +template +inline void +augment(const Graph& g, + typename graph_traits::vertex_descriptor src, + typename graph_traits::vertex_descriptor sink, + PredEdgeMap p, + ResCapMap residual_capacity, + RevEdgeMap reverse_edge) +{ + typename graph_traits::edge_descriptor e; + typename graph_traits::vertex_descriptor u; + typedef typename property_traits::value_type FlowValue; + + // find minimum residual capacity along the augmenting path + FlowValue delta = (std::numeric_limits::max)(); + e = get(p, sink); + do { + BOOST_USING_STD_MIN(); + delta = min BOOST_PREVENT_MACRO_SUBSTITUTION(delta, get(residual_capacity, e)); + u = source(e, g); + e = get(p, u); + } while (u != src); + + // push delta units of flow along the augmenting path + e = get(p, sink); + do { + put(residual_capacity, e, get(residual_capacity, e) - delta); + put(residual_capacity, get(reverse_edge, e), get(residual_capacity, get(reverse_edge, e)) + delta); + u = source(e, g); + e = get(p, u); + } while (u != src); +} + +} // namespace detail +} //namespace boost + +#endif /* BOOST_GRAPH_AUGMENT_HPP */ + diff --git a/include/boost/graph/detail/compressed_sparse_row_struct.hpp b/include/boost/graph/detail/compressed_sparse_row_struct.hpp index 4fb3c2269..6e7b60d74 100644 --- a/include/boost/graph/detail/compressed_sparse_row_struct.hpp +++ b/include/boost/graph/detail/compressed_sparse_row_struct.hpp @@ -21,7 +21,7 @@ #include #include #include -#include +#include #include #if 0 #include // For some debugging code below @@ -44,7 +44,6 @@ #include #include #include -#include namespace boost { @@ -219,8 +218,6 @@ namespace detail { // the user has supplied the number of edges. edges_size_type numedges = numedges_or_zero; if (numedges == 0) { - typedef typename std::iterator_traits::iterator_category - category; numedges = boost::graph::detail::reserve_count_for_single_pass(edge_begin, edge_end); } m_column.clear(); @@ -255,7 +252,7 @@ namespace detail { std::vector& targets, vertices_size_type numverts, GlobalToLocal global_to_local) { - assert (sources.size() == targets.size()); + BOOST_ASSERT (sources.size() == targets.size()); // Do an in-place histogram sort (at least that's what I think it is) to // sort sources and targets m_rowstart.clear(); @@ -281,8 +278,8 @@ namespace detail { std::vector& edge_props, vertices_size_type numverts, GlobalToLocal global_to_local) { - assert (sources.size() == targets.size()); - assert (sources.size() == edge_props.size()); + BOOST_ASSERT (sources.size() == targets.size()); + BOOST_ASSERT (sources.size() == edge_props.size()); // Do an in-place histogram sort (at least that's what I think it is) to // sort sources and targets m_rowstart.clear(); @@ -314,7 +311,6 @@ namespace detail { inherited_edge_properties::resize(numedges); EdgeIndex current_edge = 0; typedef typename boost::graph_traits::vertex_descriptor g_vertex; - typedef typename boost::graph_traits::edge_descriptor g_edge; typedef typename boost::graph_traits::out_edge_iterator g_out_edge_iter; @@ -348,7 +344,6 @@ namespace detail { // Flip sequence BidirectionalIterator first(last_sorted); BidirectionalIterator last(first_sorted); - typedef Vertex vertex_t; typedef Vertex vertex_num; typedef EdgeIndex edge_num; edge_num new_edge_count = std::distance(first, last); diff --git a/include/boost/graph/detail/d_ary_heap.hpp b/include/boost/graph/detail/d_ary_heap.hpp index c3b3ef7fd..cf930fc18 100644 --- a/include/boost/graph/detail/d_ary_heap.hpp +++ b/include/boost/graph/detail/d_ary_heap.hpp @@ -15,11 +15,16 @@ #include #include #include -#include +#include #include #include #include +// WARNING: it is not safe to copy a d_ary_heap_indirect and then modify one of +// the copies. The class is required to be copyable so it can be passed around +// (without move support from C++11), but it deep-copies the heap contents yet +// shallow-copies the index_in_heap_map. + namespace boost { // Swap two elements in a property map without assuming they model @@ -121,18 +126,21 @@ namespace boost { } Value& top() { + BOOST_ASSERT (!this->empty()); return data[0]; } const Value& top() const { + BOOST_ASSERT (!this->empty()); return data[0]; } void pop() { + BOOST_ASSERT (!this->empty()); put(index_in_heap, data[0], (size_type)(-1)); if (data.size() != 1) { data[0] = data.back(); - put(index_in_heap, data[0], 0); + put(index_in_heap, data[0], (size_type)(0)); data.pop_back(); preserve_heap_property_down(); verify_heap(); @@ -213,7 +221,7 @@ namespace boost { #if 0 for (size_t i = 1; i < data.size(); ++i) { if (compare_indirect(data[i], data[parent(i)])) { - assert (!"Element is smaller than its parent"); + BOOST_ASSERT (!"Element is smaller than its parent"); } } #endif diff --git a/include/boost/graph/detail/edge.hpp b/include/boost/graph/detail/edge.hpp index da085973a..badf28d4f 100644 --- a/include/boost/graph/detail/edge.hpp +++ b/include/boost/graph/detail/edge.hpp @@ -11,11 +11,7 @@ #ifndef BOOST_GRAPH_DETAIL_EDGE_HPP #define BOOST_GRAPH_DETAIL_EDGE_HPP -#if __GNUC__ < 3 -#include -#else #include -#endif namespace boost { @@ -100,15 +96,6 @@ namespace boost { } // namespace boost namespace std { - -#if __GNUC__ < 3 - template - std::ostream& - operator<<(std::ostream& os, const boost::detail::edge_desc_impl& e) - { - return os << "(" << e.m_source << "," << e.m_target << ")"; - } -#else template std::basic_ostream& operator<<(std::basic_ostream& os, @@ -116,8 +103,16 @@ namespace std { { return os << "(" << e.m_source << "," << e.m_target << ")"; } -#endif +} +// Boost's functional/hash +namespace boost { + template + struct hash > + { + std::size_t operator()(const boost::detail::edge_desc_impl & x) const + { return hash_value(x.get_property()); } + }; } diff --git a/include/boost/graph/detail/geodesic.hpp b/include/boost/graph/detail/geodesic.hpp index 99edaf9e3..adcb17f0a 100644 --- a/include/boost/graph/detail/geodesic.hpp +++ b/include/boost/graph/detail/geodesic.hpp @@ -11,6 +11,7 @@ #include #include #include +#include // TODO: Should this really be in detail? @@ -51,13 +52,13 @@ namespace detail { Combinator combine, Distance init) { - function_requires< VertexListGraphConcept >(); + BOOST_CONCEPT_ASSERT(( VertexListGraphConcept )); typedef typename graph_traits::vertex_descriptor Vertex; typedef typename graph_traits::vertex_iterator VertexIterator; - function_requires< ReadablePropertyMapConcept >(); - function_requires< NumericValueConcept >(); + BOOST_CONCEPT_ASSERT(( ReadablePropertyMapConcept )); + BOOST_CONCEPT_ASSERT(( NumericValueConcept )); typedef numeric_values DistanceNumbers; - function_requires< AdaptableBinaryFunction >(); + BOOST_CONCEPT_ASSERT(( AdaptableBinaryFunction )); // If there's ever an infinite distance, then we simply return // infinity. Note that this /will/ include the a non-zero @@ -65,7 +66,7 @@ namespace detail { // zero, so it shouldn't be too problematic. Distance ret = init; VertexIterator i, end; - for(tie(i, end) = vertices(g); i != end; ++i) { + for(boost::tie(i, end) = vertices(g); i != end; ++i) { Vertex v = *i; if(get(dist, v) != DistanceNumbers::infinity()) { ret = combine(ret, get(dist, v)); diff --git a/include/boost/graph/detail/histogram_sort.hpp b/include/boost/graph/detail/histogram_sort.hpp index 742c6f963..ef0363563 100644 --- a/include/boost/graph/detail/histogram_sort.hpp +++ b/include/boost/graph/detail/histogram_sort.hpp @@ -10,6 +10,8 @@ #ifndef BOOST_GRAPH_DETAIL_HISTOGRAM_SORT_HPP #define BOOST_GRAPH_DETAIL_HISTOGRAM_SORT_HPP +#include + namespace boost { namespace graph { namespace detail { @@ -52,12 +54,12 @@ count_starts KeyFilter key_filter, KeyTransform key_transform) { - typedef VerticesSize vertices_size_type; typedef typename std::iterator_traits::value_type EdgeIndex; // Put the degree of each vertex v into m_rowstart[v + 1] for (KeyIterator i = begin; i != end; ++i) { if (key_filter(*i)) { + BOOST_ASSERT (key_transform(*i) < numkeys); ++starts[key_transform(*i) + 1]; } } @@ -66,7 +68,7 @@ count_starts // m_rowstart EdgeIndex start_of_this_row = 0; starts[0] = start_of_this_row; - for (vertices_size_type i = 1; i <= numkeys; ++i) { + for (VerticesSize i = 1; i < numkeys + 1; ++i) { start_of_this_row += starts[i]; starts[i] = start_of_this_row; } @@ -85,7 +87,6 @@ histogram_sort(KeyIterator key_begin, KeyIterator key_end, KeyFilter key_filter, KeyTransform key_transform) { - typedef NumKeys vertices_size_type; typedef typename std::iterator_traits::value_type EdgeIndex; // Histogram sort the edges by their source vertices, putting the targets @@ -96,7 +97,8 @@ histogram_sort(KeyIterator key_begin, KeyIterator key_end, Value1InputIter v1i = values1_begin; for (KeyIterator i = key_begin; i != key_end; ++i, ++v1i) { if (key_filter(*i)) { - vertices_size_type source = key_transform(*i); + NumKeys source = key_transform(*i); + BOOST_ASSERT (source < numkeys); EdgeIndex insert_pos = current_insert_positions[source]; ++current_insert_positions[source]; values1_out[insert_pos] = *v1i; @@ -122,7 +124,6 @@ histogram_sort(KeyIterator key_begin, KeyIterator key_end, KeyFilter key_filter, KeyTransform key_transform) { - typedef NumKeys vertices_size_type; typedef typename std::iterator_traits::value_type EdgeIndex; // Histogram sort the edges by their source vertices, putting the targets @@ -134,7 +135,8 @@ histogram_sort(KeyIterator key_begin, KeyIterator key_end, Value2InputIter v2i = values2_begin; for (KeyIterator i = key_begin; i != key_end; ++i, ++v1i, ++v2i) { if (key_filter(*i)) { - vertices_size_type source = key_transform(*i); + NumKeys source = key_transform(*i); + BOOST_ASSERT (source < numkeys); EdgeIndex insert_pos = current_insert_positions[source]; ++current_insert_positions[source]; values1_out[insert_pos] = *v1i; @@ -154,18 +156,18 @@ histogram_sort_inplace(KeyIterator key_begin, Value1Iter values1, KeyTransform key_transform) { - typedef NumKeys vertices_size_type; typedef typename std::iterator_traits::value_type EdgeIndex; // 1. Copy m_rowstart (except last element) to get insert positions std::vector insert_positions(rowstart, rowstart + numkeys); // 2. Swap the sources and targets into place for (size_t i = 0; i < rowstart[numkeys]; ++i) { + BOOST_ASSERT (key_transform(key_begin[i]) < numkeys); // While edge i is not in the right bucket: while (!(i >= rowstart[key_transform(key_begin[i])] && i < insert_positions[key_transform(key_begin[i])])) { // Add a slot in the right bucket size_t target_pos = insert_positions[key_transform(key_begin[i])]++; - assert (target_pos < rowstart[key_transform(key_begin[i]) + 1]); + BOOST_ASSERT (target_pos < rowstart[key_transform(key_begin[i]) + 1]); if (target_pos == i) continue; // Swap this edge into place using std::swap; @@ -188,18 +190,18 @@ histogram_sort_inplace(KeyIterator key_begin, Value2Iter values2, KeyTransform key_transform) { - typedef NumKeys vertices_size_type; typedef typename std::iterator_traits::value_type EdgeIndex; // 1. Copy m_rowstart (except last element) to get insert positions std::vector insert_positions(rowstart, rowstart + numkeys); // 2. Swap the sources and targets into place for (size_t i = 0; i < rowstart[numkeys]; ++i) { + BOOST_ASSERT (key_transform(key_begin[i]) < numkeys); // While edge i is not in the right bucket: while (!(i >= rowstart[key_transform(key_begin[i])] && i < insert_positions[key_transform(key_begin[i])])) { // Add a slot in the right bucket size_t target_pos = insert_positions[key_transform(key_begin[i])]++; - assert (target_pos < rowstart[key_transform(key_begin[i]) + 1]); + BOOST_ASSERT (target_pos < rowstart[key_transform(key_begin[i]) + 1]); if (target_pos == i) continue; // Swap this edge into place using std::swap; @@ -267,16 +269,21 @@ void split_into_separate_coords_filtered } } +// The versions of operator()() here can't return by reference because the +// actual type passed in may not match Pair, in which case the reference +// parameter is bound to a temporary that could end up dangling after the +// operator returns. + template struct project1st { typedef typename Pair::first_type result_type; - const result_type& operator()(const Pair& p) const {return p.first;} + result_type operator()(const Pair& p) const {return p.first;} }; template struct project2nd { typedef typename Pair::second_type result_type; - const result_type& operator()(const Pair& p) const {return p.second;} + result_type operator()(const Pair& p) const {return p.second;} }; } diff --git a/include/boost/graph/detail/indexed_properties.hpp b/include/boost/graph/detail/indexed_properties.hpp index e1f874b2c..4494625c6 100644 --- a/include/boost/graph/detail/indexed_properties.hpp +++ b/include/boost/graph/detail/indexed_properties.hpp @@ -253,7 +253,7 @@ class indexed_edge_properties typedef secret const_edge_map_type; secret operator[](secret) { return secret(); } - void write_by_index(std::size_t idx, const no_property& prop) {} + void write_by_index(std::size_t /*idx*/, const no_property& /*prop*/) {} edge_map_type get_edge_bundle(const IndexMap& = IndexMap()) const { return edge_map_type(); @@ -270,7 +270,7 @@ class indexed_edge_properties public: void push_back(const edge_push_back_type&) { } - void move_range(std::size_t src_begin, std::size_t src_end, std::size_t dest_begin) {} + void move_range(std::size_t /*src_begin*/, std::size_t /*src_end*/, std::size_t /*dest_begin*/) {} typedef dummy_no_property_iterator iterator; iterator begin() {return dummy_no_property_iterator();} diff --git a/include/boost/graph/detail/is_distributed_selector.hpp b/include/boost/graph/detail/is_distributed_selector.hpp new file mode 100644 index 000000000..4319d9d89 --- /dev/null +++ b/include/boost/graph/detail/is_distributed_selector.hpp @@ -0,0 +1,26 @@ +// Copyright 2012 The Trustees of Indiana University. + +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// Authors: Jeremiah Willcock +// Andrew Lumsdaine + +// Selector to determine whether a selector is distributedS (can only be true +// if has been included) so that we can +// disable various sequential-graph-only traits specializations for distributed +// graphs. + +#ifndef BOOST_GRAPH_DETAIL_IS_DISTRIBUTED_SELECTOR_HPP +#define BOOST_GRAPH_DETAIL_IS_DISTRIBUTED_SELECTOR_HPP + +#include + +namespace boost { + namespace detail { + template struct is_distributed_selector: boost::mpl::false_ {}; + } +} + +#endif // BOOST_GRAPH_DETAIL_IS_DISTRIBUTED_SELECTOR_HPP diff --git a/include/boost/graph/detail/is_same.hpp b/include/boost/graph/detail/is_same.hpp deleted file mode 100644 index 07330d301..000000000 --- a/include/boost/graph/detail/is_same.hpp +++ /dev/null @@ -1,48 +0,0 @@ -//======================================================================= -// Copyright 1997, 1998, 1999, 2000 University of Notre Dame. -// Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek -// -// Distributed under the Boost Software License, Version 1.0. (See -// accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -//======================================================================= -#ifndef BOOST_GRAPH_DETAIL_IS_SAME_HPP -#define BOOST_GRAPH_DETAIL_IS_SAME_HPP - -// Deprecate the use of this header. -// TODO: Remove this file from trunk/release in 1.41/1.42. -#if defined(_MSC_VER) || defined(__BORLANDC__) || defined(__DMC__) -# pragma message ("Warning: This header is deprecated. Please use: boost/type_traits/is_same.hpp") -#elif defined(__GNUC__) || defined(__HP_aCC) || defined(__SUNPRO_CC) || defined(__IBMCPP__) -# warning "This header is deprecated. Please use: boost/type_traits/is_same.hpp" -#endif - -#include - -namespace boost { - struct false_tag; - struct true_tag; - - namespace graph_detail { - -#if !defined BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION - template - struct is_same { - typedef boost::false_tag is_same_tag; - }; - template - struct is_same { - typedef boost::true_tag is_same_tag; - }; -#else - template - struct is_same { - enum { Unum = U::num, Vnum = V::num }; - typedef typename mpl::if_c< (Unum == Vnum), - boost::true_tag, boost::false_tag>::type is_same_tag; - }; -#endif - } // namespace graph_detail -} // namespace boost - -#endif diff --git a/include/boost/graph/detail/labeled_graph_traits.hpp b/include/boost/graph/detail/labeled_graph_traits.hpp index 6eb106093..a0c0973f9 100644 --- a/include/boost/graph/detail/labeled_graph_traits.hpp +++ b/include/boost/graph/detail/labeled_graph_traits.hpp @@ -218,9 +218,9 @@ namespace graph_detail { #define LABELED_GRAPH_PARAMS typename G, typename L, typename S #define LABELED_GRAPH labeled_graph -// Specialize mutability traits for for the labeled graph. +// Specialize mutability traits for the labeled graph. // This specialization depends on the mutability of the underlying graph type. -// If the underlying graph is fully mutable, this this is also fully mutable. +// If the underlying graph is fully mutable, this is also fully mutable. // Otherwise, it's different. template struct graph_mutability_traits< LABELED_GRAPH > { diff --git a/include/boost/graph/detail/read_graphviz_spirit.hpp b/include/boost/graph/detail/read_graphviz_spirit.hpp index 4e8b22e5e..994646988 100644 --- a/include/boost/graph/detail/read_graphviz_spirit.hpp +++ b/include/boost/graph/detail/read_graphviz_spirit.hpp @@ -604,7 +604,9 @@ bool read_graphviz_spirit(MultiPassIterator begin, MultiPassIterator end, scanner_t scan(begin, end, policies); - return p.parse(scan); + bool ok = p.parse(scan); + m_graph.finish_building_graph(); + return ok; } } // namespace boost diff --git a/include/boost/graph/detail/set_adaptor.hpp b/include/boost/graph/detail/set_adaptor.hpp index 90a64a2cd..33acc07e3 100644 --- a/include/boost/graph/detail/set_adaptor.hpp +++ b/include/boost/graph/detail/set_adaptor.hpp @@ -111,7 +111,7 @@ namespace boost { // Shit, can't implement this without knowing the size of the // universe. template - void set_compliment(const std::set& x, + void set_compliment(const std::set& /*x*/, std::set& z) { z.clear(); diff --git a/include/boost/graph/dijkstra_shortest_paths.hpp b/include/boost/graph/dijkstra_shortest_paths.hpp index 5b39cb385..10e40f828 100644 --- a/include/boost/graph/dijkstra_shortest_paths.hpp +++ b/include/boost/graph/dijkstra_shortest_paths.hpp @@ -30,6 +30,7 @@ #include #include #include +#include #ifdef BOOST_GRAPH_DIJKSTRA_TESTING # include @@ -68,7 +69,7 @@ namespace boost { template struct DijkstraVisitorConcept { void constraints() { - function_requires< CopyConstructibleConcept >(); + BOOST_CONCEPT_ASSERT(( CopyConstructibleConcept )); vis.initialize_vertex(u, g); vis.discover_vertex(u, g); vis.examine_vertex(u, g); @@ -117,6 +118,7 @@ namespace boost { struct dijkstra_bfs_visitor { typedef typename property_traits::value_type D; + typedef typename property_traits::value_type W; dijkstra_bfs_visitor(UniformCostVisitor vis, UpdatableQueue& Q, WeightMap w, PredecessorMap p, DistanceMap d, @@ -158,9 +160,39 @@ namespace boost { void examine_vertex(Vertex u, Graph& g) { m_vis.examine_vertex(u, g); } template void examine_edge(Edge e, Graph& g) { - if (m_compare(get(m_weight, e), m_zero)) + // Test for negative-weight edges: + // + // Reasons that other comparisons do not work: + // + // m_compare(e_weight, D(0)): + // m_compare only needs to work on distances, not weights, and those + // types do not need to be the same (bug 8398, + // https://svn.boost.org/trac/boost/ticket/8398). + // m_compare(m_combine(source_dist, e_weight), source_dist): + // if m_combine is project2nd (as in prim_minimum_spanning_tree), + // this test will claim that the edge weight is negative whenever + // the edge weight is less than source_dist, even if both of those + // are positive (bug 9012, + // https://svn.boost.org/trac/boost/ticket/9012). + // m_compare(m_combine(e_weight, source_dist), source_dist): + // would fix project2nd issue, but documentation only requires that + // m_combine be able to take a distance and a weight (in that order) + // and return a distance. + + // W e_weight = get(m_weight, e); + // sd_plus_ew = source_dist + e_weight. + // D sd_plus_ew = m_combine(source_dist, e_weight); + // sd_plus_2ew = source_dist + 2 * e_weight. + // D sd_plus_2ew = m_combine(sd_plus_ew, e_weight); + // The test here is equivalent to e_weight < 0 if m_combine has a + // cancellation law, but always returns false when m_combine is a + // projection operator. + if (m_compare(m_combine(m_zero, get(m_weight, e)), m_zero)) boost::throw_exception(negative_edge()); + // End of test for negative-weight edges. + m_vis.examine_edge(e, g); + } template void black_target(Edge, Graph&) { } @@ -251,14 +283,14 @@ namespace boost { } // Call breadth first search with default color map. - template inline void dijkstra_shortest_paths_no_init (const Graph& g, - typename graph_traits::vertex_descriptor s, + SourceInputIter s_begin, SourceInputIter s_end, PredecessorMap predecessor, DistanceMap distance, WeightMap weight, IndexMap index_map, Compare compare, Combine combine, DistZero zero, @@ -270,16 +302,16 @@ namespace boost { typedef typename ColorMapHelper::type ColorMap; ColorMap color = ColorMapHelper::build(g, index_map); - dijkstra_shortest_paths_no_init( g, s, predecessor, distance, weight, + dijkstra_shortest_paths_no_init( g, s_begin, s_end, predecessor, distance, weight, index_map, compare, combine, zero, vis, color); } - // Call breadth first search + // Call breadth first search with default color map. template + class DistZero> inline void dijkstra_shortest_paths_no_init (const Graph& g, @@ -287,6 +319,25 @@ namespace boost { PredecessorMap predecessor, DistanceMap distance, WeightMap weight, IndexMap index_map, Compare compare, Combine combine, DistZero zero, + DijkstraVisitor vis) + { + dijkstra_shortest_paths_no_init(g, &s, &s + 1, predecessor, distance, + weight, index_map, compare, combine, zero, + vis); + } + + // Call breadth first search + template + inline void + dijkstra_shortest_paths_no_init + (const Graph& g, + SourceInputIter s_begin, SourceInputIter s_end, + PredecessorMap predecessor, DistanceMap distance, WeightMap weight, + IndexMap index_map, + Compare compare, Combine combine, DistZero zero, DijkstraVisitor vis, ColorMap color) { typedef indirect_cmp IndirectCmp; @@ -304,7 +355,7 @@ namespace boost { PredecessorMap, DistanceMap, Combine, Compare> bfs_vis(vis, Q, weight, predecessor, distance, combine, compare, zero); - breadth_first_visit(g, s, Q, bfs_vis, color); + breadth_first_visit(g, s_begin, s_end, Q, bfs_vis, color); return; } #endif // BOOST_GRAPH_DIJKSTRA_TESTING @@ -329,11 +380,30 @@ namespace boost { PredecessorMap, DistanceMap, Combine, Compare> bfs_vis(vis, Q, weight, predecessor, distance, combine, compare, zero); - breadth_first_visit(g, s, Q, bfs_vis, color); + breadth_first_visit(g, s_begin, s_end, Q, bfs_vis, color); + } + + // Call breadth first search + template + inline void + dijkstra_shortest_paths_no_init + (const Graph& g, + typename graph_traits::vertex_descriptor s, + PredecessorMap predecessor, DistanceMap distance, WeightMap weight, + IndexMap index_map, + Compare compare, Combine combine, DistZero zero, + DijkstraVisitor vis, ColorMap color) + { + dijkstra_shortest_paths_no_init(g, &s, &s + 1, predecessor, distance, + weight, index_map, compare, combine, + zero, vis, color); } // Initialize distances and call breadth first search with default color map - template ::vertex_descriptor s, + SourceInputIter s_begin, SourceInputIter s_end, PredecessorMap predecessor, DistanceMap distance, WeightMap weight, IndexMap index_map, Compare compare, Combine combine, DistInf inf, DistZero zero, @@ -350,16 +420,17 @@ namespace boost { BOOST_GRAPH_ENABLE_IF_MODELS_PARM(VertexListGraph,vertex_list_graph_tag)) { boost::two_bit_color_map color(num_vertices(g), index_map); - dijkstra_shortest_paths(g, s, predecessor, distance, weight, index_map, - compare, combine, inf, zero, vis, + dijkstra_shortest_paths(g, s_begin, s_end, predecessor, distance, weight, + index_map, compare, combine, inf, zero, vis, color); } - // Initialize distances and call breadth first search + // Initialize distances and call breadth first search with default color map template + class DistInf, class DistZero, typename T, typename Tag, + typename Base> inline void dijkstra_shortest_paths (const VertexListGraph& g, @@ -367,6 +438,26 @@ namespace boost { PredecessorMap predecessor, DistanceMap distance, WeightMap weight, IndexMap index_map, Compare compare, Combine combine, DistInf inf, DistZero zero, + DijkstraVisitor vis, + const bgl_named_params& + BOOST_GRAPH_ENABLE_IF_MODELS_PARM(VertexListGraph,vertex_list_graph_tag)) + { + dijkstra_shortest_paths(g, &s, &s + 1, predecessor, distance, weight, + index_map, compare, combine, inf, zero, vis); + } + + // Initialize distances and call breadth first search + template + inline void + dijkstra_shortest_paths + (const VertexListGraph& g, + SourceInputIter s_begin, SourceInputIter s_end, + PredecessorMap predecessor, DistanceMap distance, WeightMap weight, + IndexMap index_map, + Compare compare, Combine combine, DistInf inf, DistZero zero, DijkstraVisitor vis, ColorMap color) { typedef typename property_traits::value_type ColorValue; @@ -378,17 +469,20 @@ namespace boost { put(predecessor, *ui, *ui); put(color, *ui, Color::white()); } - put(distance, s, zero); + for (SourceInputIter it = s_begin; it != s_end; ++it) { + put(distance, *it, zero); + } - dijkstra_shortest_paths_no_init(g, s, predecessor, distance, weight, - index_map, compare, combine, zero, vis, color); + dijkstra_shortest_paths_no_init(g, s_begin, s_end, predecessor, distance, + weight, index_map, compare, combine, zero, vis, + color); } // Initialize distances and call breadth first search template + class DistInf, class DistZero, class ColorMap> inline void dijkstra_shortest_paths (const VertexListGraph& g, @@ -396,13 +490,53 @@ namespace boost { PredecessorMap predecessor, DistanceMap distance, WeightMap weight, IndexMap index_map, Compare compare, Combine combine, DistInf inf, DistZero zero, + DijkstraVisitor vis, ColorMap color) + { + dijkstra_shortest_paths(g, &s, &s + 1, predecessor, distance, weight, + index_map, compare, combine, inf, zero, + vis, color); + } + + // Initialize distances and call breadth first search + template + inline void + dijkstra_shortest_paths + (const VertexListGraph& g, + SourceInputIter s_begin, SourceInputIter s_end, + PredecessorMap predecessor, DistanceMap distance, WeightMap weight, + IndexMap index_map, + Compare compare, Combine combine, DistInf inf, DistZero zero, DijkstraVisitor vis) { - dijkstra_shortest_paths(g, s, predecessor, distance, weight, index_map, + dijkstra_shortest_paths(g, s_begin, s_end, predecessor, distance, + weight, index_map, compare, combine, inf, zero, vis, no_named_parameters()); } + // Initialize distances and call breadth first search + template + inline void + dijkstra_shortest_paths + (const VertexListGraph& g, + typename graph_traits::vertex_descriptor s, + PredecessorMap predecessor, DistanceMap distance, WeightMap weight, + IndexMap index_map, + Compare compare, Combine combine, DistInf inf, DistZero zero, + DijkstraVisitor vis) + { + dijkstra_shortest_paths(g, &s, &s + 1, predecessor, distance, + weight, index_map, + compare, combine, inf, zero, vis); + } + namespace detail { // Handle defaults for PredecessorMap and @@ -420,6 +554,9 @@ namespace boost { dummy_property_map p_map; typedef typename property_traits::value_type D; + D inf = choose_param(get_param(params, distance_inf_t()), + (std::numeric_limits::max)()); + dijkstra_shortest_paths (g, s, choose_param(get_param(params, vertex_predecessor), p_map), @@ -427,9 +564,8 @@ namespace boost { choose_param(get_param(params, distance_compare_t()), std::less()), choose_param(get_param(params, distance_combine_t()), - closed_plus()), - choose_param(get_param(params, distance_inf_t()), - (std::numeric_limits::max)()), + closed_plus(inf)), + inf, choose_param(get_param(params, distance_zero_t()), D()), choose_param(get_param(params, graph_visitor), diff --git a/include/boost/graph/dijkstra_shortest_paths_no_color_map.hpp b/include/boost/graph/dijkstra_shortest_paths_no_color_map.hpp index 443984ff0..b1a9ef589 100644 --- a/include/boost/graph/dijkstra_shortest_paths_no_color_map.hpp +++ b/include/boost/graph/dijkstra_shortest_paths_no_color_map.hpp @@ -41,7 +41,6 @@ namespace boost { { typedef typename graph_traits::vertex_descriptor Vertex; typedef typename property_traits::value_type Distance; - typedef typename property_traits::value_type Weight; typedef indirect_cmp DistanceIndirectCompare; DistanceIndirectCompare @@ -92,7 +91,6 @@ namespace boost { } // Examine neighbors of min_vertex - typedef typename graph_traits::edge_descriptor Edge; BGL_FORALL_OUTEDGES_T(min_vertex, current_edge, graph, Graph) { visitor.examine_edge(current_edge, graph); @@ -113,16 +111,17 @@ namespace boost { distance_weight_combine, distance_compare); if (was_edge_relaxed) { - vertex_queue.update(neighbor_vertex); visitor.edge_relaxed(current_edge, graph); + if (is_neighbor_undiscovered) { + visitor.discover_vertex(neighbor_vertex, graph); + vertex_queue.push(neighbor_vertex); + } else { + vertex_queue.update(neighbor_vertex); + } } else { visitor.edge_not_relaxed(current_edge, graph); } - if (is_neighbor_undiscovered) { - visitor.discover_vertex(neighbor_vertex, graph); - vertex_queue.push(neighbor_vertex); - } } // end out edge iteration visitor.finish_vertex(min_vertex, graph); @@ -186,6 +185,9 @@ namespace boost { dummy_property_map predecessor_map; typedef typename property_traits::value_type DistanceType; + DistanceType inf = + choose_param(get_param(params, distance_inf_t()), + (std::numeric_limits::max)()); dijkstra_shortest_paths_no_color_map (graph, start_vertex, choose_param(get_param(params, vertex_predecessor), predecessor_map), @@ -193,9 +195,8 @@ namespace boost { choose_param(get_param(params, distance_compare_t()), std::less()), choose_param(get_param(params, distance_combine_t()), - closed_plus()), - choose_param(get_param(params, distance_inf_t()), - (std::numeric_limits::max)()), + closed_plus(inf)), + inf, choose_param(get_param(params, distance_zero_t()), DistanceType()), choose_param(get_param(params, graph_visitor), diff --git a/include/boost/graph/dimacs.hpp b/include/boost/graph/dimacs.hpp index 195ad3b65..3e8407dfa 100644 --- a/include/boost/graph/dimacs.hpp +++ b/include/boost/graph/dimacs.hpp @@ -17,6 +17,7 @@ #include #include #include +#include namespace boost { namespace graph { @@ -54,27 +55,27 @@ class dimacs_basic_reader { num_edges( 0 ), seen_edges( 0 ), want_weights(false) {} edge_type edge_deref() { - assert( !read_edges.empty() ); + BOOST_ASSERT( !read_edges.empty() ); return read_edges.front(); } inline edge_type* edge_ref() { - assert( !read_edges.empty() ); + BOOST_ASSERT( !read_edges.empty() ); return &read_edges.front(); } inline edge_weight_type edge_weight_deref() { - assert( !read_edge_weights.empty() ); + BOOST_ASSERT( !read_edge_weights.empty() ); return read_edge_weights.front(); } inline dimacs_basic_reader incr( incr_mode mode ) { if( mode == edge ) { - assert( !read_edges.empty() ); + BOOST_ASSERT( !read_edges.empty() ); read_edges.pop(); } else if( mode == edge_weight ) { - assert( !read_edge_weights.empty() ); + BOOST_ASSERT( !read_edge_weights.empty() ); read_edge_weights.pop(); } @@ -100,8 +101,8 @@ class dimacs_basic_reader { read_edge_weights.push( weight ); } } - assert( read_edges.size() < 100 ); - assert( read_edge_weights.size() < 100 ); + BOOST_ASSERT( read_edges.size() < 100 ); + BOOST_ASSERT( read_edge_weights.size() < 100 ); } // the 1000000 just happens to be about how many edges can be read in diff --git a/include/boost/graph/directed_graph.hpp b/include/boost/graph/directed_graph.hpp index 992546d46..585308d18 100644 --- a/include/boost/graph/directed_graph.hpp +++ b/include/boost/graph/directed_graph.hpp @@ -7,9 +7,12 @@ #ifndef BOOST_GRAPH_DIRECTED_GRAPH_HPP #define BOOST_GRAPH_DIRECTED_GRAPH_HPP -#include #include #include +#include +#include +#include +#include namespace boost { @@ -28,29 +31,26 @@ struct directed_graph_tag { }; */ template < typename VertexProp = no_property, - typename EdgeProp= no_property, - typename GraphProp= no_property> + typename EdgeProp = no_property, + typename GraphProp = no_property> class directed_graph { public: - typedef typename graph_detail::graph_prop::property graph_property_type; - typedef typename graph_detail::graph_prop::bundle graph_bundled; - - typedef typename graph_detail::vertex_prop::property vertex_property_type; - typedef typename graph_detail::vertex_prop::bundle vertex_bundled; - - typedef typename graph_detail::edge_prop::property edge_property_type; - typedef typename graph_detail::edge_prop::bundle edge_bundled; - -private: - // Wrap the user-specified properties with an index. - typedef property vertex_property; - typedef property edge_property; + typedef GraphProp graph_property_type; + typedef VertexProp vertex_property_type; + typedef EdgeProp edge_property_type; + typedef typename lookup_one_property::type graph_bundled; + typedef typename lookup_one_property::type vertex_bundled; + typedef typename lookup_one_property::type edge_bundled; +public: + // Embed indices into the vertex type. + typedef property internal_vertex_property; + typedef property internal_edge_property; public: typedef adjacency_list< listS, listS, bidirectionalS, - vertex_property, edge_property, GraphProp, + internal_vertex_property, internal_edge_property, GraphProp, listS > graph_type; @@ -83,8 +83,8 @@ class directed_graph typedef typename graph_type::edge_parallel_category edge_parallel_category; typedef typename graph_type::traversal_category traversal_category; - typedef unsigned vertex_index_type; - typedef unsigned edge_index_type; + typedef std::size_t vertex_index_type; + typedef std::size_t edge_index_type; directed_graph(GraphProp const& p = GraphProp()) : m_graph(p), m_num_vertices(0), m_num_edges(0), m_max_vertex_index(0) @@ -140,6 +140,7 @@ class directed_graph vertices_size_type num_vertices() const { return m_num_vertices; } + private: // This helper function manages the attribution of vertex indices. vertex_descriptor make_index(vertex_descriptor v) { @@ -153,7 +154,7 @@ class directed_graph { return make_index(boost::add_vertex(m_graph)); } vertex_descriptor add_vertex(vertex_property_type const& p) - { return make_index(boost::add_vertex(vertex_property(0u, p), m_graph)); } + { return make_index(boost::add_vertex(internal_vertex_property(0u, p), m_graph)); } void clear_vertex(vertex_descriptor v) { @@ -189,7 +190,7 @@ class directed_graph std::pair add_edge(vertex_descriptor u, vertex_descriptor v, edge_property_type const& p) - { return make_index(boost::add_edge(u, v, edge_property(0u, p), m_graph)); } + { return make_index(boost::add_edge(u, v, internal_edge_property(0u, p), m_graph)); } void remove_edge(vertex_descriptor u, vertex_descriptor v) { @@ -410,7 +411,7 @@ template typename DIRECTED_GRAPH::vertex_descriptor vertex(typename DIRECTED_GRAPH::vertices_size_type n, DIRECTED_GRAPH const& g) -{ return vertex(g.impl()); } +{ return vertex(n, g.impl()); } template std::pair @@ -519,37 +520,32 @@ remove_in_edge_if(typename DIRECTED_GRAPH::vertex_descriptor v, DIRECTED_GRAPH& g) { return remove_in_edge_if(v, pred, g.impl()); } -// Helper code for working with property maps -namespace detail -{ - struct directed_graph_vertex_property_selector { - template - struct bind_ { - typedef typename DirectedGraph::graph_type Graph; - typedef property_map PropertyMap; - typedef typename PropertyMap::type type; - typedef typename PropertyMap::const_type const_type; - }; - }; - - struct directed_graph_edge_property_selector { - template - struct bind_ { - typedef typename DirectedGraph::graph_type Graph; - typedef property_map PropertyMap; - typedef typename PropertyMap::type type; - typedef typename PropertyMap::const_type const_type; - }; - }; -} - -template <> -struct vertex_property_selector -{ typedef detail::directed_graph_vertex_property_selector type; }; +template +struct property_map: property_map {}; + +template +struct property_map { + typedef transform_value_property_map< + detail::remove_first_property, + typename property_map::const_type> + const_type; + typedef transform_value_property_map< + detail::remove_first_property, + typename property_map::type> + type; +}; -template <> -struct edge_property_selector -{ typedef detail::directed_graph_edge_property_selector type; }; +template +struct property_map { + typedef transform_value_property_map< + detail::remove_first_property, + typename property_map::const_type> + const_type; + typedef transform_value_property_map< + detail::remove_first_property, + typename property_map::type> + type; +}; // PropertyGraph concepts template @@ -562,6 +558,26 @@ inline typename property_map::const_type get(Property p, DIRECTED_GRAPH const& g) { return get(p, g.impl()); } +template +inline typename property_map::type +get(vertex_all_t, DIRECTED_GRAPH& g) +{ return typename property_map::type(detail::remove_first_property(), get(vertex_all, g.impl())); } + +template +inline typename property_map::const_type +get(vertex_all_t, DIRECTED_GRAPH const& g) +{ return typename property_map::const_type(detail::remove_first_property(), get(vertex_all, g.impl())); } + +template +inline typename property_map::type +get(edge_all_t, DIRECTED_GRAPH& g) +{ return typename property_map::type(detail::remove_first_property(), get(edge_all, g.impl())); } + +template +inline typename property_map::const_type +get(edge_all_t, DIRECTED_GRAPH const& g) +{ return typename property_map::const_type(detail::remove_first_property(), get(edge_all, g.impl())); } + template inline typename property_traits< typename property_map< @@ -571,10 +587,40 @@ inline typename property_traits< get(Property p, DIRECTED_GRAPH const& g, Key const& k) { return get(p, g.impl(), k); } +template +inline typename property_traits< + typename property_map< + typename DIRECTED_GRAPH::graph_type, vertex_all_t + >::const_type +>::value_type +get(vertex_all_t, DIRECTED_GRAPH const& g, Key const& k) +{ return get(vertex_all, g.impl(), k).m_base; } + +template +inline typename property_traits< + typename property_map< + typename DIRECTED_GRAPH::graph_type, edge_all_t + >::const_type +>::value_type +get(edge_all_t, DIRECTED_GRAPH const& g, Key const& k) +{ return get(edge_all, g.impl(), k).m_base; } + template inline void put(Property p, DIRECTED_GRAPH& g, Key const& k, Value const& v) { put(p, g.impl(), k, v); } +template +inline void put(vertex_all_t, DIRECTED_GRAPH& g, Key const& k, Value const& v) +{ put(vertex_all, g.impl(), k, + typename DIRECTED_GRAPH::internal_vertex_property(get(vertex_index, g.impl(), k), v)); +} + +template +inline void put(edge_all_t, DIRECTED_GRAPH& g, Key const& k, Value const& v) +{ put(edge_all, g.impl(), k, + typename DIRECTED_GRAPH::internal_vertex_property(get(edge_index, g.impl(), k), v)); +} + template typename graph_property::type& get_property(DIRECTED_GRAPH& g, Property p) @@ -590,35 +636,6 @@ void set_property(DIRECTED_GRAPH& g, Property p, Value v) { return set_property(g.impl(), p, v); } -#ifndef BOOST_GRAPH_NO_BUNDLED_PROPERTIES - -template -inline typename property_map::type -get(Type Bundle::* p, DIRECTED_GRAPH& g) { - typedef typename property_map< - DIRECTED_GRAPH, Type Bundle::* - >::type return_type; - return return_type(&g, p); -} - -template -inline typename property_map::const_type -get(Type Bundle::* p, DIRECTED_GRAPH const& g) { - typedef typename property_map< - DIRECTED_GRAPH, Type Bundle::* - >::const_type return_type; - return return_type(&g, p); -} - -template -inline Type get(Type Bundle::* p, DIRECTED_GRAPH const& g, Key const& k) -{ return get(p, g.impl(), k); } - -template -inline void put(Type Bundle::* p, DIRECTED_GRAPH& g, Key const& k, Value const& v) -{ put(p, g.impl(), k, v); } -#endif - // Vertex index management template diff --git a/include/boost/graph/dll_import_export.hpp b/include/boost/graph/dll_import_export.hpp index cc369d1d1..d03fcd3f2 100644 --- a/include/boost/graph/dll_import_export.hpp +++ b/include/boost/graph/dll_import_export.hpp @@ -13,15 +13,13 @@ #include -#ifdef BOOST_HAS_DECLSPEC -# if defined(BOOST_ALL_DYN_LINK) || defined(BOOST_GRAPH_DYN_LINK) -# ifdef BOOST_GRAPH_SOURCE -# define BOOST_GRAPH_DECL __declspec(dllexport) -# else -# define BOOST_GRAPH_DECL __declspec(dllimport) -# endif // BOOST_GRAPH_SOURCE -# endif // DYN_LINK -#endif // BOOST_HAS_DECLSPEC +#if defined(BOOST_ALL_DYN_LINK) || defined(BOOST_GRAPH_DYN_LINK) +# ifdef BOOST_GRAPH_SOURCE +# define BOOST_GRAPH_DECL BOOST_SYMBOL_EXPORT +# else +# define BOOST_GRAPH_DECL BOOST_SYMBOL_IMPORT +# endif // BOOST_GRAPH_SOURCE +#endif // DYN_LINK #ifndef BOOST_GRAPH_DECL # define BOOST_GRAPH_DECL diff --git a/include/boost/graph/dominator_tree.hpp b/include/boost/graph/dominator_tree.hpp index db40cb73f..9371eee0d 100644 --- a/include/boost/graph/dominator_tree.hpp +++ b/include/boost/graph/dominator_tree.hpp @@ -13,6 +13,7 @@ #include #include #include +#include // Dominator tree computation @@ -244,7 +245,7 @@ namespace boost { typedef typename graph_traits::vertex_descriptor Vertex; typedef typename graph_traits::vertices_size_type VerticesSizeType; - function_requires< BidirectionalGraphConcept >(); + BOOST_CONCEPT_ASSERT(( BidirectionalGraphConcept )); const VerticesSizeType numOfVertices = num_vertices(g); if (numOfVertices == 0) return; @@ -299,7 +300,7 @@ namespace boost { // Typedefs and concept check typedef typename graph_traits::vertices_size_type VerticesSizeType; - function_requires< BidirectionalGraphConcept >(); + BOOST_CONCEPT_ASSERT(( BidirectionalGraphConcept )); // 1. Depth first visit const VerticesSizeType numOfVertices = num_vertices(g); @@ -388,7 +389,7 @@ namespace boost { iterator_property_map >::iterator, IndexMap> vertexSetMap; - function_requires >(); + BOOST_CONCEPT_ASSERT(( BidirectionalGraphConcept )); // 1. Finding dominator // 1.1. Initialize diff --git a/include/boost/graph/eccentricity.hpp b/include/boost/graph/eccentricity.hpp index 99f80a452..63797a830 100644 --- a/include/boost/graph/eccentricity.hpp +++ b/include/boost/graph/eccentricity.hpp @@ -7,9 +7,10 @@ #ifndef BOOST_GRAPH_ECCENTRICITY_HPP #define BOOST_GRAPH_ECCENTRICITY_HPP -#include +#include #include #include +#include namespace boost { @@ -19,9 +20,9 @@ template ::value_type eccentricity(const Graph& g, DistanceMap dist, Combinator combine) { - function_requires< GraphConcept >(); + BOOST_CONCEPT_ASSERT(( GraphConcept )); typedef typename graph_traits::vertex_descriptor Vertex; - function_requires< ReadablePropertyMapConcept >(); + BOOST_CONCEPT_ASSERT(( ReadablePropertyMapConcept )); typedef typename property_traits::value_type Distance; return detail::combine_distances(g, dist, combine, Distance(0)); @@ -31,9 +32,9 @@ template inline typename property_traits::value_type eccentricity(const Graph& g, DistanceMap dist) { - function_requires< GraphConcept >(); + BOOST_CONCEPT_ASSERT(( GraphConcept )); typedef typename graph_traits::vertex_descriptor Vertex; - function_requires< ReadablePropertyMapConcept >(); + BOOST_CONCEPT_ASSERT(( ReadablePropertyMapConcept )); typedef typename property_traits::value_type Distance; return eccentricity(g, dist, detail::maximize()); @@ -44,12 +45,12 @@ inline std::pair::value_type, typename property_traits::value_type> all_eccentricities(const Graph& g, const DistanceMatrix& dist, EccentricityMap ecc) { - function_requires< VertexListGraphConcept >(); + BOOST_CONCEPT_ASSERT(( VertexListGraphConcept )); typedef typename graph_traits::vertex_descriptor Vertex; typedef typename graph_traits::vertex_iterator VertexIterator; - function_requires< ReadablePropertyMapConcept >(); + BOOST_CONCEPT_ASSERT(( ReadablePropertyMapConcept )); typedef typename property_traits::value_type DistanceMap; - function_requires< WritablePropertyMapConcept >(); + BOOST_CONCEPT_ASSERT(( WritablePropertyMapConcept )); typedef typename property_traits::value_type Eccentricity; BOOST_USING_STD_MIN(); BOOST_USING_STD_MAX(); @@ -76,10 +77,10 @@ inline std::pair::value_type, typename property_traits::value_type> radius_and_diameter(const Graph& g, EccentricityMap ecc) { - function_requires< VertexListGraphConcept >(); + BOOST_CONCEPT_ASSERT(( VertexListGraphConcept )); typedef typename graph_traits::vertex_descriptor Vertex; typedef typename graph_traits::vertex_iterator VertexIterator; - function_requires< ReadablePropertyMapConcept >(); + BOOST_CONCEPT_ASSERT(( ReadablePropertyMapConcept )); typedef typename property_traits::value_type Eccentricity; BOOST_USING_STD_MIN(); BOOST_USING_STD_MAX(); diff --git a/include/boost/graph/edge_coloring.hpp b/include/boost/graph/edge_coloring.hpp new file mode 100644 index 000000000..8eb79ad43 --- /dev/null +++ b/include/boost/graph/edge_coloring.hpp @@ -0,0 +1,196 @@ +//======================================================================= +// Copyright 2013 Maciej Piechotka +// Authors: Maciej Piechotka +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +//======================================================================= +#ifndef BOOST_GRAPH_EDGE_COLORING_HPP +#define BOOST_GRAPH_EDGE_COLORING_HPP + +#include +#include +#include +#include +#include +#include + +/* This algorithm is to find coloring of an edges + + Reference: + + Misra, J., & Gries, D. (1992). A constructive proof of Vizing's + theorem. In Information Processing Letters. +*/ + +namespace boost { + namespace detail { + template + bool + is_free(const Graph &g, + ColorMap color, + typename boost::graph_traits::vertex_descriptor u, + typename boost::property_traits::value_type free_color) + { + typedef typename boost::property_traits::value_type color_t; + if (free_color == (std::numeric_limits::max)()) + return false; + BGL_FORALL_OUTEDGES_T(u, e, g, Graph) { + if (get(color, e) == free_color) { + return false; + } + } + return true; + } + + template + std::vector::vertex_descriptor> + maximal_fan(const Graph &g, + ColorMap color, + typename boost::graph_traits::vertex_descriptor x, + typename boost::graph_traits::vertex_descriptor y) + { + typedef typename boost::graph_traits::vertex_descriptor vertex_t; + std::vector fan; + fan.push_back(y); + bool extended; + do { + extended = false; + BGL_FORALL_OUTEDGES_T(x, e, g, Graph) { + vertex_t v = target(e, g); + if (is_free(g, color, fan.back(), get(color, e)) && + std::find(fan.begin(), fan.end(), v) == fan.end()) { + fan.push_back(v); + extended = true; + } + } + } while(extended); + return fan; + } + template + typename boost::property_traits::value_type + find_free_color(const Graph &g, + ColorMap color, + typename boost::graph_traits::vertex_descriptor u) + { + typename boost::property_traits::value_type c = 0; + while (!is_free(g, color, u, c)) c++; + return c; + } + + template + void + invert_cd_path(const Graph &g, + ColorMap color, + typename boost::graph_traits::vertex_descriptor x, + typename boost::graph_traits::edge_descriptor eold, + typename boost::property_traits::value_type c, + typename boost::property_traits::value_type d) + { + put(color, eold, d); + BGL_FORALL_OUTEDGES_T(x, e, g, Graph) { + if (get(color, e) == d && e != eold) { + invert_cd_path(g, color, target(e, g), e, d, c); + return; + } + } + } + + template + void + invert_cd_path(const Graph &g, + ColorMap color, + typename boost::graph_traits::vertex_descriptor x, + typename boost::property_traits::value_type c, + typename boost::property_traits::value_type d) + { + BGL_FORALL_OUTEDGES_T(x, e, g, Graph) { + if (get(color, e) == d) { + invert_cd_path(g, color, target(e, g), e, d, c); + return; + } + } + } + + template + void + rotate_fan(const Graph &g, + ColorMap color, + typename boost::graph_traits::vertex_descriptor x, + ForwardIterator begin, + ForwardIterator end) + { + typedef typename boost::graph_traits::edge_descriptor edge_t; + if (begin == end) { + return; + } + edge_t previous = edge(x, *begin, g).first; + for (begin++; begin != end; begin++) { + edge_t current = edge(x, *begin, g).first; + put(color, previous, get(color, current)); + previous = current; + } + } + + template + class find_free_in_fan + { + public: + find_free_in_fan(const Graph &graph, + const ColorMap color, + typename boost::property_traits::value_type d) + : graph(graph), + color(color), + d(d) {} + bool operator()(const typename boost::graph_traits::vertex_descriptor u) const { + return is_free(graph, color, u, d); + } + private: + const Graph &graph; + const ColorMap color; + const typename boost::property_traits::value_type d; + }; + } + + template + typename boost::property_traits::value_type + color_edge(const Graph &g, + ColorMap color, + typename boost::graph_traits::edge_descriptor e) + { + typedef typename boost::graph_traits::vertex_descriptor vertex_t; + typedef typename boost::property_traits::value_type color_t; + typedef typename std::vector::iterator fan_iterator; + using namespace detail; + vertex_t x = source(e, g), y = target(e, g); + std::vector fan = maximal_fan(g, color, x, y); + color_t c = find_free_color(g, color, x); + color_t d = find_free_color(g, color, fan.back()); + invert_cd_path(g, color, x, c, d); + fan_iterator w = std::find_if(fan.begin(), + fan.end(), + find_free_in_fan(g, color, d)); + rotate_fan(g, color, x, fan.begin(), w + 1); + put(color, edge(x, *w, g).first, d); + return (std::max)(c, d); + } + + template + typename boost::property_traits::value_type + edge_coloring(const Graph &g, + ColorMap color) + { + typedef typename boost::property_traits::value_type color_t; + BGL_FORALL_EDGES_T(e, g, Graph) { + put(color, e, (std::numeric_limits::max)()); + } + color_t colors = 0; + BGL_FORALL_EDGES_T(e, g, Graph) { + colors = (std::max)(colors, color_edge(g, color, e) + 1); + } + return colors; + } +} + +#endif diff --git a/include/boost/graph/edmonds_karp_max_flow.hpp b/include/boost/graph/edmonds_karp_max_flow.hpp index 43cc592d2..377e6f14d 100644 --- a/include/boost/graph/edmonds_karp_max_flow.hpp +++ b/include/boost/graph/edmonds_karp_max_flow.hpp @@ -52,21 +52,21 @@ namespace boost { // find minimum residual capacity along the augmenting path FlowValue delta = (std::numeric_limits::max)(); - e = p[sink]; + e = get(p, sink); do { BOOST_USING_STD_MIN(); - delta = min BOOST_PREVENT_MACRO_SUBSTITUTION(delta, residual_capacity[e]); + delta = min BOOST_PREVENT_MACRO_SUBSTITUTION(delta, get(residual_capacity, e)); u = source(e, g); - e = p[u]; + e = get(p, u); } while (u != src); // push delta units of flow along the augmenting path - e = p[sink]; + e = get(p, sink); do { - residual_capacity[e] -= delta; - residual_capacity[reverse_edge[e]] += delta; + put(residual_capacity, e, get(residual_capacity, e) - delta); + put(residual_capacity, get(reverse_edge, e), get(residual_capacity, get(reverse_edge, e)) + delta); u = source(e, g); - e = p[u]; + e = get(p, u); } while (u != src); } @@ -94,22 +94,22 @@ namespace boost { typename graph_traits::out_edge_iterator ei, e_end; for (boost::tie(u_iter, u_end) = vertices(g); u_iter != u_end; ++u_iter) for (boost::tie(ei, e_end) = out_edges(*u_iter, g); ei != e_end; ++ei) - res[*ei] = cap[*ei]; + put(res, *ei, get(cap, *ei)); - color[sink] = Color::gray(); - while (color[sink] != Color::white()) { + put(color, sink, Color::gray()); + while (get(color, sink) != Color::white()) { boost::queue Q; breadth_first_search (detail::residual_graph(g, res), src, Q, make_bfs_visitor(record_edge_predecessors(pred, on_tree_edge())), color); - if (color[sink] != Color::white()) + if (get(color, sink) != Color::white()) detail::augment(g, src, sink, pred, res, rev); } // while typename property_traits::value_type flow = 0; for (boost::tie(ei, e_end) = out_edges(src, g); ei != e_end; ++ei) - flow += (cap[*ei] - res[*ei]); + flow += (get(cap, *ei) - get(res, *ei)); return flow; } // edmonds_karp_max_flow() @@ -140,7 +140,7 @@ namespace boost { } }; template<> - struct edmonds_karp_dispatch2 { + struct edmonds_karp_dispatch2 { template static typename edge_capacity_value::type apply @@ -149,9 +149,8 @@ namespace boost { typename graph_traits::vertex_descriptor sink, PredMap pred, const bgl_named_params& params, - detail::error_property_not_found) + param_not_found) { - typedef typename graph_traits::edge_descriptor edge_descriptor; typedef typename graph_traits::vertices_size_type size_type; size_type n = is_default_param(get_param(params, vertex_color)) ? num_vertices(g) : 1; @@ -183,13 +182,13 @@ namespace boost { const bgl_named_params& params, PredMap pred) { - typedef typename property_value< bgl_named_params, vertex_color_t>::type C; + typedef typename get_param_type< vertex_color_t, bgl_named_params >::type C; return edmonds_karp_dispatch2::apply (g, src, sink, pred, params, get_param(params, vertex_color)); } }; template<> - struct edmonds_karp_dispatch1 { + struct edmonds_karp_dispatch1 { template static typename edge_capacity_value::type @@ -198,7 +197,7 @@ namespace boost { typename graph_traits::vertex_descriptor src, typename graph_traits::vertex_descriptor sink, const bgl_named_params& params, - detail::error_property_not_found) + param_not_found) { typedef typename graph_traits::edge_descriptor edge_descriptor; typedef typename graph_traits::vertices_size_type size_type; @@ -206,7 +205,7 @@ namespace boost { num_vertices(g) : 1; std::vector pred_vec(n); - typedef typename property_value< bgl_named_params, vertex_color_t>::type C; + typedef typename get_param_type< vertex_color_t, bgl_named_params >::type C; return edmonds_karp_dispatch2::apply (g, src, sink, make_iterator_property_map(pred_vec.begin(), choose_const_pmap @@ -227,7 +226,7 @@ namespace boost { typename graph_traits::vertex_descriptor sink, const bgl_named_params& params) { - typedef typename property_value< bgl_named_params, vertex_predecessor_t>::type Pred; + typedef typename get_param_type< vertex_predecessor_t, bgl_named_params >::type Pred; return detail::edmonds_karp_dispatch1::apply (g, src, sink, params, get_param(params, vertex_predecessor)); } diff --git a/include/boost/graph/erdos_renyi_generator.hpp b/include/boost/graph/erdos_renyi_generator.hpp index a45944168..5be06d79d 100644 --- a/include/boost/graph/erdos_renyi_generator.hpp +++ b/include/boost/graph/erdos_renyi_generator.hpp @@ -10,7 +10,7 @@ #ifndef BOOST_GRAPH_ERDOS_RENYI_GENERATOR_HPP #define BOOST_GRAPH_ERDOS_RENYI_GENERATOR_HPP -#include +#include #include #include #include @@ -155,8 +155,8 @@ namespace boost { // bernoulli_distribution would need to be run until it returns true. // Thus, this distribution can be used to step through the edges // which are actually present. - assert (src != (std::numeric_limits::max)() && - src != n); + BOOST_ASSERT (src != (std::numeric_limits::max)() && + src != n); while (src != n) { vertices_size_type increment = rand_vertex(*gen); size_t tgt_index_limit = diff --git a/include/boost/graph/filtered_graph.hpp b/include/boost/graph/filtered_graph.hpp index 764b2d7d1..74fea4611 100644 --- a/include/boost/graph/filtered_graph.hpp +++ b/include/boost/graph/filtered_graph.hpp @@ -195,7 +195,6 @@ namespace boost { typedef filtered_graph_tag graph_tag; -#ifndef BOOST_GRAPH_NO_BUNDLED_PROPERTIES // Bundled properties support template typename graph::detail::bundled_result::type& @@ -206,11 +205,10 @@ namespace boost { typename graph::detail::bundled_result::type const& operator[](Descriptor x) const { return this->m_g[x]; } -#endif // BOOST_GRAPH_NO_BUNDLED_PROPERTIES static vertex_descriptor null_vertex() { - return Graph::null_vertex(); + return Traits::null_vertex(); } //private: @@ -222,19 +220,21 @@ namespace boost { template - struct vertex_property_type > { - typedef typename vertex_property_type::type type; - }; + struct vertex_property_type >: + vertex_property_type {}; template - struct edge_property_type > { - typedef typename edge_property_type::type type; - }; + struct edge_property_type >: + edge_property_type {}; + template + struct graph_property_type >: + graph_property_type {}; -#ifndef BOOST_GRAPH_NO_BUNDLED_PROPERTIES template struct vertex_bundle_type > @@ -244,7 +244,11 @@ namespace boost { struct edge_bundle_type > : edge_bundle_type { }; -#endif // BOOST_GRAPH_NO_BUNDLED_PROPERTIES + + template + struct graph_bundle_type > + : graph_bundle_type { }; //=========================================================================== // Non-member functions for the Filtered Edge Graph diff --git a/include/boost/graph/find_flow_cost.hpp b/include/boost/graph/find_flow_cost.hpp new file mode 100644 index 000000000..e4d6f404e --- /dev/null +++ b/include/boost/graph/find_flow_cost.hpp @@ -0,0 +1,52 @@ +//======================================================================= +// Copyright 2013 University of Warsaw. +// Authors: Piotr Wygocki +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +//======================================================================= +#ifndef BOOST_GRAPH_FIND_FLOW_COST_HPP +#define BOOST_GRAPH_FIND_FLOW_COST_HPP + +#include + +namespace boost { + +template +typename property_traits::type>::value_type +find_flow_cost(const Graph & g, Capacity capacity, ResidualCapacity residual_capacity, Weight weight) { + typedef typename property_traits::const_type>::value_type Cost; + + Cost cost = 0; + BGL_FORALL_EDGES_T(e, g, Graph) { + if(get(capacity, e) > Cost(0)) { + cost += (get(capacity, e) - get(residual_capacity, e)) * get(weight, e); + } + } + return cost; +} + +template +typename property_traits::type>::value_type +find_flow_cost(const Graph & g, + const bgl_named_params& params) { + return find_flow_cost(g, + choose_const_pmap(get_param(params, edge_capacity), g, edge_capacity), + choose_const_pmap(get_param(params, edge_residual_capacity), + g, edge_residual_capacity), + choose_const_pmap(get_param(params, edge_weight), g, edge_weight)); +} + +template +typename property_traits::type>::value_type +find_flow_cost(const Graph &g) { + bgl_named_params params(0); + return find_flow_cost(g, params); +} + + +} //boost + +#endif /* BOOST_GRAPH_FIND_FLOW_COST_HPP */ + diff --git a/include/boost/graph/floyd_warshall_shortest.hpp b/include/boost/graph/floyd_warshall_shortest.hpp index 48dba7126..472995f04 100644 --- a/include/boost/graph/floyd_warshall_shortest.hpp +++ b/include/boost/graph/floyd_warshall_shortest.hpp @@ -34,6 +34,7 @@ #include #include #include +#include namespace boost { @@ -84,7 +85,7 @@ namespace boost const BinaryFunction& combine, const Infinity& inf, const Zero& zero) { - function_requires >(); + BOOST_CONCEPT_ASSERT(( VertexListGraphConcept )); return detail::floyd_warshall_dispatch(g, d, compare, combine, inf, zero); @@ -101,9 +102,9 @@ namespace boost const BinaryPredicate& compare, const BinaryFunction& combine, const Infinity& inf, const Zero& zero) { - function_requires >(); - function_requires >(); - function_requires >(); + BOOST_CONCEPT_ASSERT(( VertexListGraphConcept )); + BOOST_CONCEPT_ASSERT(( EdgeListGraphConcept )); + BOOST_CONCEPT_ASSERT(( IncidenceGraphConcept )); typename graph_traits::vertex_iterator firstv, lastv, firstv2, lastv2; @@ -163,14 +164,16 @@ namespace boost const bgl_named_params& params) { typedef typename property_traits::value_type WM; + WM inf = + choose_param(get_param(params, distance_inf_t()), + std::numeric_limits::max BOOST_PREVENT_MACRO_SUBSTITUTION()); return floyd_warshall_initialized_all_pairs_shortest_paths(g, d, choose_param(get_param(params, distance_compare_t()), std::less()), choose_param(get_param(params, distance_combine_t()), - closed_plus()), - choose_param(get_param(params, distance_inf_t()), - std::numeric_limits::max BOOST_PREVENT_MACRO_SUBSTITUTION()), + closed_plus(inf)), + inf, choose_param(get_param(params, distance_zero_t()), WM())); } @@ -185,13 +188,15 @@ namespace boost { typedef typename property_traits::value_type WM; + WM inf = + choose_param(get_param(params, distance_inf_t()), + std::numeric_limits::max BOOST_PREVENT_MACRO_SUBSTITUTION()); return floyd_warshall_all_pairs_shortest_paths(g, d, w, choose_param(get_param(params, distance_compare_t()), std::less()), choose_param(get_param(params, distance_combine_t()), - closed_plus()), - choose_param(get_param(params, distance_inf_t()), - std::numeric_limits::max BOOST_PREVENT_MACRO_SUBSTITUTION()), + closed_plus(inf)), + inf, choose_param(get_param(params, distance_zero_t()), WM())); } diff --git a/include/boost/graph/fruchterman_reingold.hpp b/include/boost/graph/fruchterman_reingold.hpp index 4ce502e83..01d080a41 100644 --- a/include/boost/graph/fruchterman_reingold.hpp +++ b/include/boost/graph/fruchterman_reingold.hpp @@ -282,7 +282,6 @@ fruchterman_reingold_force_directed_layout Cooling cool, DisplacementMap displacement) { - typedef typename Topology::point_type Point; typedef typename graph_traits::vertex_iterator vertex_iterator; typedef typename graph_traits::vertex_descriptor vertex_descriptor; typedef typename graph_traits::edge_iterator edge_iterator; @@ -363,7 +362,7 @@ namespace detail { }; template<> - struct fr_force_directed_layout + struct fr_force_directed_layout { template& params) { typedef typename Topology::point_difference_type PointDiff; @@ -404,8 +403,7 @@ fruchterman_reingold_force_directed_layout const Topology& topology, const bgl_named_params& params) { - typedef typename property_value, - vertex_displacement_t>::type D; + typedef typename get_param_type >::type D; detail::fr_force_directed_layout::run (g, position, topology, diff --git a/include/boost/graph/geodesic_distance.hpp b/include/boost/graph/geodesic_distance.hpp index a4d702749..d76d321e1 100644 --- a/include/boost/graph/geodesic_distance.hpp +++ b/include/boost/graph/geodesic_distance.hpp @@ -9,6 +9,7 @@ #include #include +#include namespace boost { @@ -25,10 +26,10 @@ struct mean_geodesic_measure result_type operator ()(distance_type d, const Graph& g) { - function_requires< VertexListGraphConcept >(); - function_requires< NumericValueConcept >(); - function_requires< NumericValueConcept >(); - function_requires< AdaptableBinaryFunctionConcept >(); + BOOST_CONCEPT_ASSERT(( VertexListGraphConcept )); + BOOST_CONCEPT_ASSERT(( NumericValueConcept )); + BOOST_CONCEPT_ASSERT(( NumericValueConcept )); + BOOST_CONCEPT_ASSERT(( AdaptableBinaryFunctionConcept )); return (d == base_type::infinite_distance()) ? base_type::infinite_result() @@ -69,8 +70,8 @@ struct mean_graph_distance_measure inline result_type operator ()(distance_type d, const Graph& g) { - function_requires< VertexListGraphConcept >(); - function_requires< NumericValueConcept >(); + BOOST_CONCEPT_ASSERT(( VertexListGraphConcept )); + BOOST_CONCEPT_ASSERT(( NumericValueConcept )); if(d == base_type::infinite_distance()) { return base_type::infinite_result(); @@ -99,7 +100,7 @@ mean_geodesic(const Graph& g, Measure measure, Combinator combine) { - function_requires< DistanceMeasureConcept >(); + BOOST_CONCEPT_ASSERT(( DistanceMeasureConcept )); typedef typename Measure::distance_type Distance; Distance n = detail::combine_distances(g, dist, combine, Distance(0)); @@ -112,7 +113,7 @@ template >(); + BOOST_CONCEPT_ASSERT(( DistanceMeasureConcept )); typedef typename Measure::distance_type Distance; return mean_geodesic(g, dist, measure, std::plus()); @@ -139,15 +140,15 @@ all_mean_geodesics(const Graph& g, GeodesicMap geo, Measure measure) { - function_requires< VertexListGraphConcept >(); + BOOST_CONCEPT_ASSERT(( VertexListGraphConcept )); typedef typename graph_traits::vertex_descriptor Vertex; typedef typename graph_traits::vertex_iterator VertexIterator; - function_requires< ReadablePropertyMapConcept >(); + BOOST_CONCEPT_ASSERT(( ReadablePropertyMapConcept )); typedef typename property_traits::value_type DistanceMap; - function_requires< DistanceMeasureConcept >(); + BOOST_CONCEPT_ASSERT(( DistanceMeasureConcept )); typedef typename Measure::result_type Result; - function_requires< WritablePropertyMapConcept >(); - function_requires< NumericValueConcept >(); + BOOST_CONCEPT_ASSERT(( WritablePropertyMapConcept )); + BOOST_CONCEPT_ASSERT(( NumericValueConcept )); // NOTE: We could compute the mean geodesic here by performing additional // computations (i.e., adding and dividing). However, I don't really feel @@ -156,7 +157,7 @@ all_mean_geodesics(const Graph& g, Result inf = numeric_values::infinity(); Result sum = numeric_values::zero(); VertexIterator i, end; - for(tie(i, end) = vertices(g); i != end; ++i) { + for(boost::tie(i, end) = vertices(g); i != end; ++i) { DistanceMap dm = get(dist, *i); Result r = mean_geodesic(g, dm, measure); put(geo, *i, r); @@ -178,11 +179,11 @@ template inline typename property_traits::value_type all_mean_geodesics(const Graph& g, DistanceMatrixMap dist, GeodesicMap geo) { - function_requires< GraphConcept >(); + BOOST_CONCEPT_ASSERT(( GraphConcept )); typedef typename graph_traits::vertex_descriptor Vertex; - function_requires< ReadablePropertyMapConcept >(); + BOOST_CONCEPT_ASSERT(( ReadablePropertyMapConcept )); typedef typename property_traits::value_type DistanceMap; - function_requires< WritablePropertyMapConcept >(); + BOOST_CONCEPT_ASSERT(( WritablePropertyMapConcept )); typedef typename property_traits::value_type Result; return all_mean_geodesics(g, dist, geo, measure_mean_geodesic(g, DistanceMap())); @@ -193,7 +194,7 @@ template inline typename Measure::result_type small_world_distance(const Graph& g, GeodesicMap geo, Measure measure) { - function_requires< DistanceMeasureConcept >(); + BOOST_CONCEPT_ASSERT(( DistanceMeasureConcept )); typedef typename Measure::result_type Result; Result sum = detail::combine_distances(g, geo, std::plus(), Result(0)); diff --git a/include/boost/graph/graph_archetypes.hpp b/include/boost/graph/graph_archetypes.hpp index 9b364bb81..81f9c2c8a 100644 --- a/include/boost/graph/graph_archetypes.hpp +++ b/include/boost/graph/graph_archetypes.hpp @@ -53,6 +53,8 @@ namespace boost { // should use a different namespace for this typedef void in_edge_iterator; typedef void vertex_iterator; typedef void edge_iterator; + + static vertex_descriptor null_vertex() {return vertex_descriptor();} }; template V source(const typename incidence_graph_archetype::edge_descriptor&, @@ -105,6 +107,8 @@ namespace boost { // should use a different namespace for this typedef void out_edge_iterator; typedef void vertex_iterator; typedef void edge_iterator; + + static vertex_descriptor null_vertex() {return vertex_descriptor();} }; template @@ -154,6 +158,8 @@ namespace boost { // should use a different namespace for this typedef void in_edge_iterator; typedef void edge_iterator; + + static vertex_descriptor null_vertex() {return vertex_descriptor();} }; template diff --git a/include/boost/graph/graph_as_tree.hpp b/include/boost/graph/graph_as_tree.hpp index 3758c3f00..721e503e8 100644 --- a/include/boost/graph/graph_as_tree.hpp +++ b/include/boost/graph/graph_as_tree.hpp @@ -50,13 +50,9 @@ namespace boost { template ::vertex_descriptor -#endif , class ChIt -#if !defined BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION = typename graph_traits::adjacency_iterator -#endif > class graph_as_tree : public graph_as_tree_base #include #include +#include +#include +#include #include +#include #include namespace boost @@ -34,7 +38,6 @@ namespace boost // It is needed in order to allow us to write using boost::vertices as // needed for ADL when using vector_as_graph below. #if !defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP) \ - && !BOOST_WORKAROUND(__GNUC__, <= 2) \ && !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) # define BOOST_VECTOR_AS_GRAPH_GRAPH_ADL_HACK #endif @@ -54,12 +57,10 @@ typename T::ThereReallyIsNoMemberByThisNameInT vertices(T const&); BOOST_concept(Graph,(G)) { typedef typename graph_traits::vertex_descriptor vertex_descriptor; + typedef typename graph_traits::edge_descriptor edge_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; + typedef typename graph_traits::edge_parallel_category edge_parallel_category; + typedef typename graph_traits::traversal_category traversal_category; BOOST_CONCEPT_USAGE(Graph) { @@ -74,11 +75,12 @@ typename T::ThereReallyIsNoMemberByThisNameInT vertices(T const&); : Graph { typedef typename graph_traits::edge_descriptor edge_descriptor; - typedef typename graph_traits::out_edge_iterator - out_edge_iterator; + typedef typename graph_traits::out_edge_iterator out_edge_iterator; + typedef typename graph_traits::degree_size_type degree_size_type; + typedef typename graph_traits::traversal_category traversal_category; - typedef typename graph_traits::traversal_category - traversal_category; + BOOST_STATIC_ASSERT((boost::mpl::not_ >::value)); + BOOST_STATIC_ASSERT((boost::mpl::not_ >::value)); BOOST_CONCEPT_USAGE(IncidenceGraph) { BOOST_CONCEPT_ASSERT((MultiPassInputIterator)); @@ -122,6 +124,8 @@ typename T::ThereReallyIsNoMemberByThisNameInT vertices(T const&); BOOST_CONCEPT_ASSERT((Convertible)); + BOOST_STATIC_ASSERT((boost::mpl::not_ >::value)); + p = in_edges(v, g); n = in_degree(v, g); e = *p.first; @@ -152,6 +156,8 @@ typename T::ThereReallyIsNoMemberByThisNameInT vertices(T const&); BOOST_CONCEPT_ASSERT((Convertible)); + BOOST_STATIC_ASSERT((boost::mpl::not_ >::value)); + p = adjacent_vertices(v, g); v = *p.first; const_constraints(g); @@ -177,6 +183,9 @@ typename T::ThereReallyIsNoMemberByThisNameInT vertices(T const&); BOOST_CONCEPT_ASSERT((Convertible)); + BOOST_STATIC_ASSERT((boost::mpl::not_ >::value)); + BOOST_STATIC_ASSERT((boost::mpl::not_ >::value)); + #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 @@ -226,6 +235,9 @@ typename T::ThereReallyIsNoMemberByThisNameInT vertices(T const&); BOOST_CONCEPT_ASSERT((Convertible)); + BOOST_STATIC_ASSERT((boost::mpl::not_ >::value)); + BOOST_STATIC_ASSERT((boost::mpl::not_ >::value)); + p = edges(g); e = *p.first; u = source(e, g); @@ -342,7 +354,7 @@ typename T::ThereReallyIsNoMemberByThisNameInT vertices(T const&); } G g; typename graph_traits::vertex_descriptor v; - typename vertex_property::type vp; + typename vertex_property_type::type vp; }; BOOST_concept(EdgeMutablePropertyGraph,(G)) @@ -356,7 +368,7 @@ typename T::ThereReallyIsNoMemberByThisNameInT vertices(T const&); G g; std::pair p; typename graph_traits::vertex_descriptor u, v; - typename edge_property::type ep; + typename edge_property_type::type ep; }; BOOST_concept(AdjacencyMatrix,(G)) @@ -457,10 +469,10 @@ typename T::ThereReallyIsNoMemberByThisNameInT vertices(T const&); const_constraints(g); } - void const_constraints(const Graph& g) + void const_constraints(const Graph& g_) { typedef typename property_map::const_type Map; - Map m = get(vertex_index, g); + Map m = get(vertex_index, g_); ignore_unused_variable_warning(m); } private: @@ -484,10 +496,10 @@ typename T::ThereReallyIsNoMemberByThisNameInT vertices(T const&); const_constraints(g); } - void const_constraints(const Graph& g) + void const_constraints(const Graph& g_) { typedef typename property_map::const_type Map; - Map m = get(edge_index, g); + Map m = get(edge_index, g_); ignore_unused_variable_warning(m); } private: @@ -529,8 +541,8 @@ typename T::ThereReallyIsNoMemberByThisNameInT vertices(T const&); { BOOST_CONCEPT_USAGE(NumericValue) { - function_requires< DefaultConstructible >(); - function_requires< CopyConstructible >(); + BOOST_CONCEPT_ASSERT(( DefaultConstructible )); + BOOST_CONCEPT_ASSERT(( CopyConstructible )); numeric_values::zero(); numeric_values::infinity(); } diff --git a/include/boost/graph/graph_stats.hpp b/include/boost/graph/graph_stats.hpp index 636c49137..ad0e330ca 100644 --- a/include/boost/graph/graph_stats.hpp +++ b/include/boost/graph/graph_stats.hpp @@ -12,6 +12,7 @@ #include #include #include +#include namespace boost { namespace graph { @@ -124,7 +125,7 @@ std::map weight_degree_dist( Graph& g ) { for( std::map::iterator iter = dist.begin(); iter != dist.end(); ++iter ) { - assert( n[iter->first] != 0 ); + BOOST_ASSERT( n[iter->first] != 0 ); dist[iter->first] /= n[iter->first]; } diff --git a/include/boost/graph/graph_test.hpp b/include/boost/graph/graph_test.hpp index fc4d9f0f9..69d89f34f 100644 --- a/include/boost/graph/graph_test.hpp +++ b/include/boost/graph/graph_test.hpp @@ -213,7 +213,7 @@ namespace boost { IsoMap iso_map(iso_vec.begin(), get(vertex_index, g)); copy_graph(g, cpy, orig_to_copy(iso_map)); - assert((verify_isomorphism(g, cpy, iso_map))); + BOOST_CHECK((verify_isomorphism(g, cpy, iso_map))); vertex_t v = add_vertex(g); @@ -325,10 +325,10 @@ namespace boost { template void test_readable_vertex_property_graph - (const std::vector& vertex_prop, PropertyTag, const Graph& g) + (const std::vector& vertex_prop, PropertyTag tag, const Graph& g) { typedef typename property_map::const_type const_Map; - const_Map pmap = get(PropertyTag(), g); + const_Map pmap = get(tag, g); typename std::vector::const_iterator i = vertex_prop.begin(); for (typename boost::graph_traits::vertex_iterator @@ -339,7 +339,7 @@ namespace boost { ++bgl_first_9) { //BGL_FORALL_VERTICES_T(v, g, Graph) { typename property_traits::value_type - pval1 = get(pmap, v), pval2 = get(PropertyTag(), g, v); + pval1 = get(pmap, v), pval2 = get(tag, g, v); BOOST_CHECK(pval1 == pval2); BOOST_CHECK(pval1 == *i++); } @@ -350,7 +350,7 @@ namespace boost { (const std::vector& vertex_prop, PropertyTag tag, Graph& g) { typedef typename property_map::type PMap; - PMap pmap = get(PropertyTag(), g); + PMap pmap = get(tag, g); typename std::vector::const_iterator i = vertex_prop.begin(); for (typename boost::graph_traits::vertex_iterator bgl_first_9 = vertices(g).first, bgl_last_9 = vertices(g).second; @@ -368,7 +368,7 @@ namespace boost { typename std::vector::const_iterator j = vertex_prop.begin(); BGL_FORALL_VERTICES_T(v, g, Graph) - put(PropertyTag(), g, v, *j++); + put(tag, g, v, *j++); test_readable_vertex_property_graph(vertex_prop, tag, g); } diff --git a/include/boost/graph/graph_traits.hpp b/include/boost/graph/graph_traits.hpp index fd1b0415c..a1c27483a 100644 --- a/include/boost/graph/graph_traits.hpp +++ b/include/boost/graph/graph_traits.hpp @@ -12,10 +12,15 @@ #include #include +#include /* Primarily for std::pair */ #include #include +#include #include #include +#include +#include +#include #include #include #include @@ -24,23 +29,47 @@ namespace boost { + namespace detail { +#define BOOST_GRAPH_MEMBER_OR_VOID(name) \ + BOOST_MPL_HAS_XXX_TRAIT_DEF(name) \ + template struct BOOST_JOIN(get_member_, name) {typedef typename T::name type;}; \ + template struct BOOST_JOIN(get_opt_member_, name): \ + boost::mpl::eval_if_c< \ + BOOST_JOIN(has_, name)::value, \ + BOOST_JOIN(get_member_, name), \ + boost::mpl::identity > \ + {}; + BOOST_GRAPH_MEMBER_OR_VOID(adjacency_iterator) + BOOST_GRAPH_MEMBER_OR_VOID(out_edge_iterator) + BOOST_GRAPH_MEMBER_OR_VOID(in_edge_iterator) + BOOST_GRAPH_MEMBER_OR_VOID(vertex_iterator) + BOOST_GRAPH_MEMBER_OR_VOID(edge_iterator) + BOOST_GRAPH_MEMBER_OR_VOID(vertices_size_type) + BOOST_GRAPH_MEMBER_OR_VOID(edges_size_type) + BOOST_GRAPH_MEMBER_OR_VOID(degree_size_type) + } + template struct graph_traits { +#define BOOST_GRAPH_PULL_OPT_MEMBER(name) \ + typedef typename detail::BOOST_JOIN(get_opt_member_, name)::type name; + typedef typename G::vertex_descriptor vertex_descriptor; typedef typename G::edge_descriptor edge_descriptor; - typedef typename G::adjacency_iterator adjacency_iterator; - typedef typename G::out_edge_iterator out_edge_iterator; - typedef typename G::in_edge_iterator in_edge_iterator; - typedef typename G::vertex_iterator vertex_iterator; - typedef typename G::edge_iterator edge_iterator; + BOOST_GRAPH_PULL_OPT_MEMBER(adjacency_iterator) + BOOST_GRAPH_PULL_OPT_MEMBER(out_edge_iterator) + BOOST_GRAPH_PULL_OPT_MEMBER(in_edge_iterator) + BOOST_GRAPH_PULL_OPT_MEMBER(vertex_iterator) + BOOST_GRAPH_PULL_OPT_MEMBER(edge_iterator) typedef typename G::directed_category directed_category; typedef typename G::edge_parallel_category edge_parallel_category; typedef typename G::traversal_category traversal_category; - typedef typename G::vertices_size_type vertices_size_type; - typedef typename G::edges_size_type edges_size_type; - typedef typename G::degree_size_type degree_size_type; + BOOST_GRAPH_PULL_OPT_MEMBER(vertices_size_type) + BOOST_GRAPH_PULL_OPT_MEMBER(edges_size_type) + BOOST_GRAPH_PULL_OPT_MEMBER(degree_size_type) +#undef BOOST_GRAPH_PULL_OPT_MEMBER static inline vertex_descriptor null_vertex(); }; @@ -137,7 +166,13 @@ namespace boost { struct edge_list_graph_tag { }; struct adjacency_matrix_tag { }; - /** @name Taversal Category Traits + // Parallel traversal_category tags + struct distributed_graph_tag { }; + struct distributed_vertex_list_graph_tag { }; + struct distributed_edge_list_graph_tag { }; +#define BOOST_GRAPH_SEQUENTIAL_TRAITS_DEFINES_DISTRIBUTED_TAGS // Disable these from external versions of PBGL + + /** @name Traversal Category Traits * These traits classify graph types by their supported methods of * vertex and edge traversal. */ @@ -217,23 +252,31 @@ namespace boost { //?? not the right place ?? Lee typedef boost::forward_traversal_tag multi_pass_input_iterator_tag; + namespace detail { + BOOST_MPL_HAS_XXX_TRAIT_DEF(graph_property_type) + BOOST_MPL_HAS_XXX_TRAIT_DEF(edge_property_type) + BOOST_MPL_HAS_XXX_TRAIT_DEF(vertex_property_type) + + template struct get_graph_property_type {typedef typename G::graph_property_type type;}; + template struct get_edge_property_type {typedef typename G::edge_property_type type;}; + template struct get_vertex_property_type {typedef typename G::vertex_property_type type;}; + } + template - struct graph_property_type { - typedef typename G::graph_property_type type; - }; + struct graph_property_type + : boost::mpl::eval_if, + detail::get_graph_property_type, + no_property> {}; template - struct edge_property_type { - typedef typename G::edge_property_type type; - }; + struct edge_property_type + : boost::mpl::eval_if, + detail::get_edge_property_type, + no_property> {}; template - struct vertex_property_type { - typedef typename G::vertex_property_type type; - }; - - struct no_bundle { }; - struct no_graph_bundle : no_bundle { }; - struct no_vertex_bundle : no_bundle { }; - struct no_edge_bundle : no_bundle { }; + struct vertex_property_type + : boost::mpl::eval_if, + detail::get_vertex_property_type, + no_property> {}; template struct graph_bundle_type { @@ -261,13 +304,21 @@ namespace boost { typedef typename bundler::type type; }; + template + class bundled_result { + typedef typename graph_traits::vertex_descriptor Vertex; + typedef graph_bundle_type bundler; + public: + typedef typename bundler::type type; + }; + } } // namespace graph::detail namespace graph_detail { // A helper metafunction for determining whether or not a type is // bundled. template - struct is_no_bundle : mpl::bool_::value> + struct is_no_bundle : mpl::bool_::value> { }; } // namespace graph_detail diff --git a/include/boost/graph/graph_utility.hpp b/include/boost/graph/graph_utility.hpp index ba1fe3d83..f1f120e30 100644 --- a/include/boost/graph/graph_utility.hpp +++ b/include/boost/graph/graph_utility.hpp @@ -237,8 +237,6 @@ namespace boost { template bool is_adj_dispatch(Graph& g, Vertex a, Vertex b, bidirectional_tag) { - typedef typename graph_traits::edge_descriptor - edge_descriptor; typename graph_traits::adjacency_iterator vi, viend, adj_found; boost::tie(vi, viend) = adjacent_vertices(a, g); @@ -265,21 +263,9 @@ namespace boost { template bool is_adj_dispatch(Graph& g, Vertex a, Vertex b, directed_tag) { - typedef typename graph_traits::edge_descriptor - edge_descriptor; typename graph_traits::adjacency_iterator vi, viend, found; boost::tie(vi, viend) = adjacent_vertices(a, g); -#if defined(BOOST_MSVC) && BOOST_MSVC <= 1300 && defined(__SGI_STL_PORT) - // Getting internal compiler error with std::find() - found = viend; - for (; vi != viend; ++vi) - if (*vi == b) { - found = vi; - break; - } -#else found = std::find(vi, viend, b); -#endif if ( found == viend ) return false; @@ -287,17 +273,7 @@ namespace boost { out_found; boost::tie(oi, oiend) = out_edges(a, g); -#if defined(BOOST_MSVC) && BOOST_MSVC <= 1300 && defined(__SGI_STL_PORT) - // Getting internal compiler error with std::find() - out_found = oiend; - for (; oi != oiend; ++oi) - if (target(*oi, g) == b) { - out_found = oi; - break; - } -#else out_found = std::find_if(oi, oiend, incident_to(b, g)); -#endif if (out_found == oiend) return false; return true; diff --git a/include/boost/graph/graphml.hpp b/include/boost/graph/graphml.hpp index 6afa12c96..be73def30 100644 --- a/include/boost/graph/graphml.hpp +++ b/include/boost/graph/graphml.hpp @@ -204,14 +204,14 @@ template 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); +read_graphml(std::istream& in, mutate_graph& g, size_t desired_idx); template void -read_graphml(std::istream& in, MutableGraph& g, dynamic_properties& dp) +read_graphml(std::istream& in, MutableGraph& g, dynamic_properties& dp, size_t desired_idx = 0) { mutate_graph_impl mg(g,dp); - read_graphml(in, mg); + read_graphml(in, mg, desired_idx); } template @@ -262,8 +262,8 @@ write_graphml(std::ostream& out, const Graph& g, VertexIndexMap vertex_index, for (dynamic_properties::const_iterator i = dp.begin(); i != dp.end(); ++i) { std::string key_id = "key" + lexical_cast(key_count++); - if (i->second->key() == typeid(Graph)) - vertex_key_ids[i->first] = key_id; + if (i->second->key() == typeid(Graph*)) + graph_key_ids[i->first] = key_id; else if (i->second->key() == typeid(vertex_descriptor)) vertex_key_ids[i->first] = key_id; else if (i->second->key() == typeid(edge_descriptor)) @@ -273,7 +273,7 @@ write_graphml(std::ostream& out, const Graph& g, VertexIndexMap vertex_index, std::string type_name = "string"; mpl::for_each(get_type_name(i->second->value(), type_names, type_name)); out << " second->key() == typeid(Graph) ? "graph" : (i->second->key() == typeid(vertex_descriptor) ? "node" : "edge")) << "\"" + << (i->second->key() == typeid(Graph*) ? "graph" : (i->second->key() == typeid(vertex_descriptor) ? "node" : "edge")) << "\"" << " attr.name=\"" << i->first << "\"" << " attr.type=\"" << type_name << "\"" << " />\n"; @@ -287,10 +287,12 @@ write_graphml(std::ostream& out, const Graph& g, VertexIndexMap vertex_index, // Output graph data for (dynamic_properties::const_iterator i = dp.begin(); i != dp.end(); ++i) { - if (i->second->key() == typeid(Graph)) + if (i->second->key() == typeid(Graph*)) { + // The const_cast here is just to get typeid correct for property + // map key; the graph should not be mutated using it. out << " first] << "\">" - << encode_char_entities(i->second->get_string(g)) << "\n"; + << encode_char_entities(i->second->get_string(const_cast(&g))) << "\n"; } } diff --git a/include/boost/graph/graphviz.hpp b/include/boost/graph/graphviz.hpp index 1e6aeaf00..1c8cb194a 100644 --- a/include/boost/graph/graphviz.hpp +++ b/include/boost/graph/graphviz.hpp @@ -25,10 +25,14 @@ #include #include #include +#include +#include #include #include +#include #include #include +#include namespace boost { @@ -67,7 +71,8 @@ namespace boost { if (regex_match(s, valid_unquoted_id)) { return s; } else { - return "\"" + regex_replace(s, sregex(as_xpr('"')), "\\\"") + "\""; + boost::algorithm::replace_all(s, "\"", "\\\""); + return "\"" + s + "\""; } } @@ -284,8 +289,6 @@ namespace boost { BOOST_GRAPH_ENABLE_IF_MODELS_PARM(Graph,vertex_list_graph_tag)) { write_graphviz(out, g, vpw, epw, gpw, get(vertex_index, g)); } -#if !defined(BOOST_MSVC) || BOOST_MSVC > 1300 - // ambiguous overload problem with VC++ template inline void write_graphviz(std::ostream& out, const Graph& g @@ -295,7 +298,6 @@ namespace boost { default_writer gw; write_graphviz(out, g, dw, dw, gw); } -#endif template inline void @@ -344,21 +346,7 @@ namespace boost { typename Graph::const_children_iterator i_child, j_child; //print graph/node/edge attributes -#if defined(BOOST_MSVC) && BOOST_MSVC <= 1300 - typedef typename graph_property::type - GAttrMap; - typedef typename graph_property::type - NAttrMap; - typedef typename graph_property::type - EAttrMap; - GAttrMap gam = get_property(g, graph_graph_attribute); - NAttrMap nam = get_property(g, graph_vertex_attribute); - EAttrMap eam = get_property(g, graph_edge_attribute); - graph_attributes_writer writer(gam, nam, eam); - writer(out); -#else make_graph_attributes_writer(g)(out); -#endif //print subgraph for ( boost::tie(i_child,j_child) = g.children(); @@ -377,15 +365,7 @@ namespace boost { if ( vertex_marker[pos] ) { vertex_marker[pos] = false; out << escape_dot_string(pos); -#if defined(BOOST_MSVC) && BOOST_MSVC <= 1300 - typedef typename property_map::const_type - VertexAttributeMap; - attributes_writer vawriter(get(vertex_attribute, - g.root())); - vawriter(out, v); -#else make_vertex_attributes_writer(g.root())(out, v); -#endif out << ";" << std::endl; } } @@ -398,14 +378,7 @@ namespace boost { edge_marker[pos] = false; out << escape_dot_string(get(vertex_id, u)) << " " << Traits::delimiter() << " " << escape_dot_string(get(vertex_id, v)); -#if defined(BOOST_MSVC) && BOOST_MSVC <= 1300 - typedef typename property_map::const_type - EdgeAttributeMap; - attributes_writer eawriter(get(edge_attribute, g)); - eawriter(out, *ei); -#else make_edge_attributes_writer(g)(out, *ei); //print edge properties -#endif out << ";" << std::endl; } } @@ -563,6 +536,28 @@ namespace boost { const std::string* node_id; }; + template + class dynamic_graph_properties_writer + { + public: + dynamic_graph_properties_writer(const dynamic_properties& dp, const Graph& g) : g(&g), dp(&dp) { } + + void operator()(std::ostream& out) const + { + for (dynamic_properties::const_iterator i = dp->begin(); + i != dp->end(); ++i) { + if (typeid(Graph*) == i->second->key()) { + // const_cast here is to match interface used in read_graphviz + out << i->first << "=" << escape_dot_string(i->second->get_string(const_cast(g))) << ";\n"; + } + } + } + + private: + const Graph* g; + const dynamic_properties* dp; + }; + namespace graph { namespace detail { template @@ -614,7 +609,7 @@ namespace boost { (out, g, /*vertex_writer=*/dynamic_vertex_properties_writer(dp, node_id), /*edge_writer=*/dynamic_properties_writer(dp), - /*graph_writer=*/default_writer(), + /*graph_writer=*/dynamic_graph_properties_writer(dp, g), id); } @@ -712,6 +707,9 @@ class mutate_graph virtual void // RG: need new second parameter to support BGL subgraphs set_graph_property(const id_t& key, const id_t& value) = 0; + + virtual void + finish_building_graph() = 0; }; template @@ -780,6 +778,8 @@ class mutate_graph_impl : public mutate_graph put(key, dp_, &graph_, value); } + void finish_building_graph() {} + protected: MutableGraph& graph_; @@ -789,6 +789,109 @@ class mutate_graph_impl : public mutate_graph std::map bgl_edges; }; +template +class mutate_graph_impl > + : public mutate_graph +{ + typedef compressed_sparse_row_graph CSRGraph; + typedef typename graph_traits::vertices_size_type bgl_vertex_t; + typedef typename graph_traits::edges_size_type bgl_edge_t; + typedef typename graph_traits::edge_descriptor edge_descriptor; + + public: + mutate_graph_impl(CSRGraph& graph, dynamic_properties& dp, + std::string node_id_prop) + : graph_(graph), dp_(dp), vertex_count(0), node_id_prop_(node_id_prop) { } + + ~mutate_graph_impl() {} + + void finish_building_graph() { + typedef compressed_sparse_row_graph TempCSRGraph; + TempCSRGraph temp(edges_are_unsorted_multi_pass, + edges_to_add.begin(), edges_to_add.end(), + counting_iterator(0), + vertex_count); + set_property(temp, graph_all, get_property(graph_, graph_all)); + graph_.assign(temp); // Copies structure, not properties + std::vector edge_permutation_from_sorting(num_edges(temp)); + BGL_FORALL_EDGES_T(e, temp, TempCSRGraph) { + edge_permutation_from_sorting[temp[e]] = e; + } + typedef boost::tuple v_prop; + BOOST_FOREACH(const v_prop& t, vertex_props) { + put(boost::get<0>(t), dp_, boost::get<1>(t), boost::get<2>(t)); + } + typedef boost::tuple e_prop; + BOOST_FOREACH(const e_prop& t, edge_props) { + put(boost::get<0>(t), dp_, edge_permutation_from_sorting[boost::get<1>(t)], boost::get<2>(t)); + } + } + + bool is_directed() const + { + return + boost::is_convertible< + typename boost::graph_traits::directed_category, + boost::directed_tag>::value; + } + + virtual void do_add_vertex(const node_t& node) + { + // Add the node to the graph. + bgl_vertex_t v = vertex_count++; + + // Set up a mapping from name to BGL vertex. + bgl_nodes.insert(std::make_pair(node, v)); + + // node_id_prop_ allows the caller to see the real id names for nodes. + vertex_props.push_back(boost::make_tuple(node_id_prop_, v, node)); + } + + void + do_add_edge(const edge_t& edge, const node_t& source, const node_t& target) + { + bgl_edge_t result = edges_to_add.size(); + edges_to_add.push_back(std::make_pair(bgl_nodes[source], bgl_nodes[target])); + bgl_edges.insert(std::make_pair(edge, result)); + } + + void + set_node_property(const id_t& key, const node_t& node, const id_t& value) + { + vertex_props.push_back(boost::make_tuple(key, bgl_nodes[node], value)); + } + + void + set_edge_property(const id_t& key, const edge_t& edge, const id_t& value) + { + edge_props.push_back(boost::make_tuple(key, bgl_edges[edge], value)); + } + + void + set_graph_property(const id_t& key, const id_t& value) + { + /* RG: pointer to graph prevents copying */ + put(key, dp_, &graph_, value); + } + + + protected: + CSRGraph& graph_; + dynamic_properties& dp_; + bgl_vertex_t vertex_count; + std::string node_id_prop_; + std::vector > vertex_props; + std::vector > edge_props; + std::vector > edges_to_add; + std::map bgl_nodes; + std::map bgl_edges; +}; + } } } // end namespace boost::detail::graph #ifdef BOOST_GRAPH_USE_SPIRIT_PARSER diff --git a/include/boost/graph/grid_graph.hpp b/include/boost/graph/grid_graph.hpp index 9eff52591..9a09fca34 100644 --- a/include/boost/graph/grid_graph.hpp +++ b/include/boost/graph/grid_graph.hpp @@ -17,7 +17,6 @@ #include #include #include -#include #include #include #include @@ -31,11 +30,6 @@ #define BOOST_GRID_GRAPH_TYPE \ grid_graph -#define BOOST_GRID_GRAPH_TYPE_MEM typename BOOST_GRID_GRAPH_TYPE:: - -#define BOOST_GRID_GRAPH_TYPE_TD(mem) \ - typedef typename BOOST_GRID_GRAPH_TYPE::mem mem - #define BOOST_GRID_GRAPH_TRAITS_T \ typename graph_traits @@ -63,14 +57,21 @@ namespace boost { grid_graph_index_map() { } grid_graph_index_map(const Graph& graph) : - m_graph(make_shared(graph)) { } + m_graph(&graph) { } value_type operator[](key_type key) const { return (m_graph->index_of(key)); } + friend inline Index + get(const grid_graph_index_map& index_map, + const typename grid_graph_index_map::key_type& key) + { + return (index_map[key]); + } + protected: - shared_ptr m_graph; + const Graph* m_graph; }; template @@ -89,6 +90,39 @@ namespace boost { typedef type const_type; }; + //========================== + // Reverse Edge Property Map + //========================== + + template + struct grid_graph_reverse_edge_map { + public: + typedef Descriptor value_type; + typedef Descriptor reference_type; + typedef reference_type reference; + typedef Descriptor key_type; + typedef readable_property_map_tag category; + + grid_graph_reverse_edge_map() { } + + value_type operator[](const key_type& key) const { + return (value_type(key.second, key.first)); + } + + friend inline Descriptor + get(const grid_graph_reverse_edge_map& rev_map, + const typename grid_graph_reverse_edge_map::key_type& key) + { + return (rev_map[key]); + } + }; + + template + struct property_map { + typedef grid_graph_reverse_edge_map type; + typedef type const_type; + }; + //================= // Function Objects //================= @@ -268,7 +302,7 @@ namespace boost { typedef transform_iterator adjacency_iterator; // categories - typedef undirected_tag directed_category; + typedef directed_tag directed_category; typedef disallow_parallel_edge_tag edge_parallel_category; struct traversal_category : virtual public incidence_graph_tag, virtual public adjacency_graph_tag, @@ -351,7 +385,7 @@ namespace boost { // Stop at the end of this dimension if necessary. new_position = (std::min)(new_position, - length(dimension_index) - 1); + vertices_size_type(length(dimension_index) - 1)); } vertex[dimension_index] = new_position; @@ -417,7 +451,7 @@ namespace boost { vertex_descriptor vertex_at (vertices_size_type vertex_index) const { - array vertex; + boost::array vertex; vertices_size_type index_divider = 1; for (std::size_t dimension_index = 0; @@ -507,6 +541,8 @@ namespace boost { vertex_descriptor source_vertex = source(edge, *this); vertex_descriptor target_vertex = target(edge, *this); + BOOST_ASSERT (source_vertex != target_vertex); + // Determine the dimension where the source and target vertices // differ (should only be one if this is a valid edge). std::size_t different_dimension_index = 0; @@ -671,7 +707,8 @@ namespace boost { void precalculate() { m_num_vertices = std::accumulate(m_dimension_lengths.begin(), - m_dimension_lengths.end(), 1, + m_dimension_lengths.end(), + vertices_size_type(1), std::multiplies()); // Calculate number of edges in each dimension @@ -706,13 +743,12 @@ namespace boost { // VertexListGraph //================ - template - friend inline std::pair - vertices(const BOOST_GRID_GRAPH_TYPE& graph) { - BOOST_GRID_GRAPH_TYPE_TD(vertex_iterator); - BOOST_GRID_GRAPH_TYPE_TD(vertex_function); - BOOST_GRID_GRAPH_TYPE_TD(vertex_index_iterator); + friend inline std::pair + vertices(const type& graph) { + typedef typename type::vertex_iterator vertex_iterator; + typedef typename type::vertex_function vertex_function; + typedef typename type::vertex_index_iterator vertex_index_iterator; return (std::make_pair (vertex_iterator(vertex_index_iterator(0), @@ -721,16 +757,14 @@ namespace boost { vertex_function(&graph)))); } - template - friend inline BOOST_GRID_GRAPH_TYPE_MEM vertices_size_type - num_vertices(const BOOST_GRID_GRAPH_TYPE& graph) { + friend inline typename type::vertices_size_type + num_vertices(const type& graph) { return (graph.num_vertices()); } - template - friend inline BOOST_GRID_GRAPH_TYPE_MEM vertex_descriptor - vertex(BOOST_GRID_GRAPH_TYPE_MEM vertices_size_type vertex_index, - const BOOST_GRID_GRAPH_TYPE& graph) { + friend inline typename type::vertex_descriptor + vertex(typename type::vertices_size_type vertex_index, + const type& graph) { return (graph.vertex_at(vertex_index)); } @@ -739,14 +773,13 @@ namespace boost { // IncidenceGraph //=============== - template - friend inline std::pair - out_edges(BOOST_GRID_GRAPH_TYPE_MEM vertex_descriptor vertex, - const BOOST_GRID_GRAPH_TYPE& graph) { - BOOST_GRID_GRAPH_TYPE_TD(degree_iterator); - BOOST_GRID_GRAPH_TYPE_TD(out_edge_function); - BOOST_GRID_GRAPH_TYPE_TD(out_edge_iterator); + friend inline std::pair + out_edges(typename type::vertex_descriptor vertex, + const type& graph) { + typedef typename type::degree_iterator degree_iterator; + typedef typename type::out_edge_function out_edge_function; + typedef typename type::out_edge_iterator out_edge_iterator; return (std::make_pair (out_edge_iterator(degree_iterator(0), @@ -755,19 +788,17 @@ namespace boost { out_edge_function(vertex, &graph)))); } - template - friend inline BOOST_GRID_GRAPH_TYPE_MEM degree_size_type + friend inline typename type::degree_size_type out_degree - (BOOST_GRID_GRAPH_TYPE_MEM vertex_descriptor vertex, - const BOOST_GRID_GRAPH_TYPE& graph) { + (typename type::vertex_descriptor vertex, + const type& graph) { return (graph.out_degree(vertex)); } - template - friend inline BOOST_GRID_GRAPH_TYPE_MEM edge_descriptor - out_edge_at(BOOST_GRID_GRAPH_TYPE_MEM vertex_descriptor vertex, - BOOST_GRID_GRAPH_TYPE_MEM degree_size_type out_edge_index, - const BOOST_GRID_GRAPH_TYPE& graph) { + friend inline typename type::edge_descriptor + out_edge_at(typename type::vertex_descriptor vertex, + typename type::degree_size_type out_edge_index, + const type& graph) { return (graph.out_edge_at(vertex, out_edge_index)); } @@ -775,14 +806,13 @@ namespace boost { // AdjacencyGraph //=============== - template - friend typename std::pair - adjacent_vertices (BOOST_GRID_GRAPH_TYPE_MEM vertex_descriptor vertex, - const BOOST_GRID_GRAPH_TYPE& graph) { - BOOST_GRID_GRAPH_TYPE_TD(degree_iterator); - BOOST_GRID_GRAPH_TYPE_TD(adjacent_vertex_function); - BOOST_GRID_GRAPH_TYPE_TD(adjacency_iterator); + friend typename std::pair + adjacent_vertices (typename type::vertex_descriptor vertex, + const type& graph) { + typedef typename type::degree_iterator degree_iterator; + typedef typename type::adjacent_vertex_function adjacent_vertex_function; + typedef typename type::adjacency_iterator adjacency_iterator; return (std::make_pair (adjacency_iterator(degree_iterator(0), @@ -795,26 +825,23 @@ namespace boost { // EdgeListGraph //============== - template - friend inline BOOST_GRID_GRAPH_TYPE_MEM edges_size_type - num_edges(const BOOST_GRID_GRAPH_TYPE& graph) { + friend inline typename type::edges_size_type + num_edges(const type& graph) { return (graph.num_edges()); } - template - friend inline BOOST_GRID_GRAPH_TYPE_MEM edge_descriptor - edge_at(BOOST_GRID_GRAPH_TYPE_MEM edges_size_type edge_index, - const BOOST_GRID_GRAPH_TYPE& graph) { + friend inline typename type::edge_descriptor + edge_at(typename type::edges_size_type edge_index, + const type& graph) { return (graph.edge_at(edge_index)); } - template - friend inline std::pair - edges(const BOOST_GRID_GRAPH_TYPE& graph) { - BOOST_GRID_GRAPH_TYPE_TD(edge_index_iterator); - BOOST_GRID_GRAPH_TYPE_TD(edge_function); - BOOST_GRID_GRAPH_TYPE_TD(edge_iterator); + friend inline std::pair + edges(const type& graph) { + typedef typename type::edge_index_iterator edge_index_iterator; + typedef typename type::edge_function edge_function; + typedef typename type::edge_iterator edge_iterator; return (std::make_pair (edge_iterator(edge_index_iterator(0), @@ -827,14 +854,13 @@ namespace boost { // BiDirectionalGraph //=================== - template - friend inline std::pair - in_edges(BOOST_GRID_GRAPH_TYPE_MEM vertex_descriptor vertex, - const BOOST_GRID_GRAPH_TYPE& graph) { - BOOST_GRID_GRAPH_TYPE_TD(in_edge_function); - BOOST_GRID_GRAPH_TYPE_TD(degree_iterator); - BOOST_GRID_GRAPH_TYPE_TD(in_edge_iterator); + friend inline std::pair + in_edges(typename type::vertex_descriptor vertex, + const type& graph) { + typedef typename type::in_edge_function in_edge_function; + typedef typename type::degree_iterator degree_iterator; + typedef typename type::in_edge_iterator in_edge_iterator; return (std::make_pair (in_edge_iterator(degree_iterator(0), @@ -843,25 +869,22 @@ namespace boost { in_edge_function(vertex, &graph)))); } - template - friend inline BOOST_GRID_GRAPH_TYPE_MEM degree_size_type - in_degree (BOOST_GRID_GRAPH_TYPE_MEM vertex_descriptor vertex, - const BOOST_GRID_GRAPH_TYPE& graph) { + friend inline typename type::degree_size_type + in_degree (typename type::vertex_descriptor vertex, + const type& graph) { return (graph.in_degree(vertex)); } - template - friend inline BOOST_GRID_GRAPH_TYPE_MEM degree_size_type - degree (BOOST_GRID_GRAPH_TYPE_MEM vertex_descriptor vertex, - const BOOST_GRID_GRAPH_TYPE& graph) { + friend inline typename type::degree_size_type + degree (typename type::vertex_descriptor vertex, + const type& graph) { return (graph.out_degree(vertex) * 2); } - template - friend inline BOOST_GRID_GRAPH_TYPE_MEM edge_descriptor - in_edge_at(BOOST_GRID_GRAPH_TYPE_MEM vertex_descriptor vertex, - BOOST_GRID_GRAPH_TYPE_MEM degree_size_type in_edge_index, - const BOOST_GRID_GRAPH_TYPE& graph) { + friend inline typename type::edge_descriptor + in_edge_at(typename type::vertex_descriptor vertex, + typename type::degree_size_type in_edge_index, + const type& graph) { return (graph.in_edge_at(vertex, in_edge_index)); } @@ -870,21 +893,20 @@ namespace boost { // Adjacency Matrix //================== - template - friend std::pair - edge (BOOST_GRID_GRAPH_TYPE_MEM vertex_descriptor source_vertex, - BOOST_GRID_GRAPH_TYPE_MEM vertex_descriptor destination_vertex, - const BOOST_GRID_GRAPH_TYPE& graph) { + friend std::pair + edge (typename type::vertex_descriptor source_vertex, + typename type::vertex_descriptor destination_vertex, + const type& graph) { - std::pair edge_exists = + std::pair edge_exists = std::make_pair(std::make_pair(source_vertex, destination_vertex), false); for (std::size_t dimension_index = 0; dimension_index < Dimensions; ++dimension_index) { - BOOST_GRID_GRAPH_TYPE_MEM vertices_size_type dim_difference = 0; - BOOST_GRID_GRAPH_TYPE_MEM vertices_size_type + typename type::vertices_size_type dim_difference = 0; + typename type::vertices_size_type source_dim = source_vertex[dimension_index], dest_dim = destination_vertex[dimension_index]; @@ -931,68 +953,62 @@ namespace boost { // Index Property Map Functions //============================= - template - friend inline BOOST_GRID_GRAPH_TYPE_MEM vertices_size_type + friend inline typename type::vertices_size_type get(vertex_index_t, - const BOOST_GRID_GRAPH_TYPE& graph, - BOOST_GRID_GRAPH_TYPE_MEM vertex_descriptor vertex) { + const type& graph, + typename type::vertex_descriptor vertex) { return (graph.index_of(vertex)); } - template - friend inline BOOST_GRID_GRAPH_TYPE_MEM edges_size_type + friend inline typename type::edges_size_type get(edge_index_t, - const BOOST_GRID_GRAPH_TYPE& graph, - BOOST_GRID_GRAPH_TYPE_MEM edge_descriptor edge) { + const type& graph, + typename type::edge_descriptor edge) { return (graph.index_of(edge)); } - template friend inline grid_graph_index_map< - BOOST_GRID_GRAPH_TYPE, - BOOST_GRID_GRAPH_TYPE_MEM vertex_descriptor, - BOOST_GRID_GRAPH_TYPE_MEM vertices_size_type> - get(vertex_index_t, const BOOST_GRID_GRAPH_TYPE& graph) { + type, + typename type::vertex_descriptor, + typename type::vertices_size_type> + get(vertex_index_t, const type& graph) { return (grid_graph_index_map< - BOOST_GRID_GRAPH_TYPE, - BOOST_GRID_GRAPH_TYPE_MEM vertex_descriptor, - BOOST_GRID_GRAPH_TYPE_MEM vertices_size_type>(graph)); + type, + typename type::vertex_descriptor, + typename type::vertices_size_type>(graph)); } - template friend inline grid_graph_index_map< - BOOST_GRID_GRAPH_TYPE, - BOOST_GRID_GRAPH_TYPE_MEM edge_descriptor, - BOOST_GRID_GRAPH_TYPE_MEM edges_size_type> - get(edge_index_t, const BOOST_GRID_GRAPH_TYPE& graph) { + type, + typename type::edge_descriptor, + typename type::edges_size_type> + get(edge_index_t, const type& graph) { return (grid_graph_index_map< - BOOST_GRID_GRAPH_TYPE, - BOOST_GRID_GRAPH_TYPE_MEM edge_descriptor, - BOOST_GRID_GRAPH_TYPE_MEM edges_size_type>(graph)); + type, + typename type::edge_descriptor, + typename type::edges_size_type>(graph)); } - template - friend inline Index - get(const grid_graph_index_map& index_map, - const typename grid_graph_index_map::key_type& key) - { - return (index_map[key]); - } + friend inline grid_graph_reverse_edge_map< + typename type::edge_descriptor> + get(edge_reverse_t, const type& graph) { + return (grid_graph_reverse_edge_map< + typename type::edge_descriptor>()); + } template friend struct grid_graph_index_map; + template + friend struct grid_graph_reverse_edge_map; + }; // grid_graph } // namespace boost #undef BOOST_GRID_GRAPH_TYPE -#undef BOOST_GRID_GRAPH_TYPE_TD -#undef BOOST_GRID_GRAPH_TYPE_MEM #undef BOOST_GRID_GRAPH_TEMPLATE_PARAMS #undef BOOST_GRID_GRAPH_TRAITS_T diff --git a/include/boost/graph/gursoy_atun_layout.hpp b/include/boost/graph/gursoy_atun_layout.hpp index b16a01f68..9f050e1b3 100644 --- a/include/boost/graph/gursoy_atun_layout.hpp +++ b/include/boost/graph/gursoy_atun_layout.hpp @@ -17,6 +17,7 @@ #include #include +#include #include #include #include @@ -169,7 +170,7 @@ gursoy_atun_step } min_distance_unset = false; } - assert (!min_distance_unset); // Graph must have at least one vertex + BOOST_ASSERT (!min_distance_unset); // Graph must have at least one vertex boost::detail::update_position_visitor< PositionMap, NodeDistanceMap, Topology, VertexListAndIncidenceGraph> @@ -207,9 +208,6 @@ void gursoy_atun_refine(const VertexListAndIncidenceGraph& graph, typedef typename graph_traits::vertex_iterator vertex_iterator; - typedef typename graph_traits::vertex_descriptor - vertex_descriptor; - typedef typename Topology::point_type point_type; vertex_iterator i, iend; double diameter_ratio = (double)diameter_final / diameter_initial; double learning_constant_ratio = @@ -229,6 +227,7 @@ void gursoy_atun_refine(const VertexListAndIncidenceGraph& graph, vertex_index_map); for (int round = 0; round < nsteps; ++round) { double part_done = (double)round / (nsteps - 1); + // fprintf(stderr, "%2d%% done\n", int(rint(part_done * 100.))); int diameter = (int)(diameter_initial * pow(diameter_ratio, part_done)); double learning_constant = learning_constant_initial * pow(learning_constant_ratio, part_done); diff --git a/include/boost/graph/hawick_circuits.hpp b/include/boost/graph/hawick_circuits.hpp new file mode 100644 index 000000000..93c12b5c7 --- /dev/null +++ b/include/boost/graph/hawick_circuits.hpp @@ -0,0 +1,381 @@ +// Copyright Louis Dionne 2013 + +// Use, modification and distribution is subject to the Boost Software +// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy +// at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GRAPH_HAWICK_CIRCUITS_HPP +#define BOOST_GRAPH_HAWICK_CIRCUITS_HPP + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include // for boost::tie +#include +#include +#include +#include // for std::pair +#include + + +namespace boost { +namespace hawick_circuits_detail { +//! @internal Functor returning all the vertices adjacent to a vertex. +struct get_all_adjacent_vertices { + template + struct result; + + template + struct result { + private: + typedef typename remove_reference::type RawGraph; + typedef graph_traits Traits; + typedef typename Traits::adjacency_iterator AdjacencyIterator; + + public: + typedef std::pair type; + }; + + template + typename result< + get_all_adjacent_vertices(BOOST_FWD_REF(Vertex), BOOST_FWD_REF(Graph)) + >::type + operator()(BOOST_FWD_REF(Vertex) v, BOOST_FWD_REF(Graph) g) const { + return adjacent_vertices(boost::forward(v), + boost::forward(g)); + } +}; + +//! @internal Functor returning a set of the vertices adjacent to a vertex. +struct get_unique_adjacent_vertices { + template + struct result; + + template + struct result { + typedef std::set::type> type; + }; + + template + typename result::type + operator()(Vertex v, Graph const& g) const { + typedef typename result< + get_unique_adjacent_vertices(Vertex, Graph const&) + >::type Set; + return Set(adjacent_vertices(v, g).first, + adjacent_vertices(v, g).second); + } +}; + +//! @internal +//! Return whether a container contains a given value. +//! This is not meant as a general purpose membership testing function; it +//! would have to be more clever about possible optimizations. +template +bool contains(Container const& c, Value const& v) { + return std::find(boost::begin(c), boost::end(c), v) != boost::end(c); +} + +/*! + * @internal + * Algorithm finding all the cycles starting from a given vertex. + * + * The search is only done in the subgraph induced by the starting vertex + * and the vertices with an index higher than the starting vertex. + */ +template < + typename Graph, + typename Visitor, + typename VertexIndexMap, + typename Stack, + typename ClosedMatrix, + typename GetAdjacentVertices +> +struct hawick_circuits_from { +private: + typedef graph_traits Traits; + typedef typename Traits::vertex_descriptor Vertex; + typedef typename Traits::edge_descriptor Edge; + typedef typename Traits::vertices_size_type VerticesSize; + typedef typename property_traits::value_type VertexIndex; + + typedef typename result_of< + GetAdjacentVertices(Vertex, Graph const&) + >::type AdjacentVertices; + typedef typename range_iterator::type AdjacencyIterator; + + // The one_bit_color_map starts all white, i.e. not blocked. + // Since we make that assumption (I looked at the implementation, but + // I can't find anything that documents this behavior), we're gonna + // assert it in the constructor. + typedef one_bit_color_map BlockedMap; + typedef typename property_traits::value_type BlockedColor; + + static BlockedColor blocked_false_color() + { return color_traits::white(); } + + static BlockedColor blocked_true_color() + { return color_traits::black(); } + + // This is used by the constructor to secure the assumption + // documented above. + bool blocked_map_starts_all_unblocked() const { + BOOST_FOREACH(Vertex v, vertices(graph_)) + if (is_blocked(v)) + return false; + return true; + } + + // This is only used in the constructor to make sure the optimization of + // sharing data structures between iterations does not break the code. + bool all_closed_rows_are_empty() const { + BOOST_FOREACH(typename ClosedMatrix::reference row, closed_) + if (!row.empty()) + return false; + return true; + } + +public: + hawick_circuits_from(Graph const& graph, Visitor& visitor, + VertexIndexMap const& vim, + Stack& stack, ClosedMatrix& closed, + VerticesSize n_vertices) + : graph_(graph), visitor_(visitor), vim_(vim), stack_(stack), + closed_(closed), blocked_(n_vertices, vim_) + { + BOOST_ASSERT(blocked_map_starts_all_unblocked()); + + // Since sharing the data structures between iterations is + // just an optimization, it must always be equivalent to + // constructing new ones in this constructor. + BOOST_ASSERT(stack_.empty()); + BOOST_ASSERT(closed_.size() == n_vertices); + BOOST_ASSERT(all_closed_rows_are_empty()); + } + +private: + //! @internal Return the index of a given vertex. + VertexIndex index_of(Vertex v) const { + return get(vim_, v); + } + + + //! @internal Return whether a vertex `v` is closed to a vertex `u`. + bool is_closed_to(Vertex u, Vertex v) const { + typedef typename ClosedMatrix::const_reference VertexList; + VertexList closed_to_u = closed_[index_of(u)]; + return contains(closed_to_u, v); + } + + //! @internal Close a vertex `v` to a vertex `u`. + void close_to(Vertex u, Vertex v) { + BOOST_ASSERT(!is_closed_to(u, v)); + closed_[index_of(u)].push_back(v); + } + + + //! @internal Return whether a given vertex is blocked. + bool is_blocked(Vertex v) const { + return get(blocked_, v) == blocked_true_color(); + } + + //! @internal Block a given vertex. + void block(Vertex v) { + put(blocked_, v, blocked_true_color()); + } + + //! @internal Unblock a given vertex. + void unblock(Vertex u) { + typedef typename ClosedMatrix::reference VertexList; + + put(blocked_, u, blocked_false_color()); + VertexList closed_to_u = closed_[index_of(u)]; + + while (!closed_to_u.empty()) { + Vertex const w = closed_to_u.back(); + closed_to_u.pop_back(); + if (is_blocked(w)) + unblock(w); + } + BOOST_ASSERT(closed_to_u.empty()); + } + + //! @internal Main procedure as described in the paper. + bool circuit(Vertex start, Vertex v) { + bool found_circuit = false; + stack_.push_back(v); + block(v); + + // Cache some values that are used more than once in the function. + VertexIndex const index_of_start = index_of(start); + AdjacentVertices const adj_vertices = GetAdjacentVertices()(v, graph_); + AdjacencyIterator const w_end = boost::end(adj_vertices); + + for (AdjacencyIterator w_it = boost::begin(adj_vertices); + w_it != w_end; + ++w_it) + { + Vertex const w = *w_it; + // Since we're only looking in the subgraph induced by `start` + // and the vertices with an index higher than `start`, we skip + // any vertex that does not satisfy that. + if (index_of(w) < index_of_start) + continue; + + // If the last vertex is equal to `start`, we have a circuit. + else if (w == start) { + // const_cast to ensure the visitor does not modify the stack + visitor_.cycle(const_cast(stack_), graph_); + found_circuit = true; + } + + // If `w` is not blocked, we continue searching further down the + // same path for a cycle with `w` in it. + else if (!is_blocked(w) && circuit(start, w)) + found_circuit = true; + } + + if (found_circuit) + unblock(v); + else + for (AdjacencyIterator w_it = boost::begin(adj_vertices); + w_it != w_end; + ++w_it) + { + Vertex const w = *w_it; + // Like above, we skip vertices that are not in the subgraph + // we're considering. + if (index_of(w) < index_of_start) + continue; + + // If `v` is not closed to `w`, we make it so. + if (!is_closed_to(w, v)) + close_to(w, v); + } + + BOOST_ASSERT(v == stack_.back()); + stack_.pop_back(); + return found_circuit; + } + +public: + void operator()(Vertex start) { + circuit(start, start); + } + +private: + Graph const& graph_; + Visitor& visitor_; + VertexIndexMap const& vim_; + Stack& stack_; + ClosedMatrix& closed_; + BlockedMap blocked_; +}; + +template < + typename GetAdjacentVertices, + typename Graph, typename Visitor, typename VertexIndexMap +> +void call_hawick_circuits(Graph const& graph, + Visitor /* by value */ visitor, + VertexIndexMap const& vertex_index_map) { + typedef graph_traits Traits; + typedef typename Traits::vertex_descriptor Vertex; + typedef typename Traits::vertices_size_type VerticesSize; + typedef typename Traits::vertex_iterator VertexIterator; + + typedef std::vector Stack; + typedef std::vector > ClosedMatrix; + + typedef hawick_circuits_from< + Graph, Visitor, VertexIndexMap, Stack, ClosedMatrix, + GetAdjacentVertices + > SubAlgorithm; + + VerticesSize const n_vertices = num_vertices(graph); + Stack stack; stack.reserve(n_vertices); + ClosedMatrix closed(n_vertices); + + VertexIterator start, last; + for (boost::tie(start, last) = vertices(graph); start != last; ++start) { + // Note1: The sub algorithm may NOT be reused once it has been called. + + // Note2: We reuse the Stack and the ClosedMatrix (after clearing them) + // in each iteration to avoid redundant destruction and construction. + // It would be strictly equivalent to have these as member variables + // of the sub algorithm. + SubAlgorithm sub_algo(graph, visitor, vertex_index_map, + stack, closed, n_vertices); + sub_algo(*start); + stack.clear(); + typename ClosedMatrix::iterator row, last_row = closed.end(); + for (row = closed.begin(); row != last_row; ++row) + row->clear(); + } +} + +template +void call_hawick_circuits(Graph const& graph, BOOST_FWD_REF(Visitor) visitor) { + call_hawick_circuits( + graph, boost::forward(visitor), get(vertex_index, graph) + ); +} +} // end namespace hawick_circuits_detail + +//! Enumerate all the elementary circuits in a directed multigraph. +template +void hawick_circuits(BOOST_FWD_REF(Graph) graph, + BOOST_FWD_REF(Visitor) visitor, + BOOST_FWD_REF(VertexIndexMap) vertex_index_map) { + hawick_circuits_detail::call_hawick_circuits< + hawick_circuits_detail::get_all_adjacent_vertices + >( + boost::forward(graph), + boost::forward(visitor), + boost::forward(vertex_index_map) + ); +} + +template +void hawick_circuits(BOOST_FWD_REF(Graph) graph, + BOOST_FWD_REF(Visitor) visitor) { + hawick_circuits_detail::call_hawick_circuits< + hawick_circuits_detail::get_all_adjacent_vertices + >(boost::forward(graph), boost::forward(visitor)); +} + +/*! + * Same as `boost::hawick_circuits`, but duplicate circuits caused by parallel + * edges will not be considered. Each circuit will be considered only once. + */ +template +void hawick_unique_circuits(BOOST_FWD_REF(Graph) graph, + BOOST_FWD_REF(Visitor) visitor, + BOOST_FWD_REF(VertexIndexMap) vertex_index_map) { + hawick_circuits_detail::call_hawick_circuits< + hawick_circuits_detail::get_unique_adjacent_vertices + >( + boost::forward(graph), + boost::forward(visitor), + boost::forward(vertex_index_map) + ); +} + +template +void hawick_unique_circuits(BOOST_FWD_REF(Graph) graph, + BOOST_FWD_REF(Visitor) visitor) { + hawick_circuits_detail::call_hawick_circuits< + hawick_circuits_detail::get_unique_adjacent_vertices + >(boost::forward(graph), boost::forward(visitor)); +} +} // end namespace boost + +#endif // !BOOST_GRAPH_HAWICK_CIRCUITS_HPP diff --git a/include/boost/graph/howard_cycle_ratio.hpp b/include/boost/graph/howard_cycle_ratio.hpp index 09c6522b8..afbf26d87 100644 --- a/include/boost/graph/howard_cycle_ratio.hpp +++ b/include/boost/graph/howard_cycle_ratio.hpp @@ -20,6 +20,7 @@ #include #include #include +#include /** @file howard_cycle_ratio.hpp * @brief The implementation of the maximum/minimum cycle ratio/mean algorithm. @@ -477,13 +478,13 @@ namespace boost { { typedef typename graph_traits::directed_category DirCat; BOOST_STATIC_ASSERT((is_convertible::value == true)); - function_requires< IncidenceGraphConcept >(); - function_requires< VertexListGraphConcept >(); + BOOST_CONCEPT_ASSERT(( IncidenceGraphConcept )); + BOOST_CONCEPT_ASSERT(( VertexListGraphConcept )); typedef typename graph_traits::vertex_descriptor Vertex; - function_requires< ReadablePropertyMapConcept >(); + BOOST_CONCEPT_ASSERT(( ReadablePropertyMapConcept )); typedef typename graph_traits::edge_descriptor Edge; - function_requires< ReadablePropertyMapConcept >(); - function_requires< ReadablePropertyMapConcept >(); + BOOST_CONCEPT_ASSERT(( ReadablePropertyMapConcept )); + BOOST_CONCEPT_ASSERT(( ReadablePropertyMapConcept )); if(pcc == 0) { return detail::mcr_howard( diff --git a/include/boost/graph/is_kuratowski_subgraph.hpp b/include/boost/graph/is_kuratowski_subgraph.hpp index fab0b0246..d0a2aede9 100644 --- a/include/boost/graph/is_kuratowski_subgraph.hpp +++ b/include/boost/graph/is_kuratowski_subgraph.hpp @@ -9,7 +9,6 @@ #define __IS_KURATOWSKI_SUBGRAPH_HPP__ #include -#include //for next/prior #include //for tie #include #include @@ -33,7 +32,7 @@ namespace boost { typename graph_traits::vertex_iterator vi, vi_end, inner_vi; Graph K_5(5); - for(tie(vi,vi_end) = vertices(K_5); vi != vi_end; ++vi) + for(boost::tie(vi,vi_end) = vertices(K_5); vi != vi_end; ++vi) for(inner_vi = next(vi); inner_vi != vi_end; ++inner_vi) add_edge(*vi, *inner_vi, K_5); return K_5; @@ -47,7 +46,7 @@ namespace boost vi, vi_end, bipartition_start, inner_vi; Graph K_3_3(6); bipartition_start = next(next(next(vertices(K_3_3).first))); - for(tie(vi, vi_end) = vertices(K_3_3); vi != bipartition_start; ++vi) + for(boost::tie(vi, vi_end) = vertices(K_3_3); vi != bipartition_start; ++vi) for(inner_vi= bipartition_start; inner_vi != vi_end; ++inner_vi) add_edge(*vi, *inner_vi, K_3_3); return K_3_3; @@ -158,7 +157,7 @@ namespace boost { vertex_iterator_t vi, vi_end; - for(tie(vi,vi_end) = vertices(g); vi != vi_end; ++vi) + for(boost::tie(vi,vi_end) = vertices(g); vi != vi_end; ++vi) { vertex_t v(*vi); @@ -176,7 +175,7 @@ namespace boost while (neighbors[v].size() > 0 && neighbors[v].size() < max_size) { - // Find one of v's neighbors u such that that v and u + // Find one of v's neighbors u such that v and u // have no neighbors in common. We'll look for such a // neighbor with a naive cubic-time algorithm since the // max size of any of the neighbor sets we'll consider @@ -242,7 +241,7 @@ namespace boost if (max_size == 3) { // check to see whether we should go on to find a K_5 - for(tie(vi,vi_end) = vertices(g); vi != vi_end; ++vi) + for(boost::tie(vi,vi_end) = vertices(g); vi != vi_end; ++vi) if (neighbors[*vi].size() == 4) { target_graph = detail::tg_k_5; @@ -261,7 +260,7 @@ namespace boost v_list_t main_vertices; vertex_iterator_t vi, vi_end; - for(tie(vi,vi_end) = vertices(g); vi != vi_end; ++vi) + for(boost::tie(vi,vi_end) = vertices(g); vi != vi_end; ++vi) { if (!neighbors[*vi].empty()) main_vertices.push_back(*vi); @@ -301,11 +300,11 @@ namespace boost if (target_graph == detail::tg_k_5) { - return isomorphism(K_5,contracted_graph); + return boost::isomorphism(K_5,contracted_graph); } else //target_graph == tg_k_3_3 { - return isomorphism(K_3_3,contracted_graph); + return boost::isomorphism(K_3_3,contracted_graph); } diff --git a/include/boost/graph/is_straight_line_drawing.hpp b/include/boost/graph/is_straight_line_drawing.hpp index 6b7c39054..a4bd8ff5f 100644 --- a/include/boost/graph/is_straight_line_drawing.hpp +++ b/include/boost/graph/is_straight_line_drawing.hpp @@ -9,7 +9,7 @@ #define __IS_STRAIGHT_LINE_DRAWING_HPP__ #include -#include //for next and prior +#include #include #include #include @@ -19,6 +19,7 @@ #include #include #include +#include @@ -34,12 +35,12 @@ namespace boost // defines how far away from the endpoints of s1 and s2 we want to consider // an intersection. - bool intersects(double x1, double y1, - double x2, double y2, - double a1, double b1, - double a2, double b2, - double epsilon = 0.000001 - ) + inline bool intersects(double x1, double y1, + double x2, double y2, + double a1, double b1, + double a2, double b2, + double epsilon = 0.000001 + ) { if (x1 - x2 == 0) @@ -105,11 +106,8 @@ namespace boost { typedef typename graph_traits::vertex_descriptor vertex_t; - typedef typename graph_traits::vertex_iterator vertex_iterator_t; typedef typename graph_traits::edge_descriptor edge_t; typedef typename graph_traits::edge_iterator edge_iterator_t; - typedef typename graph_traits::edges_size_type e_size_t; - typedef typename graph_traits::vertices_size_type v_size_t; typedef std::size_t x_coord_t; typedef std::size_t y_coord_t; @@ -126,7 +124,7 @@ namespace boost active_map_t active_edges; edge_iterator_t ei, ei_end; - for(tie(ei,ei_end) = edges(g); ei != ei_end; ++ei) + for(boost::tie(ei,ei_end) = edges(g); ei != ei_end; ++ei) { edge_t e(*ei); vertex_t s(source(e,g)); diff --git a/include/boost/graph/isomorphism.hpp b/include/boost/graph/isomorphism.hpp index 9461dc31e..225cd2051 100644 --- a/include/boost/graph/isomorphism.hpp +++ b/include/boost/graph/isomorphism.hpp @@ -11,10 +11,12 @@ #include #include #include +#include +#include #include -#include #include #include // for make_indirect_pmap +#include #ifndef BOOST_GRAPH_ITERATION_MACROS_HPP #define BOOST_ISO_INCLUDED_ITER_MACROS // local macro, see bottom of file @@ -133,6 +135,10 @@ namespace boost { bool test_isomorphism() { + // reset isomapping + BGL_FORALL_VERTICES_T(v, G1, Graph1) + f[v] = graph_traits::null_vertex(); + { std::vector invar1_array; BGL_FORALL_VERTICES_T(v, G1, Graph1) @@ -153,7 +159,7 @@ namespace boost { { std::vector multiplicity(max_invariant, 0); BGL_FORALL_VERTICES_T(v, G1, Graph1) - ++multiplicity[invariant1(v)]; + ++multiplicity.at(invariant1(v)); sort(V_mult, compare_multiplicity(invariant1, &multiplicity[0])); } @@ -194,69 +200,130 @@ namespace boost { } private: + struct match_continuation { + enum {pos_G2_vertex_loop, pos_fi_adj_loop, pos_dfs_num} position; + typedef typename graph_traits::vertex_iterator vertex_iterator; + std::pair G2_verts; + typedef typename graph_traits::adjacency_iterator adjacency_iterator; + std::pair fi_adj; + edge_iter iter; + int dfs_num_k; + }; + bool match(edge_iter iter, int dfs_num_k) { + std::vector k; + typedef typename graph_traits::vertex_iterator vertex_iterator; + std::pair G2_verts(vertices(G2)); + typedef typename graph_traits::adjacency_iterator adjacency_iterator; + std::pair fi_adj; + vertex1_t i, j; + + recur: if (iter != ordered_edges.end()) { - vertex1_t i = source(*iter, G1), j = target(*iter, G2); + i = source(*iter, G1); + j = target(*iter, G1); if (dfs_num[i] > dfs_num_k) { - vertex1_t kp1 = dfs_vertices[dfs_num_k + 1]; - BGL_FORALL_VERTICES_T(u, G2, Graph2) { - if (invariant1(kp1) == invariant2(u) && in_S[u] == false) { - f[kp1] = u; - in_S[u] = true; - num_edges_on_k = 0; - - if (match(iter, dfs_num_k + 1)) -#if 0 - // dwa 2003/7/11 -- this *HAS* to be a bug! - ; -#endif - return true; + G2_verts = vertices(G2); + while (G2_verts.first != G2_verts.second) { + { + vertex2_t u = *G2_verts.first; + vertex1_t kp1 = dfs_vertices[dfs_num_k + 1]; + if (invariant1(kp1) == invariant2(u) && in_S[u] == false) { + { + f[kp1] = u; + in_S[u] = true; + num_edges_on_k = 0; - in_S[u] = false; + match_continuation new_k; + new_k.position = match_continuation::pos_G2_vertex_loop; + new_k.G2_verts = G2_verts; + new_k.iter = iter; + new_k.dfs_num_k = dfs_num_k; + k.push_back(new_k); + ++dfs_num_k; + goto recur; + } + } } +G2_loop_k: ++G2_verts.first; } } else if (dfs_num[j] > dfs_num_k) { - vertex1_t k = dfs_vertices[dfs_num_k]; - num_edges_on_k -= - count_if(adjacent_vertices(f[k], G2), make_indirect_pmap(in_S)); - - for (int jj = 0; jj < dfs_num_k; ++jj) { - vertex1_t j = dfs_vertices[jj]; - num_edges_on_k -= count(adjacent_vertices(f[j], G2), f[k]); + { + vertex1_t vk = dfs_vertices[dfs_num_k]; + num_edges_on_k -= + count_if(adjacent_vertices(f[vk], G2), make_indirect_pmap(in_S)); + + for (int jj = 0; jj < dfs_num_k; ++jj) { + vertex1_t j = dfs_vertices[jj]; + num_edges_on_k -= count(adjacent_vertices(f[j], G2), f[vk]); + } } if (num_edges_on_k != 0) - return false; - BGL_FORALL_ADJ_T(f[i], v, G2, Graph2) - if (invariant2(v) == invariant1(j) && in_S[v] == false) { - f[j] = v; - in_S[v] = true; - num_edges_on_k = 1; - BOOST_USING_STD_MAX(); - int next_k = max BOOST_PREVENT_MACRO_SUBSTITUTION(dfs_num_k, max BOOST_PREVENT_MACRO_SUBSTITUTION(dfs_num[i], dfs_num[j])); - if (match(boost::next(iter), next_k)) - return true; - in_S[v] = false; + goto return_point_false; + fi_adj = adjacent_vertices(f[i], G2); + while (fi_adj.first != fi_adj.second) { + { + vertex2_t v = *fi_adj.first; + if (invariant2(v) == invariant1(j) && in_S[v] == false) { + f[j] = v; + in_S[v] = true; + num_edges_on_k = 1; + BOOST_USING_STD_MAX(); + int next_k = max BOOST_PREVENT_MACRO_SUBSTITUTION(dfs_num_k, max BOOST_PREVENT_MACRO_SUBSTITUTION(dfs_num[i], dfs_num[j])); + match_continuation new_k; + new_k.position = match_continuation::pos_fi_adj_loop; + new_k.fi_adj = fi_adj; + new_k.iter = iter; + new_k.dfs_num_k = dfs_num_k; + ++iter; + dfs_num_k = next_k; + k.push_back(new_k); + goto recur; + } } - - +fi_adj_loop_k:++fi_adj.first; + } } else { if (container_contains(adjacent_vertices(f[i], G2), f[j])) { ++num_edges_on_k; - if (match(boost::next(iter), dfs_num_k)) - return true; + match_continuation new_k; + new_k.position = match_continuation::pos_dfs_num; + k.push_back(new_k); + ++iter; + goto recur; } } } else - return true; - return false; - } + goto return_point_true; + goto return_point_false; + { + return_point_true: return true; + + return_point_false: + if (k.empty()) return false; + const match_continuation& this_k = k.back(); + switch (this_k.position) { + case match_continuation::pos_G2_vertex_loop: {G2_verts = this_k.G2_verts; iter = this_k.iter; dfs_num_k = this_k.dfs_num_k; k.pop_back(); in_S[*G2_verts.first] = false; i = source(*iter, G1); j = target(*iter, G1); goto G2_loop_k;} + case match_continuation::pos_fi_adj_loop: {fi_adj = this_k.fi_adj; iter = this_k.iter; dfs_num_k = this_k.dfs_num_k; k.pop_back(); in_S[*fi_adj.first] = false; i = source(*iter, G1); j = target(*iter, G1); goto fi_adj_loop_k;} + case match_continuation::pos_dfs_num: {k.pop_back(); goto return_point_false;} + default: { + BOOST_ASSERT(!"Bad position"); +#ifdef UNDER_CE + exit(-1); +#else + abort(); +#endif + } + } + } + } }; @@ -284,21 +351,41 @@ namespace boost { typedef size_type result_type; degree_vertex_invariant(const InDegreeMap& in_degree_map, const Graph& g) - : m_in_degree_map(in_degree_map), m_g(g) { } + : m_in_degree_map(in_degree_map), + m_max_vertex_in_degree(0), + m_max_vertex_out_degree(0), + m_g(g) { + BGL_FORALL_VERTICES_T(v, g, Graph) { + m_max_vertex_in_degree = + (std::max)(m_max_vertex_in_degree, get(m_in_degree_map, v)); + m_max_vertex_out_degree = + (std::max)(m_max_vertex_out_degree, out_degree(v, g)); + } + } size_type operator()(vertex_t v) const { - return (num_vertices(m_g) + 1) * out_degree(v, m_g) + return (m_max_vertex_in_degree + 1) * out_degree(v, m_g) + get(m_in_degree_map, v); } // The largest possible vertex invariant number size_type max BOOST_PREVENT_MACRO_SUBSTITUTION () const { - return num_vertices(m_g) * num_vertices(m_g) + num_vertices(m_g); + return (m_max_vertex_in_degree + 1) * (m_max_vertex_out_degree + 1); } private: InDegreeMap m_in_degree_map; + size_type m_max_vertex_in_degree; + size_type m_max_vertex_out_degree; const Graph& m_g; }; + // Count actual number of vertices, even in filtered graphs. + template + size_t count_vertices(const Graph& g) + { + size_t n = 0; + BGL_FORALL_VERTICES_T(v, g, Graph) {(void)v; ++n;} + return n; + } template >(); - function_requires< EdgeListGraphConcept >(); - function_requires< VertexListGraphConcept >(); - function_requires< BidirectionalGraphConcept >(); + BOOST_CONCEPT_ASSERT(( VertexListGraphConcept )); + BOOST_CONCEPT_ASSERT(( EdgeListGraphConcept )); + BOOST_CONCEPT_ASSERT(( VertexListGraphConcept )); + //BOOST_CONCEPT_ASSERT(( BidirectionalGraphConcept )); typedef typename graph_traits::vertex_descriptor vertex1_t; typedef typename graph_traits::vertex_descriptor vertex2_t; typedef typename graph_traits::vertices_size_type size_type; // Vertex invariant requirement - function_requires< AdaptableUnaryFunctionConcept >(); - function_requires< AdaptableUnaryFunctionConcept >(); + BOOST_CONCEPT_ASSERT(( AdaptableUnaryFunctionConcept )); + BOOST_CONCEPT_ASSERT(( AdaptableUnaryFunctionConcept )); // Property map requirements - function_requires< ReadWritePropertyMapConcept >(); + BOOST_CONCEPT_ASSERT(( ReadWritePropertyMapConcept )); typedef typename property_traits::value_type IsoMappingValue; - BOOST_STATIC_ASSERT((is_same::value)); + BOOST_STATIC_ASSERT((is_convertible::value)); - function_requires< ReadablePropertyMapConcept >(); + BOOST_CONCEPT_ASSERT(( ReadablePropertyMapConcept )); typedef typename property_traits::value_type IndexMap1Value; BOOST_STATIC_ASSERT((is_convertible::value)); - function_requires< ReadablePropertyMapConcept >(); + BOOST_CONCEPT_ASSERT(( ReadablePropertyMapConcept )); typedef typename property_traits::value_type IndexMap2Value; BOOST_STATIC_ASSERT((is_convertible::value)); - if (num_vertices(G1) != num_vertices(G2)) + if (count_vertices(G1) != count_vertices(G2)) return false; - if (num_vertices(G1) == 0 && num_vertices(G2) == 0) + if (count_vertices(G1) == 0 && count_vertices(G2) == 0) return true; detail::isomorphism_algo + struct make_degree_invariant { + const G& g; + const Index& index; + make_degree_invariant(const G& g, const Index& index): g(g), index(index) {} + typedef typename boost::graph_traits::degree_size_type degree_size_type; + typedef shared_array_property_map prop_map_type; + typedef degree_vertex_invariant result_type; + result_type operator()() const { + prop_map_type pm = make_shared_array_property_map(num_vertices(g), degree_size_type(), index); + compute_in_degree(g, pm); + return result_type(pm, g); + } + }; } // namespace detail - - // Named parameter interface - template - bool isomorphism(const Graph1& g1, - const Graph2& g2, - const bgl_named_params& params) - { - typedef typename graph_traits::vertex_descriptor vertex2_t; - typename std::vector::size_type n = num_vertices(g1); - std::vector f(n); - return detail::isomorphism_impl - (g1, g2, - choose_param(get_param(params, vertex_isomorphism_t()), - make_safe_iterator_property_map(f.begin(), f.size(), - choose_const_pmap(get_param(params, vertex_index1), - g1, vertex_index), vertex2_t())), - choose_const_pmap(get_param(params, vertex_index1), g1, vertex_index), - choose_const_pmap(get_param(params, vertex_index2), g2, vertex_index), - params - ); - } - - // All defaults interface - template - bool isomorphism(const Graph1& g1, const Graph2& g2) - { - return isomorphism(g1, g2, - bgl_named_params(0));// bogus named param + namespace graph { + namespace detail { + template + struct isomorphism_impl { + typedef bool result_type; + template + bool operator()(const Graph1& g1, const Graph2& g2, const ArgPack& arg_pack) const { + using namespace boost::graph::keywords; + typedef typename boost::detail::override_const_property_result::type index1_map_type; + typedef typename boost::detail::override_const_property_result::type index2_map_type; + index1_map_type index1_map = boost::detail::override_const_property(arg_pack, _vertex_index1_map, g1, boost::vertex_index); + index2_map_type index2_map = boost::detail::override_const_property(arg_pack, _vertex_index2_map, g2, boost::vertex_index); + typedef typename graph_traits::vertex_descriptor vertex2_t; + typename std::vector::size_type n = (typename std::vector::size_type)num_vertices(g1); + std::vector f(n); + typename boost::parameter::lazy_binding< + ArgPack, + tag::vertex_invariant1, + boost::detail::make_degree_invariant >::type + invariant1 = + arg_pack[_vertex_invariant1 || boost::detail::make_degree_invariant(g1, index1_map)]; + typename boost::parameter::lazy_binding< + ArgPack, + tag::vertex_invariant2, + boost::detail::make_degree_invariant >::type + invariant2 = + arg_pack[_vertex_invariant2 || boost::detail::make_degree_invariant(g2, index2_map)]; + return boost::isomorphism + (g1, g2, + choose_param(arg_pack[_isomorphism_map | boost::param_not_found()], + make_shared_array_property_map(num_vertices(g1), vertex2_t(), index1_map)), + invariant1, + invariant2, + arg_pack[_vertex_max_invariant | (invariant2.max)()], + index1_map, + index2_map); + } + }; + } + BOOST_GRAPH_MAKE_FORWARDING_FUNCTION(isomorphism, 2, 6) } + // Named parameter interface + BOOST_GRAPH_MAKE_OLD_STYLE_PARAMETER_FUNCTION(isomorphism, 2) // Verify that the given mapping iso_map from the vertices of g1 to the // vertices of g2 describes an isomorphism. diff --git a/include/boost/graph/johnson_all_pairs_shortest.hpp b/include/boost/graph/johnson_all_pairs_shortest.hpp index 8aec50059..1e703791d 100644 --- a/include/boost/graph/johnson_all_pairs_shortest.hpp +++ b/include/boost/graph/johnson_all_pairs_shortest.hpp @@ -29,6 +29,7 @@ #include #include #include +#include namespace boost { @@ -44,8 +45,8 @@ namespace boost { { typedef graph_traits Traits1; typedef typename property_traits::value_type DT; - function_requires< BasicMatrixConcept >(); + BOOST_CONCEPT_ASSERT(( BasicMatrixConcept )); typedef typename Traits1::directed_category DirCat; bool is_undirected = is_same::value; @@ -112,7 +113,7 @@ namespace boost { for (boost::tie(e, e_end) = edges(g2); e != e_end; ++e) { typename Traits2::vertex_descriptor a = source(*e, g2), b = target(*e, g2); - put(w_hat, *e, combine(get(w, *e), (get(h, a) - get(h, b)))); + put(w_hat, *e, combine((get(h, a) - get(h, b)), get(w, *e))); } for (boost::tie(u, u_end) = vertices(g2); u != u_end; ++u) { dijkstra_visitor<> dvis; @@ -120,9 +121,7 @@ namespace boost { (g2, *u, pred, d, w_hat, id2, compare, combine, inf, zero,dvis); for (boost::tie(v, v_end) = vertices(g2); v != v_end; ++v) { if (*u != s && *v != s) { - typename Traits1::vertex_descriptor u1, v1; - u1 = verts1[get(id2, *u)]; v1 = verts1[get(id2, *v)]; - D[get(id2, *u)-1][get(id2, *v)-1] = combine(get(d, *v), (get(h, *v) - get(h, *u))); + D[get(id2, *u)-1][get(id2, *v)-1] = combine((get(h, *v) - get(h, *u)), get(d, *v)); } } } diff --git a/include/boost/graph/kamada_kawai_spring_layout.hpp b/include/boost/graph/kamada_kawai_spring_layout.hpp index 0262e1fc2..63355c946 100644 --- a/include/boost/graph/kamada_kawai_spring_layout.hpp +++ b/include/boost/graph/kamada_kawai_spring_layout.hpp @@ -17,6 +17,7 @@ #include #include #include +#include #include #include @@ -216,11 +217,13 @@ namespace boost { weight_type edge_length = detail::graph::compute_edge_length(g, distance, index, edge_or_side_length); + + // std::cerr << "edge_length = " << edge_length << std::endl; // Compute l_{ij} and k_{ij} const weight_type K = spring_constant; - vertex_iterator ui, end = vertices(g).second; - for (ui = vertices(g).first; ui != end; ++ui) { + vertex_iterator ui, end; + for (ui = vertices(g).first, end = vertices(g).second; ui != end; ++ui) { vertex_iterator vi = ui; for (++vi; vi != end; ++vi) { weight_type dij = distance[get(index, *ui)][get(index, *vi)]; @@ -237,7 +240,7 @@ namespace boost { vertex_descriptor p = *vertices(g).first; weight_type delta_p(0); - for (ui = vertices(g).first; ui != end; ++ui) { + for (ui = vertices(g).first, end = vertices(g).second; ui != end; ++ui) { deriv_type deriv = compute_partial_derivatives(*ui); put(partial_derivatives, *ui, deriv); @@ -255,12 +258,25 @@ namespace boost { // update the delta_i values in O(n) time instead of O(n^2) // time. std::vector p_partials(num_vertices(g)); - for (ui = vertices(g).first; ui != end; ++ui) { + for (ui = vertices(g).first, end = vertices(g).second; ui != end; ++ui) { vertex_descriptor i = *ui; p_partials[get(index, i)] = compute_partial_derivative(i, p); } do { + // For debugging, compute the energy value E + double E = 0.; + for (ui = vertices(g).first, end = vertices(g).second; ui != end; ++ui) { + vertex_iterator vi = ui; + for (++vi; vi != end; ++vi) { + double dist = topology.distance(position[*ui], position[*vi]); + weight_type k_ij = spring_strength[get(index,*ui)][get(index,*vi)]; + weight_type l_ij = distance[get(index, *ui)][get(index, *vi)]; + E += .5 * k_ij * (dist - l_ij) * (dist - l_ij); + } + } + // std::cerr << "E = " << E << std::endl; + // Compute the elements of the Jacobian // From // http://www.cs.panam.edu/~rfowler/papers/1994_kumar_fowler_A_Spring_UTPACSTR.pdf @@ -269,7 +285,7 @@ namespace boost { for (std::size_t i = 0; i < Point::dimensions; ++i) for (std::size_t j = 0; j < Point::dimensions; ++j) dE_d_d[i][j] = 0.; - for (ui = vertices(g).first; ui != end; ++ui) { + for (ui = vertices(g).first, end = vertices(g).second; ui != end; ++ui) { vertex_descriptor i = *ui; if (i != p) { point_difference_type diff = topology.difference(position[p], position[i]); @@ -284,6 +300,7 @@ namespace boost { dE_d_d[i][i] += k_mi * (1 + (l_mi * (diff[i] * diff[i] - dist_squared) * inv_dist_cubed)); } else { dE_d_d[i][j] += k_mi * l_mi * diff[i] * diff[j] * inv_dist_cubed; + // dE_d_d[i][j] += k_mi * l_mi * sqrt(hypot(diff[i], diff[j])) * inv_dist_cubed; } } } @@ -292,7 +309,7 @@ namespace boost { deriv_type dE_d = get(partial_derivatives, p); - // Solve dE_d_d * delta = dE_d to get delta + // Solve dE_d_d * delta = -dE_d to get delta point_difference_type delta = -linear_solver::solve(dE_d_d, dE_d); // Move p by delta @@ -307,7 +324,7 @@ namespace boost { // Select new p by updating each partial derivative and delta vertex_descriptor old_p = p; - for (ui = vertices(g).first; ui != end; ++ui) { + for (ui = vertices(g).first, end = vertices(g).second; ui != end; ++ui) { deriv_type old_deriv_p = p_partials[get(index, *ui)]; deriv_type old_p_partial = compute_partial_derivative(*ui, old_p); @@ -458,12 +475,12 @@ namespace boost { * from every vertex to every other vertex, which is computed in the * first stages of the algorithm. This value's type must be a model * of BasicMatrix with value type equal to the value type of the - * weight map. The default is a a vector of vectors. + * weight map. The default is a vector of vectors. * * \param spring_strength (UTIL/OUT) will be used to store the * strength of the spring between every pair of vertices. This * value's type must be a model of BasicMatrix with value type equal - * to the value type of the weight map. The default is a a vector of + * to the value type of the weight map. The default is a vector of * vectors. * * \param partial_derivatives (UTIL) will be used to store the diff --git a/include/boost/graph/king_ordering.hpp b/include/boost/graph/king_ordering.hpp index 9d9a438f3..29e7ac970 100644 --- a/include/boost/graph/king_ordering.hpp +++ b/include/boost/graph/king_ordering.hpp @@ -37,7 +37,6 @@ namespace boost { typename graph_traits::out_edge_iterator ei, ei_end; Vertex v, w; - typedef typename std::deque::iterator iterator; typedef typename std::deque::reverse_iterator reverse_iterator; reverse_iterator rend = Qptr->rend()-index_begin; @@ -86,8 +85,6 @@ namespace boost { //this function replaces pop_heap, and tracks state information template void percolate_down(int offset){ - typedef typename std::deque::reverse_iterator reverse_iterator; - int heap_last = index_begin + offset; int heap_first = Qptr->size() - 1; @@ -267,7 +264,6 @@ namespace boost { return permutation; typedef typename boost::graph_traits::vertex_descriptor Vertex; - typedef typename boost::graph_traits::vertex_iterator VerIter; typedef typename property_traits::value_type ColorValue; typedef color_traits Color; @@ -302,7 +298,6 @@ namespace boost { if (has_no_vertices(G)) return permutation; - typedef out_degree_property_map DegreeMap; std::vector colors(num_vertices(G)); return king_ordering(G, permutation, make_iterator_property_map(&colors[0], index_map, diff --git a/include/boost/graph/kolmogorov_max_flow.hpp b/include/boost/graph/kolmogorov_max_flow.hpp deleted file mode 100644 index c2b94c094..000000000 --- a/include/boost/graph/kolmogorov_max_flow.hpp +++ /dev/null @@ -1,814 +0,0 @@ -// Copyright (c) 2006, Stephan Diederich -// -// This code may be used under either of the following two licences: -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or -// sell copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. OF SUCH DAMAGE. -// -// Or: -// -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#ifndef BOOST_KOLMOGOROV_MAX_FLOW_HPP -#define BOOST_KOLMOGOROV_MAX_FLOW_HPP - -#if defined(_MSC_VER) || defined(__BORLANDC__) || defined(__DMC__) -# pragma message ("The kolmogorov_max_flow.hpp header is deprecated and will be removed in Boost 1.46. Use boykov_kolmogorov_max_flow.hpp instead.") -#elif defined(__GNUC__) || defined(__HP_aCC) || defined(__SUNPRO_CC) || defined(__IBMCPP__) -# warning "The kolmogorov_max_flow.hpp header is deprecated and will be removed in Boost 1.46. Use boykov_kolmogorov_max_flow.hpp instead." -#endif - -#include -#include -#include -#include -#include -#include -#include // for std::min and std::max - -#include -#include -#include -#include -#include -#include -#include - -namespace boost { - namespace detail { - - template - class kolmogorov{ - typedef typename property_traits::value_type tEdgeVal; - typedef graph_traits tGraphTraits; - typedef typename tGraphTraits::vertex_iterator vertex_iterator; - typedef typename tGraphTraits::vertex_descriptor vertex_descriptor; - typedef typename tGraphTraits::edge_descriptor edge_descriptor; - typedef typename tGraphTraits::edge_iterator edge_iterator; - typedef typename tGraphTraits::out_edge_iterator out_edge_iterator; - typedef boost::queue tQueue; //queue of vertices, used in adoption-stage - typedef typename property_traits::value_type tColorValue; - typedef color_traits tColorTraits; - typedef typename property_traits::value_type tDistanceVal; - - public: - kolmogorov(Graph& g, - EdgeCapacityMap cap, - ResidualCapacityEdgeMap res, - ReverseEdgeMap rev, - PredecessorMap pre, - ColorMap color, - DistanceMap dist, - IndexMap idx, - vertex_descriptor src, - vertex_descriptor sink): - m_g(g), - m_index_map(idx), - m_cap_map(cap), - m_res_cap_map(res), - m_rev_edge_map(rev), - m_pre_map(pre), - m_tree_map(color), - m_dist_map(dist), - m_source(src), - m_sink(sink), - m_active_nodes(), - m_in_active_list_vec(num_vertices(g), false), - m_in_active_list_map(make_iterator_property_map(m_in_active_list_vec.begin(), m_index_map)), - m_has_parent_vec(num_vertices(g), false), - m_has_parent_map(make_iterator_property_map(m_has_parent_vec.begin(), m_index_map)), - m_time_vec(num_vertices(g), 0), - m_time_map(make_iterator_property_map(m_time_vec.begin(), m_index_map)), - m_flow(0), - m_time(1), - m_last_grow_vertex(graph_traits::null_vertex()){ - // initialize the color-map with gray-values - vertex_iterator vi, v_end; - for(boost::tie(vi, v_end) = vertices(m_g); vi != v_end; ++vi){ - set_tree(*vi, tColorTraits::gray()); - } - // Initialize flow to zero which means initializing - // the residual capacity equal to the capacity - edge_iterator ei, e_end; - for(boost::tie(ei, e_end) = edges(m_g); ei != e_end; ++ei) { - m_res_cap_map[*ei] = m_cap_map[*ei]; - assert(m_rev_edge_map[m_rev_edge_map[*ei]] == *ei); //check if the reverse edge map is build up properly - } - //init the search trees with the two terminals - set_tree(m_source, tColorTraits::black()); - set_tree(m_sink, tColorTraits::white()); - m_time_map[m_source] = 1; - m_time_map[m_sink] = 1; - } - - ~kolmogorov(){} - - tEdgeVal max_flow(){ - //augment direct paths from SOURCE->SINK and SOURCE->VERTEX->SINK - augment_direct_paths(); - //start the main-loop - while(true){ - bool path_found; - edge_descriptor connecting_edge; - boost::tie(connecting_edge, path_found) = grow(); //find a path from source to sink - if(!path_found){ - //we're finished, no more paths were found - break; - } - ++m_time; - augment(connecting_edge); //augment that path - adopt(); //rebuild search tree structure - } - return m_flow; - } - - //the complete class is protected, as we want access to members in derived test-class (see $(BOOST_ROOT)/libs/graph/test/kolmogorov_max_flow_test.cpp) - protected: - void augment_direct_paths(){ - //in a first step, we augment all direct paths from source->NODE->sink - //and additionally paths from source->sink - //this improves especially graphcuts for segmentation, as most of the nodes have source/sink connects - //but shouldn't have an impact on other maxflow problems (this is done in grow() anyway) - out_edge_iterator ei, e_end; - for(boost::tie(ei, e_end) = out_edges(m_source, m_g); ei != e_end; ++ei){ - edge_descriptor from_source = *ei; - vertex_descriptor current_node = target(from_source, m_g); - if(current_node == m_sink){ - tEdgeVal cap = m_res_cap_map[from_source]; - m_res_cap_map[from_source] = 0; - m_flow += cap; - continue; - } - edge_descriptor to_sink; - bool is_there; - boost::tie(to_sink, is_there) = lookup_edge(current_node, m_sink, m_g); - if(is_there){ - tEdgeVal cap_from_source = m_res_cap_map[from_source]; - tEdgeVal cap_to_sink = m_res_cap_map[to_sink]; - if(cap_from_source > cap_to_sink){ - set_tree(current_node, tColorTraits::black()); - add_active_node(current_node); - set_edge_to_parent(current_node, from_source); - m_dist_map[current_node] = 1; - m_time_map[current_node] = 1; - //add stuff to flow and update residuals - //we dont need to update reverse_edges, as incoming/outgoing edges to/from source/sink don't count for max-flow - m_res_cap_map[from_source] -= cap_to_sink; - m_res_cap_map[to_sink] = 0; - m_flow += cap_to_sink; - } else if(cap_to_sink > 0){ - set_tree(current_node, tColorTraits::white()); - add_active_node(current_node); - set_edge_to_parent(current_node, to_sink); - m_dist_map[current_node] = 1; - m_time_map[current_node] = 1; - //add stuff to flow and update residuals - //we dont need to update reverse_edges, as incoming/outgoing edges to/from source/sink don't count for max-flow - m_res_cap_map[to_sink] -= cap_from_source; - m_res_cap_map[from_source] = 0; - m_flow += cap_from_source; - } - } else if(m_res_cap_map[from_source]){ - //there is no sink connect, so we can't augment this path - //but to avoid adding m_source to the active nodes, we just activate this node and set the approciate things - set_tree(current_node, tColorTraits::black()); - set_edge_to_parent(current_node, from_source); - m_dist_map[current_node] = 1; - m_time_map[current_node] = 1; - add_active_node(current_node); - } - } - for(boost::tie(ei, e_end) = out_edges(m_sink, m_g); ei != e_end; ++ei){ - edge_descriptor to_sink = m_rev_edge_map[*ei]; - vertex_descriptor current_node = source(to_sink, m_g); - if(m_res_cap_map[to_sink]){ - set_tree(current_node, tColorTraits::white()); - set_edge_to_parent(current_node, to_sink); - m_dist_map[current_node] = 1; - m_time_map[current_node] = 1; - add_active_node(current_node); - } - } - } - - /** - * returns a pair of an edge and a boolean. if the bool is true, the edge is a connection of a found path from s->t , read "the link" and - * source(returnVal, m_g) is the end of the path found in the source-tree - * target(returnVal, m_g) is the beginning of the path found in the sink-tree - */ - std::pair grow(){ - assert(m_orphans.empty()); - vertex_descriptor current_node; - while((current_node = get_next_active_node()) != graph_traits::null_vertex()){ //if there is one - assert(get_tree(current_node) != tColorTraits::gray() && (has_parent(current_node) || current_node==m_source || current_node==m_sink)); - if(get_tree(current_node) == tColorTraits::black()){ - //source tree growing - out_edge_iterator ei, e_end; - if(current_node != m_last_grow_vertex){ - m_last_grow_vertex = current_node; - boost::tie(m_last_grow_edge_it, m_last_grow_edge_end) = out_edges(current_node, m_g); - } - for(; m_last_grow_edge_it != m_last_grow_edge_end; ++m_last_grow_edge_it){ - edge_descriptor out_edge = *m_last_grow_edge_it; - if(m_res_cap_map[out_edge] > 0){ //check if we have capacity left on this edge - vertex_descriptor other_node = target(out_edge, m_g); - if(get_tree(other_node) == tColorTraits::gray()){ //it's a free node - set_tree(other_node, tColorTraits::black()); //aquire other node to our search tree - set_edge_to_parent(other_node, out_edge); //set us as parent - m_dist_map[other_node] = m_dist_map[current_node] + 1; //and update the distance-heuristic - m_time_map[other_node] = m_time_map[current_node]; - add_active_node(other_node); - } else if(get_tree(other_node) == tColorTraits::black()){ - if(is_closer_to_terminal(current_node, other_node)){ //we do this to get shorter paths. check if we are nearer to the source as its parent is - set_edge_to_parent(other_node, out_edge); - m_dist_map[other_node] = m_dist_map[current_node] + 1; - m_time_map[other_node] = m_time_map[current_node]; - } - } else{ - assert(get_tree(other_node)==tColorTraits::white()); - //kewl, found a path from one to the other search tree, return the connecting edge in src->sink dir - return std::make_pair(out_edge, true); - } - } - } //for all out-edges - } //source-tree-growing - else{ - assert(get_tree(current_node) == tColorTraits::white()); - out_edge_iterator ei, e_end; - if(current_node != m_last_grow_vertex){ - m_last_grow_vertex = current_node; - boost::tie(m_last_grow_edge_it, m_last_grow_edge_end) = out_edges(current_node, m_g); - } - for(; m_last_grow_edge_it != m_last_grow_edge_end; ++m_last_grow_edge_it){ - edge_descriptor in_edge = m_rev_edge_map[*m_last_grow_edge_it]; - if(m_res_cap_map[in_edge] > 0){ //check if there is capacity left - vertex_descriptor other_node = source(in_edge, m_g); - if(get_tree(other_node) == tColorTraits::gray()){ //it's a free node - set_tree(other_node, tColorTraits::white()); //aquire that node to our search tree - set_edge_to_parent(other_node, in_edge); //set us as parent - add_active_node(other_node); //activate that node - m_dist_map[other_node] = m_dist_map[current_node] + 1; //set its distance - m_time_map[other_node] = m_time_map[current_node]; //and time - } else if(get_tree(other_node) == tColorTraits::white()){ - if(is_closer_to_terminal(current_node, other_node)){ - //we are closer to the sink than its parent is, so we "adopt" him - set_edge_to_parent(other_node, in_edge); - m_dist_map[other_node] = m_dist_map[current_node] + 1; - m_time_map[other_node] = m_time_map[current_node]; - } - } else{ - assert(get_tree(other_node)==tColorTraits::black()); - //kewl, found a path from one to the other search tree, return the connecting edge in src->sink dir - return std::make_pair(in_edge, true); - } - } - } //for all out-edges - } //sink-tree growing - //all edges of that node are processed, and no more paths were found. so remove if from the front of the active queue - finish_node(current_node); - } //while active_nodes not empty - return std::make_pair(edge_descriptor(), false); //no active nodes anymore and no path found, we're done - } - - /** - * augments path from s->t and updates residual graph - * source(e, m_g) is the end of the path found in the source-tree - * target(e, m_g) is the beginning of the path found in the sink-tree - * this phase generates orphans on satured edges, if the attached verts are from different search-trees - * orphans are ordered in distance to sink/source. first the farest from the source are front_inserted into the orphans list, - * and after that the sink-tree-orphans are front_inserted. when going to adoption stage the orphans are popped_front, and so we process the nearest - * verts to the terminals first - */ - void augment(edge_descriptor e){ - assert(get_tree(target(e, m_g)) == tColorTraits::white()); - assert(get_tree(source(e, m_g)) == tColorTraits::black()); - assert(m_orphans.empty()); - - const tEdgeVal bottleneck = find_bottleneck(e); - //now we push the found flow through the path - //for each edge we saturate we have to look for the verts that belong to that edge, one of them becomes an orphans - //now process the connecting edge - m_res_cap_map[e] -= bottleneck; - assert(m_res_cap_map[e] >= 0); - m_res_cap_map[m_rev_edge_map[e]] += bottleneck; - - //now we follow the path back to the source - vertex_descriptor current_node = source(e, m_g); - while(current_node != m_source){ - edge_descriptor pred = get_edge_to_parent(current_node); - m_res_cap_map[pred] -= bottleneck; - assert(m_res_cap_map[pred] >= 0); - m_res_cap_map[m_rev_edge_map[pred]] += bottleneck; - if(m_res_cap_map[pred] == 0){ - set_no_parent(current_node); - m_orphans.push_front(current_node); - } - current_node = source(pred, m_g); - } - //then go forward in the sink-tree - current_node = target(e, m_g); - while(current_node != m_sink){ - edge_descriptor pred = get_edge_to_parent(current_node); - m_res_cap_map[pred] -= bottleneck; - assert(m_res_cap_map[pred] >= 0); - m_res_cap_map[m_rev_edge_map[pred]] += bottleneck; - if(m_res_cap_map[pred] == 0){ - set_no_parent(current_node); - m_orphans.push_front(current_node); - } - current_node = target(pred, m_g); - } - //and add it to the max-flow - m_flow += bottleneck; - } - - /** - * returns the bottleneck of a s->t path (end_of_path is last vertex in source-tree, begin_of_path is first vertex in sink-tree) - */ - inline tEdgeVal find_bottleneck(edge_descriptor e){ - BOOST_USING_STD_MIN(); - tEdgeVal minimum_cap = m_res_cap_map[e]; - vertex_descriptor current_node = source(e, m_g); - //first go back in the source tree - while(current_node != m_source){ - edge_descriptor pred = get_edge_to_parent(current_node); - minimum_cap = min BOOST_PREVENT_MACRO_SUBSTITUTION(minimum_cap, m_res_cap_map[pred]); - current_node = source(pred, m_g); - } - //then go forward in the sink-tree - current_node = target(e, m_g); - while(current_node != m_sink){ - edge_descriptor pred = get_edge_to_parent(current_node); - minimum_cap = min BOOST_PREVENT_MACRO_SUBSTITUTION(minimum_cap, m_res_cap_map[pred]); - current_node = target(pred, m_g); - } - return minimum_cap; - } - - /** - * rebuild search trees - * empty the queue of orphans, and find new parents for them or just drop them from the search trees - */ - void adopt(){ - while(!m_orphans.empty() || !m_child_orphans.empty()){ - vertex_descriptor current_node; - if(m_child_orphans.empty()){ - //get the next orphan from the main-queue and remove it - current_node = m_orphans.front(); - m_orphans.pop_front(); - } else{ - current_node = m_child_orphans.front(); - m_child_orphans.pop(); - } - if(get_tree(current_node) == tColorTraits::black()){ - //we're in the source-tree - tDistanceVal min_distance = (std::numeric_limits::max)(); - edge_descriptor new_parent_edge; - out_edge_iterator ei, e_end; - for(boost::tie(ei, e_end) = out_edges(current_node, m_g); ei != e_end; ++ei){ - const edge_descriptor in_edge = m_rev_edge_map[*ei]; - assert(target(in_edge, m_g) == current_node); //we should be the target of this edge - if(m_res_cap_map[in_edge] > 0){ - vertex_descriptor other_node = source(in_edge, m_g); - if(get_tree(other_node) == tColorTraits::black() && has_source_connect(other_node)){ - if(m_dist_map[other_node] < min_distance){ - min_distance = m_dist_map[other_node]; - new_parent_edge = in_edge; - } - } - } - } - if(min_distance != (std::numeric_limits::max)()){ - set_edge_to_parent(current_node, new_parent_edge); - m_dist_map[current_node] = min_distance + 1; - m_time_map[current_node] = m_time; - } else{ - m_time_map[current_node] = 0; - for(boost::tie(ei, e_end) = out_edges(current_node, m_g); ei != e_end; ++ei){ - edge_descriptor in_edge = m_rev_edge_map[*ei]; - vertex_descriptor other_node = source(in_edge, m_g); - if(get_tree(other_node) == tColorTraits::black() && has_parent(other_node)){ - if(m_res_cap_map[in_edge] > 0){ - add_active_node(other_node); - } - if(source(get_edge_to_parent(other_node), m_g) == current_node){ - //we are the parent of that node - //it has to find a new parent, too - set_no_parent(other_node); - m_child_orphans.push(other_node); - } - } - } - set_tree(current_node, tColorTraits::gray()); - } //no parent found - } //source-tree-adoption - else{ - //now we should be in the sink-tree, check that... - assert(get_tree(current_node) == tColorTraits::white()); - out_edge_iterator ei, e_end; - edge_descriptor new_parent_edge; - tDistanceVal min_distance = (std::numeric_limits::max)(); - for(boost::tie(ei, e_end) = out_edges(current_node, m_g); ei != e_end; ++ei){ - const edge_descriptor out_edge = *ei; - if(m_res_cap_map[out_edge] > 0){ - const vertex_descriptor other_node = target(out_edge, m_g); - if(get_tree(other_node) == tColorTraits::white() && has_sink_connect(other_node)) - if(m_dist_map[other_node] < min_distance){ - min_distance = m_dist_map[other_node]; - new_parent_edge = out_edge; - } - } - } - if(min_distance != (std::numeric_limits::max)()){ - set_edge_to_parent(current_node, new_parent_edge); - m_dist_map[current_node] = min_distance + 1; - m_time_map[current_node] = m_time; - } else{ - m_time_map[current_node] = 0; - for(boost::tie(ei, e_end) = out_edges(current_node, m_g); ei != e_end; ++ei){ - const edge_descriptor out_edge = *ei; - const vertex_descriptor other_node = target(out_edge, m_g); - if(get_tree(other_node) == tColorTraits::white() && has_parent(other_node)){ - if(m_res_cap_map[out_edge] > 0){ - add_active_node(other_node); - } - if(target(get_edge_to_parent(other_node), m_g) == current_node){ - //we were it's parent, so it has to find a new one, too - set_no_parent(other_node); - m_child_orphans.push(other_node); - } - } - } - set_tree(current_node, tColorTraits::gray()); - } //no parent found - } //sink-tree adoption - } //while !orphans.empty() - } //adopt - - /** - * return next active vertex if there is one, otherwise a null_vertex - */ - inline vertex_descriptor get_next_active_node(){ - while(true){ - if(m_active_nodes.empty()) - return graph_traits::null_vertex(); - vertex_descriptor v = m_active_nodes.front(); - - if(!has_parent(v) && v != m_source && v != m_sink){ //if it has no parent, this node can't be active(if its not source or sink) - m_active_nodes.pop(); - m_in_active_list_map[v] = false; - } else{ - assert(get_tree(v) == tColorTraits::black() || get_tree(v) == tColorTraits::white()); - return v; - } - } - } - - /** - * adds v as an active vertex, but only if its not in the list already - */ - inline void add_active_node(vertex_descriptor v){ - assert(get_tree(v) != tColorTraits::gray()); - if(m_in_active_list_map[v]){ - return; - } else{ - m_in_active_list_map[v] = true; - m_active_nodes.push(v); - } - } - - /** - * finish_node removes a node from the front of the active queue (its called in grow phase, if no more paths can be found using this node) - */ - inline void finish_node(vertex_descriptor v){ - assert(m_active_nodes.front() == v); - m_active_nodes.pop(); - m_in_active_list_map[v] = false; - m_last_grow_vertex = graph_traits::null_vertex(); - } - - /** - * removes a vertex from the queue of active nodes (actually this does nothing, - * but checks if this node has no parent edge, as this is the criteria for beeing no more active) - */ - inline void remove_active_node(vertex_descriptor v){ - assert(!has_parent(v)); - } - - /** - * returns the search tree of v; tColorValue::black() for source tree, white() for sink tree, gray() for no tree - */ - inline tColorValue get_tree(vertex_descriptor v) const { - return m_tree_map[v]; - } - - /** - * sets search tree of v; tColorValue::black() for source tree, white() for sink tree, gray() for no tree - */ - inline void set_tree(vertex_descriptor v, tColorValue t){ - m_tree_map[v] = t; - } - - /** - * returns edge to parent vertex of v; - */ - inline edge_descriptor get_edge_to_parent(vertex_descriptor v) const{ - return m_pre_map[v]; - } - - /** - * returns true if the edge stored in m_pre_map[v] is a valid entry - */ - inline bool has_parent(vertex_descriptor v) const{ - return m_has_parent_map[v]; - } - - /** - * sets edge to parent vertex of v; - */ - inline void set_edge_to_parent(vertex_descriptor v, edge_descriptor f_edge_to_parent){ - assert(m_res_cap_map[f_edge_to_parent] > 0); - m_pre_map[v] = f_edge_to_parent; - m_has_parent_map[v] = true; - } - - /** - * removes the edge to parent of v (this is done by invalidating the entry an additional map) - */ - inline void set_no_parent(vertex_descriptor v){ - m_has_parent_map[v] = false; - } - - /** - * checks if vertex v has a connect to the sink-vertex (@var m_sink) - * @param v the vertex which is checked - * @return true if a path to the sink was found, false if not - */ - inline bool has_sink_connect(vertex_descriptor v){ - tDistanceVal current_distance = 0; - vertex_descriptor current_vertex = v; - while(true){ - if(m_time_map[current_vertex] == m_time){ - //we found a node which was already checked this round. use it for distance calculations - current_distance += m_dist_map[current_vertex]; - break; - } - if(current_vertex == m_sink){ - m_time_map[m_sink] = m_time; - break; - } - if(has_parent(current_vertex)){ - //it has a parent, so get it - current_vertex = target(get_edge_to_parent(current_vertex), m_g); - ++current_distance; - } else{ - //no path found - return false; - } - } - current_vertex=v; - while(m_time_map[current_vertex] != m_time){ - m_dist_map[current_vertex] = current_distance--; - m_time_map[current_vertex] = m_time; - current_vertex = target(get_edge_to_parent(current_vertex), m_g); - } - return true; - } - - /** - * checks if vertex v has a connect to the source-vertex (@var m_source) - * @param v the vertex which is checked - * @return true if a path to the source was found, false if not - */ - inline bool has_source_connect(vertex_descriptor v){ - tDistanceVal current_distance = 0; - vertex_descriptor current_vertex = v; - while(true){ - if(m_time_map[current_vertex] == m_time){ - //we found a node which was already checked this round. use it for distance calculations - current_distance += m_dist_map[current_vertex]; - break; - } - if(current_vertex == m_source){ - m_time_map[m_source] = m_time; - break; - } - if(has_parent(current_vertex)){ - //it has a parent, so get it - current_vertex = source(get_edge_to_parent(current_vertex), m_g); - ++current_distance; - } else{ - //no path found - return false; - } - } - current_vertex=v; - while(m_time_map[current_vertex] != m_time){ - m_dist_map[current_vertex] = current_distance-- ; - m_time_map[current_vertex] = m_time; - current_vertex = source(get_edge_to_parent(current_vertex), m_g); - } - return true; - } - - /** - * returns true, if p is closer to a terminal than q - */ - inline bool is_closer_to_terminal(vertex_descriptor p, vertex_descriptor q){ - //checks the timestamps first, to build no cycles, and after that the real distance - return (m_time_map[q] <= m_time_map[p] && m_dist_map[q] > m_dist_map[p]+1); - } - - //////// - // member vars - //////// - Graph& m_g; - IndexMap m_index_map; - EdgeCapacityMap m_cap_map; - ResidualCapacityEdgeMap m_res_cap_map; - ReverseEdgeMap m_rev_edge_map; - PredecessorMap m_pre_map; //stores paths found in the growth stage - ColorMap m_tree_map; //maps each vertex into one of the two search tree or none (gray()) - DistanceMap m_dist_map; //stores distance to source/sink nodes - vertex_descriptor m_source; - vertex_descriptor m_sink; - - tQueue m_active_nodes; - std::vector m_in_active_list_vec; - iterator_property_map::iterator, IndexMap> m_in_active_list_map; - - std::list m_orphans; - tQueue m_child_orphans; // we use a second queuqe for child orphans, as they are FIFO processed - - std::vector m_has_parent_vec; - iterator_property_map::iterator, IndexMap> m_has_parent_map; - - std::vector m_time_vec; //timestamp of each node, used for sink/source-path calculations - iterator_property_map::iterator, IndexMap> m_time_map; - tEdgeVal m_flow; - long m_time; - vertex_descriptor m_last_grow_vertex; - out_edge_iterator m_last_grow_edge_it; - out_edge_iterator m_last_grow_edge_end; - }; - } //namespace detail - - /** - * non-named-parameter version, given everything - * this is the catch all version - */ - template - typename property_traits::value_type - kolmogorov_max_flow - (Graph& g, - CapacityEdgeMap cap, - ResidualCapacityEdgeMap res_cap, - ReverseEdgeMap rev_map, - PredecessorMap pre_map, - ColorMap color, - DistanceMap dist, - IndexMap idx, - typename graph_traits::vertex_descriptor src, - typename graph_traits::vertex_descriptor sink - ) - { - typedef typename graph_traits::vertex_descriptor vertex_descriptor; - typedef typename graph_traits::edge_descriptor edge_descriptor; - //as this method is the last one before we instantiate the solver, we do the concept checks here - function_requires >(); //to have vertices(), num_vertices(), - function_requires >(); //to have edges() - function_requires >(); //to have source(), target() and out_edges() - function_requires >(); //read flow-values from edges - function_requires >(); //write flow-values to residuals - function_requires >(); //read out reverse edges - function_requires >(); //store predecessor there - function_requires >(); //write corresponding tree - function_requires >(); //write distance to source/sink - function_requires >(); //get index 0...|V|-1 - assert(num_vertices(g) >= 2 && src != sink); - detail::kolmogorov - algo(g, cap, res_cap, rev_map, pre_map, color, dist, idx, src, sink); - return algo.max_flow(); - } - - /** - * non-named-parameter version, given: capacity, residucal_capacity, reverse_edges, and an index map. - */ - template - typename property_traits::value_type - kolmogorov_max_flow - (Graph& g, - CapacityEdgeMap cap, - ResidualCapacityEdgeMap res_cap, - ReverseEdgeMap rev, - IndexMap idx, - typename graph_traits::vertex_descriptor src, - typename graph_traits::vertex_descriptor sink) - { - typename graph_traits::vertices_size_type n_verts = num_vertices(g); - std::vector::edge_descriptor> predecessor_vec(n_verts); - std::vector color_vec(n_verts); - std::vector::vertices_size_type> distance_vec(n_verts); - return kolmogorov_max_flow - (g, cap, res_cap, rev, - make_iterator_property_map(predecessor_vec.begin(), idx), - make_iterator_property_map(color_vec.begin(), idx), - make_iterator_property_map(distance_vec.begin(), idx), - idx, src, sink); - } - - /** - * non-named-parameter version, some given: capacity, residual_capacity, reverse_edges, color_map and an index map. - * Use this if you are interested in the minimum cut, as the color map provides that info - */ - template - typename property_traits::value_type - kolmogorov_max_flow - (Graph& g, - CapacityEdgeMap cap, - ResidualCapacityEdgeMap res_cap, - ReverseEdgeMap rev, - ColorMap color, - IndexMap idx, - typename graph_traits::vertex_descriptor src, - typename graph_traits::vertex_descriptor sink) - { - typename graph_traits::vertices_size_type n_verts = num_vertices(g); - std::vector::edge_descriptor> predecessor_vec(n_verts); - std::vector::vertices_size_type> distance_vec(n_verts); - - return kolmogorov_max_flow - (g, cap, res_cap, rev, - make_iterator_property_map(predecessor_vec.begin(), idx), - color, - make_iterator_property_map(distance_vec.begin(), idx), - idx, src, sink); - } - - /** - * named-parameter version, some given - */ - template - typename property_traits::const_type>::value_type - kolmogorov_max_flow - (Graph& g, - typename graph_traits::vertex_descriptor src, - typename graph_traits::vertex_descriptor sink, - const bgl_named_params& params) - { - return kolmogorov_max_flow(g, - choose_const_pmap(get_param(params, edge_capacity), g, edge_capacity), - choose_pmap(get_param(params, edge_residual_capacity), g, edge_residual_capacity), - choose_const_pmap(get_param(params, edge_reverse), g, edge_reverse), - choose_pmap(get_param(params, vertex_predecessor), g, vertex_predecessor), - choose_pmap(get_param(params, vertex_color), g, vertex_color), - choose_pmap(get_param(params, vertex_distance), g, vertex_distance), - choose_const_pmap(get_param(params, vertex_index), g, vertex_index), - src, sink); - } - - /** - * named-parameter version, none given - */ - template - typename property_traits::const_type>::value_type - kolmogorov_max_flow - (Graph& g, - typename graph_traits::vertex_descriptor src, - typename graph_traits::vertex_descriptor sink) - { - bgl_named_params params(0); // bogus empty param - return kolmogorov_max_flow(g, src, sink, params); - } -} // namespace boost - -#endif // BOOST_KOLMOGOROV_MAX_FLOW_HPP - diff --git a/include/boost/graph/kruskal_min_spanning_tree.hpp b/include/boost/graph/kruskal_min_spanning_tree.hpp index a847e3f15..b7e815770 100644 --- a/include/boost/graph/kruskal_min_spanning_tree.hpp +++ b/include/boost/graph/kruskal_min_spanning_tree.hpp @@ -28,6 +28,7 @@ #include #include #include +#include namespace boost { @@ -51,18 +52,18 @@ namespace boost { if (num_vertices(G) == 0) return; // Nothing to do in this case typedef typename graph_traits::vertex_descriptor Vertex; typedef typename graph_traits::edge_descriptor Edge; - function_requires >(); - function_requires >(); - function_requires >(); - function_requires >(); - function_requires >(); - function_requires >(); + BOOST_CONCEPT_ASSERT(( VertexListGraphConcept )); + BOOST_CONCEPT_ASSERT(( EdgeListGraphConcept )); + BOOST_CONCEPT_ASSERT(( OutputIteratorConcept )); + BOOST_CONCEPT_ASSERT(( ReadWritePropertyMapConcept )); + BOOST_CONCEPT_ASSERT(( ReadWritePropertyMapConcept )); + BOOST_CONCEPT_ASSERT(( ReadablePropertyMapConcept )); typedef typename property_traits::value_type W_value; typedef typename property_traits::value_type R_value; typedef typename property_traits::value_type P_value; - function_requires >(); - function_requires >(); - function_requires >(); + BOOST_CONCEPT_ASSERT(( ComparableConcept )); + BOOST_CONCEPT_ASSERT(( ConvertibleConcept )); + BOOST_CONCEPT_ASSERT(( IntegerConcept )); disjoint_sets dset(rank, parent); @@ -101,7 +102,6 @@ namespace boost { { typedef typename graph_traits::vertices_size_type size_type; typedef typename graph_traits::vertex_descriptor vertex_t; - typedef typename property_map::type index_map_t; if (num_vertices(g) == 0) return; // Nothing to do in this case typename graph_traits::vertices_size_type n = num_vertices(g); diff --git a/include/boost/graph/labeled_graph.hpp b/include/boost/graph/labeled_graph.hpp index e1a2f7c2d..5b688b02e 100644 --- a/include/boost/graph/labeled_graph.hpp +++ b/include/boost/graph/labeled_graph.hpp @@ -21,7 +21,7 @@ #include // This file implements a utility for creating mappings from arbitrary -// identifers to the vertices of a graph. +// identifiers to the vertices of a graph. namespace boost { @@ -104,7 +104,7 @@ namespace graph_detail { // Tag dispatch on random access containers (i.e., vectors). This function // basically requires a) that Container is vector