Ticket #6780: max_adj_search_v9.patch
File max_adj_search_v9.patch, 51.3 KB (added by , 10 years ago) |
---|
-
boost/graph/maximum_adjacency_search.hpp
1 // 2 //======================================================================= 3 // Copyright 2012 Fernando Vilas 4 // 2010 Daniel Trebbien 5 // 6 // Distributed under the Boost Software License, Version 1.0. (See 7 // accompanying file LICENSE_1_0.txt or copy at 8 // http://www.boost.org/LICENSE_1_0.txt) 9 //======================================================================= 10 // 11 12 // The maximum adjacency search algorithm was originally part of the 13 // Stoer-Wagner min cut implementation by Daniel Trebbien. It has been 14 // broken out into its own file to be a public search algorithm, with 15 // visitor concepts. 16 #ifndef BOOST_GRAPH_MAXIMUM_ADJACENCY_SEARCH_H 17 #define BOOST_GRAPH_MAXIMUM_ADJACENCY_SEARCH_H 18 19 /** 20 * This is an implementation of the maximum adjacency search on an 21 * undirected graph. It allows a visitor object to perform some 22 * operation on each vertex as that vertex is visited. 23 * 24 * The algorithm runs as follows: 25 * 26 * Initialize all nodes to be unvisited (reach count = 0) 27 * and call vis.initialize_vertex 28 * For i = number of nodes in graph downto 1 29 * Select the unvisited node with the highest reach count 30 * The user provides the starting node to break the first tie, 31 * but future ties are broken arbitrarily 32 * Visit the node by calling vis.start_vertex 33 * Increment the reach count for all unvisited neighbors 34 * and call vis.examine_edge for each of these edges 35 * Mark the node as visited and call vis.finish_vertex 36 * 37 */ 38 39 #include <boost/concept_check.hpp> 40 #include <boost/concept/assert.hpp> 41 #include <boost/graph/buffer_concepts.hpp> 42 #include <boost/graph/exception.hpp> 43 #include <boost/graph/graph_concepts.hpp> 44 #include <boost/graph/iteration_macros.hpp> 45 #include <boost/graph/named_function_params.hpp> 46 #include <boost/graph/visitors.hpp> 47 #include <boost/tuple/tuple.hpp> 48 49 #include <set> 50 51 namespace boost { 52 template <class Visitor, class Graph> 53 struct MASVisitorConcept { 54 void constraints() { 55 boost::function_requires< boost::CopyConstructibleConcept<Visitor> >(); 56 vis.initialize_vertex(u, g); 57 vis.start_vertex(u, g); 58 vis.examine_edge(e, g); 59 vis.finish_vertex(u, g); 60 } 61 Visitor vis; 62 Graph g; 63 typename boost::graph_traits<Graph>::vertex_descriptor u; 64 typename boost::graph_traits<Graph>::edge_descriptor e; 65 }; 66 67 template <class Visitors = null_visitor> 68 class mas_visitor { 69 public: 70 mas_visitor() { } 71 mas_visitor(Visitors vis) : m_vis(vis) { } 72 73 template <class Vertex, class Graph> 74 void 75 initialize_vertex(Vertex u, Graph& g) 76 { 77 invoke_visitors(m_vis, u, g, ::boost::on_initialize_vertex()); 78 } 79 80 template <class Vertex, class Graph> 81 void 82 start_vertex(Vertex u, Graph& g) 83 { 84 invoke_visitors(m_vis, u, g, ::boost::on_start_vertex()); 85 } 86 87 template <class Edge, class Graph> 88 void 89 examine_edge(Edge e, Graph& g) 90 { 91 invoke_visitors(m_vis, e, g, ::boost::on_examine_edge()); 92 } 93 94 template <class Vertex, class Graph> 95 void 96 finish_vertex(Vertex u, Graph& g) 97 { 98 invoke_visitors(m_vis, u, g, ::boost::on_finish_vertex()); 99 } 100 101 BOOST_GRAPH_EVENT_STUB(on_initialize_vertex,mas) 102 BOOST_GRAPH_EVENT_STUB(on_start_vertex,mas) 103 BOOST_GRAPH_EVENT_STUB(on_examine_edge,mas) 104 BOOST_GRAPH_EVENT_STUB(on_finish_vertex,mas) 105 106 protected: 107 Visitors m_vis; 108 }; 109 template <class Visitors> 110 mas_visitor<Visitors> 111 make_mas_visitor(Visitors vis) { 112 return mas_visitor<Visitors>(vis); 113 } 114 typedef mas_visitor<> default_mas_visitor; 115 116 namespace detail { 117 template <class Graph, class WeightMap, class MASVisitor, class VertexAssignmentMap, class KeyedUpdatablePriorityQueue> 118 void 119 maximum_adjacency_search(const Graph& g, WeightMap weights, MASVisitor vis, const typename boost::graph_traits<Graph>::vertex_descriptor start, VertexAssignmentMap assignments, KeyedUpdatablePriorityQueue pq) { 120 typedef typename boost::graph_traits<Graph>::vertex_descriptor vertex_descriptor; 121 typedef typename boost::graph_traits<Graph>::vertices_size_type vertices_size_type; 122 typedef typename boost::graph_traits<Graph>::edge_descriptor edge_descriptor; 123 typedef typename boost::property_traits<WeightMap>::value_type weight_type; 124 125 std::set<vertex_descriptor> assignedVertices; 126 127 // initialize `assignments` (all vertices are initially 128 // assigned to themselves) 129 BGL_FORALL_VERTICES_T(v, g, Graph) { 130 put(assignments, v, v); 131 } 132 133 typename KeyedUpdatablePriorityQueue::key_map keys = pq.keys(); 134 135 // set number of visited neighbors for all vertices to 0 136 BGL_FORALL_VERTICES_T(v, g, Graph) { 137 if (v == get(assignments, v)) { // foreach u \in V do 138 put(keys, v, weight_type(0)); vis.initialize_vertex(v, g); 139 140 pq.push(v); 141 } 142 } 143 BOOST_ASSERT(pq.size() >= 2); 144 145 // Give the starting vertex high priority 146 put(keys, start, get(keys, start) + num_vertices(g) + 1); 147 pq.update(start); 148 149 // start traversing the graph 150 //vertex_descriptor s, t; 151 weight_type w; 152 while (!pq.empty()) { // while PQ \neq {} do 153 const vertex_descriptor u = pq.top(); // u = extractmax(PQ) 154 w = get(keys, u); vis.start_vertex(u, g); 155 pq.pop(); // vis.start_vertex(u, g); 156 157 BGL_FORALL_OUTEDGES_T(u, e, g, Graph) { // foreach (u, v) \in E do 158 vis.examine_edge(e, g); 159 160 const vertex_descriptor v = get(assignments, target(e, g)); 161 162 if (pq.contains(v)) { // if v \in PQ then 163 put(keys, v, get(keys, v) + get(weights, e)); // increasekey(PQ, v, wA(v) + w(u, v)) 164 pq.update(v); 165 } 166 } 167 168 typename std::set<vertex_descriptor>::const_iterator assignedVertexIt, assignedVertexEnd = assignedVertices.end(); 169 for (assignedVertexIt = assignedVertices.begin(); assignedVertexIt != assignedVertexEnd; ++assignedVertexIt) { 170 const vertex_descriptor uPrime = *assignedVertexIt; 171 172 if (get(assignments, uPrime) == u) { 173 BGL_FORALL_OUTEDGES_T(uPrime, e, g, Graph) { // foreach (u, v) \in E do 174 vis.examine_edge(e, g); 175 176 const vertex_descriptor v = get(assignments, target(e, g)); 177 178 if (pq.contains(v)) { // if v \in PQ then 179 put(keys, v, get(keys, v) + get(weights, e)); // increasekey(PQ, v, wA(v) + w(u, v)) 180 pq.update(v); 181 } 182 } 183 } 184 } 185 vis.finish_vertex(u, g); 186 } 187 } 188 } // end namespace detail 189 190 template <class Graph, class WeightMap, class MASVisitor, class VertexAssignmentMap, class KeyedUpdatablePriorityQueue> 191 void 192 maximum_adjacency_search(const Graph& g, WeightMap weights, MASVisitor vis, const typename boost::graph_traits<Graph>::vertex_descriptor start, VertexAssignmentMap assignments, KeyedUpdatablePriorityQueue pq) { 193 BOOST_CONCEPT_ASSERT((boost::IncidenceGraphConcept<Graph>)); 194 BOOST_CONCEPT_ASSERT((boost::VertexListGraphConcept<Graph>)); 195 typedef typename boost::graph_traits<Graph>::vertex_descriptor vertex_descriptor; 196 typedef typename boost::graph_traits<Graph>::vertices_size_type vertices_size_type; 197 typedef typename boost::graph_traits<Graph>::edge_descriptor edge_descriptor; 198 BOOST_CONCEPT_ASSERT((boost::Convertible<typename boost::graph_traits<Graph>::directed_category, boost::undirected_tag>)); 199 BOOST_CONCEPT_ASSERT((boost::ReadablePropertyMapConcept<WeightMap, edge_descriptor>)); 200 typedef typename boost::property_traits<WeightMap>::value_type weight_type; 201 boost::function_requires< MASVisitorConcept<MASVisitor, Graph> >(); 202 BOOST_CONCEPT_ASSERT((boost::ReadWritePropertyMapConcept<VertexAssignmentMap, vertex_descriptor>)); 203 BOOST_CONCEPT_ASSERT((boost::Convertible<vertex_descriptor, typename boost::property_traits<VertexAssignmentMap>::value_type>)); 204 BOOST_CONCEPT_ASSERT((boost::KeyedUpdatableQueueConcept<KeyedUpdatablePriorityQueue>)); 205 206 vertices_size_type n = num_vertices(g); 207 if (n < 2) 208 throw boost::bad_graph("the input graph must have at least two vertices."); 209 else if (!pq.empty()) 210 throw std::invalid_argument("the max-priority queue must be empty initially."); 211 212 detail::maximum_adjacency_search(g, weights, 213 vis, start, 214 assignments, pq); 215 } 216 217 namespace graph { 218 namespace detail { 219 template <typename WeightMap> 220 struct mas_dispatch { 221 typedef void result_type; 222 template <typename Graph, typename ArgPack> 223 static result_type apply(const Graph& g, 224 //const bgl_named_params<P,T,R>& params, 225 const ArgPack& params, 226 WeightMap w) { 227 228 using namespace boost::graph::keywords; 229 typedef typename boost::graph_traits<Graph>::vertex_descriptor vertex_descriptor; 230 typedef typename WeightMap::value_type weight_type; 231 232 typedef boost::detail::make_priority_queue_from_arg_pack_gen<boost::graph::keywords::tag::max_priority_queue, weight_type, vertex_descriptor, std::greater<weight_type> > default_pq_gen_type; 233 234 default_pq_gen_type pq_gen(choose_param(get_param(params, boost::distance_zero_t()), weight_type(0))); 235 236 typename boost::result_of<default_pq_gen_type(const Graph&, const ArgPack&)>::type pq = pq_gen(g, params); 237 238 boost::maximum_adjacency_search 239 (g, 240 w, 241 params [ _visitor | make_mas_visitor(null_visitor())], 242 params [ _root_vertex | *vertices(g).first], 243 params [ _vertex_assignment_map | boost::detail::make_property_map_from_arg_pack_gen<boost::graph::keywords::tag::vertex_assignment_map, vertex_descriptor>(vertex_descriptor())(g, params)], 244 pq 245 ); 246 } 247 }; 248 249 template <> 250 struct mas_dispatch<boost::param_not_found> { 251 typedef void result_type; 252 253 template <typename Graph, typename ArgPack> 254 static result_type apply(const Graph& g, 255 const ArgPack& params, 256 param_not_found) { 257 258 using namespace boost::graph::keywords; 259 typedef typename boost::graph_traits<Graph>::vertex_descriptor vertex_descriptor; 260 261 // get edge_weight_t as the weight type 262 typedef typename boost::property_map<Graph, edge_weight_t> WeightMap; 263 typedef typename WeightMap::value_type weight_type; 264 265 typedef boost::detail::make_priority_queue_from_arg_pack_gen<boost::graph::keywords::tag::max_priority_queue, weight_type, vertex_descriptor, std::greater<weight_type> > default_pq_gen_type; 266 267 default_pq_gen_type pq_gen(choose_param(get_param(params, boost::distance_zero_t()), weight_type(0))); 268 269 typename boost::result_of<default_pq_gen_type(const Graph&, const ArgPack&)>::type pq = pq_gen(g, params); 270 271 boost::maximum_adjacency_search 272 (g, 273 get(edge_weight, g), 274 params [ _visitor | make_mas_visitor(null_visitor())], 275 params [ _root_vertex | *vertices(g).first], 276 params [ _vertex_assignment_map | boost::detail::make_property_map_from_arg_pack_gen<boost::graph::keywords::tag::vertex_assignment_map, vertex_descriptor>(vertex_descriptor())(g, params)], 277 pq 278 ); 279 } 280 }; 281 } // end namespace detail 282 } // end namespace graph 283 284 // Named parameter interface 285 //BOOST_GRAPH_MAKE_OLD_STYLE_PARAMETER_FUNCTION(maximum_adjacency_search, 1) 286 template <typename Graph, typename P, typename T, typename R> 287 void 288 maximum_adjacency_search (const Graph& g, 289 const bgl_named_params<P,T,R>& params) { 290 291 typedef bgl_named_params<P, T, R> params_type; 292 BOOST_GRAPH_DECLARE_CONVERTED_PARAMETERS(params_type, params) 293 294 // do the dispatch based on WeightMap 295 typedef typename get_param_type<edge_weight_t, bgl_named_params<P,T,R> >::type W; 296 graph::detail::mas_dispatch<W>::apply(g, arg_pack, get_param(params, edge_weight)); 297 } 298 299 namespace graph { 300 namespace detail { 301 template <typename Graph> 302 struct maximum_adjacency_search_impl { 303 typedef void result_type; 304 305 template <typename ArgPack> 306 void 307 operator() (const Graph& g, const ArgPack arg_pack) const { 308 // call the function that does the dispatching 309 typedef typename get_param_type<edge_weight_t, ArgPack >::type W; 310 graph::detail::mas_dispatch<W>::apply(g, arg_pack, get_param(arg_pack, edge_weight)); 311 } 312 }; 313 } // end namespace detail 314 BOOST_GRAPH_MAKE_FORWARDING_FUNCTION(maximum_adjacency_search,1,5) 315 } // end namespace graph 316 317 } // end namespace boost 318 319 #include <boost/graph/iteration_macros_undef.hpp> 320 321 #endif // BOOST_GRAPH_MAXIMUM_ADJACENCY_SEARCH_H -
boost/graph/stoer_wagner_min_cut.hpp
15 15 #include <boost/graph/buffer_concepts.hpp> 16 16 #include <boost/graph/exception.hpp> 17 17 #include <boost/graph/graph_traits.hpp> 18 #include <boost/graph/ iteration_macros.hpp>18 #include <boost/graph/maximum_adjacency_search.hpp> 19 19 #include <boost/graph/named_function_params.hpp> 20 #include <boost/graph/one_bit_color_map.hpp> 20 21 #include <boost/graph/detail/d_ary_heap.hpp> 21 22 #include <boost/property_map/property_map.hpp> 22 23 #include <boost/tuple/tuple.hpp> 23 24 #include <boost/utility/result_of.hpp> 25 #include <boost/graph/iteration_macros.hpp> 24 26 25 27 namespace boost { 26 28 27 29 namespace detail { 28 29 /** 30 * \brief Performs a phase of the Stoer-Wagner min-cut algorithm 31 * 32 * Performs a phase of the Stoer-Wagner min-cut algorithm. 33 * 34 * As described by Stoer & Wagner (1997), a phase is simply a maximum adjacency search 35 * (also called a maximum cardinality search), which results in the selection of two vertices 36 * \em s and \em t, and, as a side product, a minimum <em>s</em>-<em>t</em> cut of 37 * the input graph. Here, the input graph is basically \p g, but some vertices are virtually 38 * assigned to others as a way of viewing \p g as a graph with some sets of 39 * vertices merged together. 40 * 41 * This implementation is a translation of pseudocode by Professor Uri Zwick, 42 * School of Computer Science, Tel Aviv University. 43 * 44 * \pre \p g is a connected, undirected graph 45 * \param[in] g the input graph 46 * \param[in] assignments a read/write property map from each vertex to the vertex that it is assigned to 47 * \param[in] assignedVertices a list of vertices that are assigned to others 48 * \param[in] weights a readable property map from each edge to its weight (a non-negative value) 49 * \param[out] pq a keyed, updatable max-priority queue 50 * \returns a tuple (\em s, \em t, \em w) of the "<em>s</em>" and "<em>t</em>" 51 * of the minimum <em>s</em>-<em>t</em> cut and the cut weight \em w 52 * of the minimum <em>s</em>-<em>t</em> cut. 53 * \see http://www.cs.tau.ac.il/~zwick/grad-algo-08/gmc.pdf 54 * 55 * \author Daniel Trebbien 56 * \date 2010-09-11 57 */ 58 template <class UndirectedGraph, class VertexAssignmentMap, class WeightMap, class KeyedUpdatablePriorityQueue> 59 boost::tuple<typename boost::graph_traits<UndirectedGraph>::vertex_descriptor, typename boost::graph_traits<UndirectedGraph>::vertex_descriptor, typename boost::property_traits<WeightMap>::value_type> 60 stoer_wagner_phase(const UndirectedGraph& g, VertexAssignmentMap assignments, const std::set<typename boost::graph_traits<UndirectedGraph>::vertex_descriptor>& assignedVertices, WeightMap weights, KeyedUpdatablePriorityQueue& pq) { 61 typedef typename boost::graph_traits<UndirectedGraph>::vertex_descriptor vertex_descriptor; 30 template < typename ParityMap, typename WeightMap, typename IndexMap > 31 class mas_min_cut_visitor : public boost::default_mas_visitor { 32 typedef one_bit_color_map <IndexMap> InternalParityMap; 62 33 typedef typename boost::property_traits<WeightMap>::value_type weight_type; 63 64 BOOST_ASSERT(pq.empty()); 65 typename KeyedUpdatablePriorityQueue::key_map keys = pq.keys(); 66 67 BGL_FORALL_VERTICES_T(v, g, UndirectedGraph) { 68 if (v == get(assignments, v)) { // foreach u \in V do 69 put(keys, v, weight_type(0)); 70 71 pq.push(v); 34 public: 35 template < typename Graph > 36 mas_min_cut_visitor(const Graph& g, 37 ParityMap parity, 38 weight_type& cutweight, 39 WeightMap weight_map, 40 IndexMap index_map) 41 : m_bestParity(parity), 42 m_parity(make_one_bit_color_map(num_vertices(g), index_map)), 43 m_bestWeight(cutweight), 44 m_cutweight(0), 45 m_visited(0), 46 m_weightMap(weight_map) 47 { 48 // set here since the init list sets the reference 49 m_bestWeight = (std::numeric_limits<weight_type>::max)(); 50 } 51 52 template < typename Vertex, typename Graph > 53 void initialize_vertex(Vertex u, const Graph & g) 54 { 55 typedef typename boost::property_traits<ParityMap>::value_type parity_type; 56 typedef typename boost::property_traits<InternalParityMap>::value_type internal_parity_type; 57 58 put(m_parity, u, internal_parity_type(0)); 59 put(m_bestParity, u, parity_type(0)); 60 } 61 62 template < typename Edge, typename Graph > 63 void examine_edge(Edge e, const Graph & g) 64 { 65 weight_type w = get(m_weightMap, e); 66 67 // if the target of e is already marked then decrease cutweight 68 // otherwise, increase it 69 if (get(m_parity, boost::target(e, g))) { 70 m_cutweight -= w; 71 } else { 72 m_cutweight += w; 72 73 } 73 74 } 74 75 BOOST_ASSERT(pq.size() >= 2); 76 77 vertex_descriptor s = boost::graph_traits<UndirectedGraph>::null_vertex(); 78 vertex_descriptor t = boost::graph_traits<UndirectedGraph>::null_vertex(); 79 weight_type w; 80 while (!pq.empty()) { // while PQ \neq {} do 81 const vertex_descriptor u = pq.top(); // u = extractmax(PQ) 82 w = get(keys, u); 83 pq.pop(); 84 85 s = t; t = u; 86 87 BGL_FORALL_OUTEDGES_T(u, e, g, UndirectedGraph) { // foreach (u, v) \in E do 88 const vertex_descriptor v = get(assignments, target(e, g)); 89 90 if (pq.contains(v)) { // if v \in PQ then 91 put(keys, v, get(keys, v) + get(weights, e)); // increasekey(PQ, v, wA(v) + w(u, v)) 92 pq.update(v); 75 76 template < typename Vertex, typename Graph > 77 void finish_vertex(Vertex u, const Graph & g) 78 { 79 typedef typename boost::property_traits<ParityMap>::value_type parity_type; 80 typedef typename boost::property_traits<InternalParityMap>::value_type internal_parity_type; 81 82 ++m_visited; 83 put(m_parity, u, internal_parity_type(1)); 84 85 if (m_cutweight < m_bestWeight && m_visited < num_vertices(g)) { 86 m_bestWeight = m_cutweight; 87 BGL_FORALL_VERTICES_T(i, g, Graph) { 88 put(m_bestParity,i, get(m_parity,i)); 93 89 } 94 90 } 95 96 typename std::set<vertex_descriptor>::const_iterator assignedVertexIt, assignedVertexEnd = assignedVertices.end();97 for (assignedVertexIt = assignedVertices.begin(); assignedVertexIt != assignedVertexEnd; ++assignedVertexIt) {98 const vertex_descriptor uPrime = *assignedVertexIt;99 100 if (get(assignments, uPrime) == u) {101 BGL_FORALL_OUTEDGES_T(uPrime, e, g, UndirectedGraph) { // foreach (u, v) \in E do102 const vertex_descriptor v = get(assignments, target(e, g));103 104 if (pq.contains(v)) { // if v \in PQ then105 put(keys, v, get(keys, v) + get(weights, e)); // increasekey(PQ, v, wA(v) + w(u, v))106 pq.update(v);107 }108 }109 }110 }111 91 } 112 113 return boost::make_tuple(s, t, w); 114 } 115 92 93 inline void clear() { 94 m_bestWeight = (std::numeric_limits<weight_type>::max)(); 95 m_visited = 0; 96 m_cutweight = 0; 97 } 98 99 private: 100 ParityMap m_bestParity; 101 InternalParityMap m_parity; 102 weight_type& m_bestWeight; 103 weight_type m_cutweight; 104 unsigned m_visited; 105 const WeightMap& m_weightMap; 106 }; 107 116 108 /** 117 109 * \brief Computes a min-cut of the input graph 118 110 * … … 135 127 * \author Daniel Trebbien 136 128 * \date 2010-09-11 137 129 */ 138 template <class UndirectedGraph, class WeightMap, class ParityMap, class VertexAssignmentMap, class KeyedUpdatablePriorityQueue >130 template <class UndirectedGraph, class WeightMap, class ParityMap, class VertexAssignmentMap, class KeyedUpdatablePriorityQueue, class IndexMap> 139 131 typename boost::property_traits<WeightMap>::value_type 140 stoer_wagner_min_cut(const UndirectedGraph& g, WeightMap weights, ParityMap parities, VertexAssignmentMap assignments, KeyedUpdatablePriorityQueue& pq) { 132 stoer_wagner_min_cut(const UndirectedGraph& g, WeightMap weights, ParityMap parities, VertexAssignmentMap assignments, KeyedUpdatablePriorityQueue& pq, IndexMap index_map) { 133 typedef typename boost::graph_traits<UndirectedGraph>::vertex_descriptor vertex_descriptor; 134 typedef typename boost::graph_traits<UndirectedGraph>::vertices_size_type vertices_size_type; 135 typedef typename boost::graph_traits<UndirectedGraph>::edge_descriptor edge_descriptor; 136 typedef typename boost::property_traits<WeightMap>::value_type weight_type; 137 typedef typename boost::property_traits<ParityMap>::value_type parity_type; 138 139 typename graph_traits<UndirectedGraph>::vertex_iterator u_iter, u_end; 140 141 weight_type bestW = (std::numeric_limits<weight_type>::max)(); 142 weight_type bestThisTime = (std::numeric_limits<weight_type>::max)(); 143 vertex_descriptor bestStart; 144 145 detail::mas_min_cut_visitor<ParityMap, WeightMap, IndexMap> 146 vis(g, parities, bestThisTime, weights, index_map); 147 148 // for each node in the graph, 149 for (boost::tie(u_iter, u_end) = vertices(g); u_iter != u_end; ++u_iter) { 150 // run the MAS and find the min cut 151 vis.clear(); 152 boost::maximum_adjacency_search(g, 153 boost::weight_map(weights). 154 visitor(vis). 155 root_vertex(*u_iter). 156 vertex_assignment_map(assignments). 157 max_priority_queue(pq)); 158 if (bestThisTime < bestW) { 159 bestW = bestThisTime; 160 bestStart = *u_iter; 161 } 162 } 163 164 // Run one more time, starting from the best start location, to 165 // ensure the visitor has the best values. 166 vis.clear(); 167 boost::maximum_adjacency_search(g, 168 boost::vertex_assignment_map(assignments). 169 weight_map(weights). 170 visitor(vis). 171 root_vertex(bestStart). 172 max_priority_queue(pq)); 173 174 return bestW; 175 } 176 } // end `namespace detail` within `namespace boost` 177 178 template <class UndirectedGraph, class WeightMap, class ParityMap, class VertexAssignmentMap, class KeyedUpdatablePriorityQueue, class IndexMap> 179 typename boost::property_traits<WeightMap>::value_type 180 stoer_wagner_min_cut(const UndirectedGraph& g, WeightMap weights, ParityMap parities, VertexAssignmentMap assignments, KeyedUpdatablePriorityQueue& pq, IndexMap index_map) { 141 181 BOOST_CONCEPT_ASSERT((boost::IncidenceGraphConcept<UndirectedGraph>)); 142 182 BOOST_CONCEPT_ASSERT((boost::VertexListGraphConcept<UndirectedGraph>)); 143 183 typedef typename boost::graph_traits<UndirectedGraph>::vertex_descriptor vertex_descriptor; … … 151 191 BOOST_CONCEPT_ASSERT((boost::ReadWritePropertyMapConcept<VertexAssignmentMap, vertex_descriptor>)); 152 192 BOOST_CONCEPT_ASSERT((boost::Convertible<vertex_descriptor, typename boost::property_traits<VertexAssignmentMap>::value_type>)); 153 193 BOOST_CONCEPT_ASSERT((boost::KeyedUpdatableQueueConcept<KeyedUpdatablePriorityQueue>)); 154 194 155 195 vertices_size_type n = num_vertices(g); 156 196 if (n < 2) 157 197 throw boost::bad_graph("the input graph must have at least two vertices."); 158 198 else if (!pq.empty()) 159 199 throw std::invalid_argument("the max-priority queue must be empty initially."); 160 161 std::set<vertex_descriptor> assignedVertices; 162 163 // initialize `assignments` (all vertices are initially assigned to themselves) 164 BGL_FORALL_VERTICES_T(v, g, UndirectedGraph) { 165 put(assignments, v, v); 200 201 return detail::stoer_wagner_min_cut(g, weights, 202 parities, assignments, pq, index_map); 203 } 204 205 namespace graph { 206 namespace detail { 207 template <class UndirectedGraph, class WeightMap> 208 struct stoer_wagner_min_cut_impl { 209 typedef typename boost::property_traits<WeightMap>::value_type result_type; 210 template <typename ArgPack> 211 result_type operator() (const UndirectedGraph& g, WeightMap weights, const ArgPack& arg_pack) const { 212 using namespace boost::graph::keywords; 213 typedef typename boost::graph_traits<UndirectedGraph>::vertex_descriptor vertex_descriptor; 214 typedef typename boost::property_traits<WeightMap>::value_type weight_type; 215 216 typedef typename boost::detail::make_priority_queue_from_arg_pack_gen<boost::graph::keywords::tag::max_priority_queue, weight_type, vertex_descriptor, std::greater<weight_type> > gen_type; 217 218 gen_type gen(choose_param(get_param(arg_pack, boost::distance_zero_t()), weight_type(0))); 219 220 typename boost::result_of<gen_type(const UndirectedGraph&, const ArgPack&)>::type pq = gen(g, arg_pack); 221 222 return boost::stoer_wagner_min_cut(g, 223 weights, 224 arg_pack [_parity_map | boost::dummy_property_map()], 225 boost::detail::make_property_map_from_arg_pack_gen<tag::vertex_assignment_map, vertex_descriptor>(vertex_descriptor())(g, arg_pack), 226 pq, 227 boost::detail::override_const_property(arg_pack, _vertex_index_map, g, vertex_index) 228 ); 166 229 } 167 168 vertex_descriptor s, t; 169 weight_type bestW; 170 171 boost::tie(s, t, bestW) = boost::detail::stoer_wagner_phase(g, assignments, assignedVertices, weights, pq); 172 BOOST_ASSERT(s != t); 173 BGL_FORALL_VERTICES_T(v, g, UndirectedGraph) { 174 put(parities, v, parity_type(v == t ? 1 : 0)); 175 } 176 put(assignments, t, s); 177 assignedVertices.insert(t); 178 --n; 179 180 for (; n >= 2; --n) { 181 weight_type w; 182 boost::tie(s, t, w) = boost::detail::stoer_wagner_phase(g, assignments, assignedVertices, weights, pq); 183 BOOST_ASSERT(s != t); 184 185 if (w < bestW) { 186 BGL_FORALL_VERTICES_T(v, g, UndirectedGraph) { 187 put(parities, v, parity_type(get(assignments, v) == t ? 1 : 0)); 188 189 if (get(assignments, v) == t) // all vertices that were assigned to t are now assigned to s 190 put(assignments, v, s); 191 } 192 193 bestW = w; 194 } else { 195 BGL_FORALL_VERTICES_T(v, g, UndirectedGraph) { 196 if (get(assignments, v) == t) // all vertices that were assigned to t are now assigned to s 197 put(assignments, v, s); 198 } 199 } 200 put(assignments, t, s); 201 assignedVertices.insert(t); 202 } 203 204 BOOST_ASSERT(pq.empty()); 205 206 return bestW; 230 }; 231 } 232 BOOST_GRAPH_MAKE_FORWARDING_FUNCTION(stoer_wagner_min_cut,2,4) 233 } 234 235 // Named parameter interface 236 BOOST_GRAPH_MAKE_OLD_STYLE_PARAMETER_FUNCTION(stoer_wagner_min_cut, 2) 237 namespace graph { 238 // version without IndexMap kept for backwards compatibility 239 // (but requires vertex_index_t to be defined in the graph) 240 // Place after the macro to avoid compilation errors 241 template <class UndirectedGraph, class WeightMap, class ParityMap, class VertexAssignmentMap, class KeyedUpdatablePriorityQueue> 242 typename boost::property_traits<WeightMap>::value_type 243 stoer_wagner_min_cut(const UndirectedGraph& g, WeightMap weights, ParityMap parities, VertexAssignmentMap assignments, KeyedUpdatablePriorityQueue& pq) { 244 245 return stoer_wagner_min_cut(g, weights, 246 parities, assignments, pq, 247 get(vertex_index, g)); 207 248 } 208 209 } // end `namespace detail` within `namespace boost` 210 211 template <class UndirectedGraph, class WeightMap, class P, class T, class R> 212 inline typename boost::property_traits<WeightMap>::value_type 213 stoer_wagner_min_cut(const UndirectedGraph& g, WeightMap weights, const boost::bgl_named_params<P, T, R>& params) { 214 typedef typename boost::graph_traits<UndirectedGraph>::vertex_descriptor vertex_descriptor; 215 typedef typename std::vector<vertex_descriptor>::size_type heap_container_size_type; 216 typedef typename boost::property_traits<WeightMap>::value_type weight_type; 217 218 typedef boost::bgl_named_params<P, T, R> params_type; 219 BOOST_GRAPH_DECLARE_CONVERTED_PARAMETERS(params_type, params) 220 221 typedef boost::detail::make_priority_queue_from_arg_pack_gen<boost::graph::keywords::tag::max_priority_queue, weight_type, vertex_descriptor, std::greater<weight_type> > gen_type; 222 gen_type gen(choose_param(get_param(params, boost::distance_zero_t()), weight_type(0))); 223 typename boost::result_of<gen_type(const UndirectedGraph&, const arg_pack_type&)>::type pq = gen(g, arg_pack); 224 225 return boost::detail::stoer_wagner_min_cut(g, 226 weights, 227 choose_param(get_param(params, boost::parity_map_t()), boost::dummy_property_map()), 228 boost::detail::make_property_map_from_arg_pack_gen<boost::graph::keywords::tag::vertex_assignment_map, vertex_descriptor>(vertex_descriptor())(g, arg_pack), 229 pq 230 ); 231 } 232 233 template <class UndirectedGraph, class WeightMap> 234 inline typename boost::property_traits<WeightMap>::value_type 235 stoer_wagner_min_cut(const UndirectedGraph& g, WeightMap weights) { 236 return boost::stoer_wagner_min_cut(g, weights, boost::vertex_index_map(get(boost::vertex_index, g))); 237 } 238 249 } // end `namespace graph` 239 250 } // end `namespace boost` 240 251 241 252 #include <boost/graph/iteration_macros_undef.hpp> -
libs/graph/doc/maximum_adjacency_search.html
1 <html> 2 <!-- 3 Copyright (c) Fernando Vilas 2013 4 5 6 Some content from the Stoer-Wagner Min Cut documentation, 7 Copyright (c) Daniel Trebbien 2010 8 9 Distributed under the Boost Software License, Version 1.0. 10 (See accompanying file LICENSE_1_0.txt or copy at 11 http://www.boost.org/LICENSE_1_0.txt) 12 --> 13 <head> 14 <title>Boost Graph Library: Maximum Adjacency Search</Title> 15 <body> 16 <img src="../../../boost.png" alt="C++ Boost" width="277" height="86"> 17 18 <h1><a name="sec:maximum-adjacency-search"></a> 19 <tt>maximum_adjacency_search</tt> 20 </h1> 21 22 <p> 23 <pre> 24 <em>// named parameter versions</em> 25 template <class Graph, class class P, class T, class R> 26 void 27 maximum_adjacency_search(const Graph& g, 28 const bgl_named_params<P, T, R>& params); 29 30 <i>// non-named parameter versions</i> 31 template <class Graph, class WeightMap, class MASVisitor> 32 void 33 maximum_adjacency_search(const Graph& g, WeightMap weights, MASVisitor vis, 34 const typename graph_traits<Graph>::vertex_descriptor start); 35 36 </pre> 37 38 <p> 39 The <tt>maximum_adjacency_search()</tt> function performs a traversal 40 of the vertices in an undirected graph. The next vertex visited is the 41 vertex that has the most visited neighbors at any time. In the case of 42 an unweighted, undirected graph, the number of visited neighbors of the 43 very last vertex visited in the graph is also the number of edge-disjoint 44 paths between that vertex and the next-to-last vertex visited. These can be 45 retrieved from a visitor, an example of which is in the test harness 46 mas_test.cpp. 47 </p> 48 49 <p> 50 The <tt>maximum_adjacency_search()</tt> function invokes user-defined 51 actions at certain event-points within the algorithm. This provides a 52 mechanism for adapting the generic MAS algorithm to the many situations 53 in which it can be used. In the pseudo-code below, the event points 54 for MAS are the labels on the right. The user-defined actions must be 55 provided in the form of a visitor object, that is, an object whose type 56 meets the requirements for a MAS Visitor. 57 </p> 58 59 <table> 60 <tr> 61 <td valign="top"> 62 <pre> 63 MAS(<i>G</i>) 64 <b>for</b> each vertex <i>u in V</i> 65 <i>reach_count[u] := 0</i> 66 <b>end for</b> 67 // for the starting vertex s 68 <i>reach_count[s] := 1</i> 69 <b>for</b> each unvisited vertex <i>u in V</i> 70 <b>call</b> MAS-VISIT(<i>G</i>, <i>u</i>) 71 remove u from the list on unvisited vertices 72 <b>for</b> each out edge from <i>u</i> to <i>t</i> 73 <b>if</b> <i>t</i> has not yet been visited 74 increment <i>reach_count[t]</i> 75 <b>end if</b> 76 <b>end for</b> each out edge 77 <b>call</b> MAS-VISIT(<i>G</i>, <i>u</i>) 78 <b>end for</b> each unvisited vertex 79 <pre> 80 </td> 81 <td valign="top"> 82 <pre> 83 - 84 - 85 initialize vertex <i>u</i> 86 - 87 - 88 - 89 - 90 examine vertex <i>u</i> 91 - 92 examine edge <i>(u,t)</i> 93 - 94 - 95 - 96 - 97 finish vertex <i>u</i> 98 - 99 </pre> 100 </td> 101 </tr> 102 </table> 103 104 <h3>Where Defined</h3> 105 106 <p> 107 <a href="../../../boost/graph/maximum_adjacency_search.hpp"><tt>boost/graph/maximum_adjacency_search.hpp</tt></a></p> 108 109 <h3>Parameters</h3> 110 111 IN: <tt>const UndirectedGraph& g</tt></p> 112 <blockquote> 113 A connected, directed graph. The graph type must 114 be a model of <a href="./IncidenceGraph.html">Incidence Graph</a> 115 and <a href="./VertexListGraph.html">Vertex List Graph</a>.<br> 116 </blockquote> 117 118 <h3>Named Parameters</h3> 119 120 <p>IN: <tt>WeightMap weights</tt></p> 121 <blockquote> 122 The weight or length of each edge in the graph. The 123 <tt>WeightMap</tt> type must be a model of 124 <a href="../../property_map/doc/ReadablePropertyMap.html">Readable 125 Property Map</a> and its value type must be <a class="external" 126 href="http://www.sgi.com/tech/stl/LessThanComparable.html"> 127 Less Than Comparable</a> and summable. The key type of this map 128 needs to be the graph's edge descriptor type. 129 <b>Default:</b> <tt>get(edge_weight, g)</tt><br> 130 </blockquote> 131 132 IN: <tt>visitor(MASVisitor vis)</tt></p> 133 <blockquote> 134 A visitor object that is invoked inside the algorithm at the 135 event-points specified by the MAS Visitor concept. The visitor 136 object is passed by value <a href="#1">[1]</a>. <br> 137 <b>Default:</b> <tt>mas_visitor<null_visitor></tt><br> 138 </blockquote> 139 140 IN: <tt>root_vertex(typename 141 graph_traits<VertexListGraph>::vertex_descriptor start)</tt></p> 142 <blockquote> 143 This specifies the vertex that the depth-first search should 144 originate from. The type is the type of a vertex descriptor for the 145 given graph.<br> 146 <b>Default:</b> <tt>*vertices(g).first</tt><br> 147 </blockquote> 148 149 <h4>Expert Parameters</h4> 150 151 <p>IN: <tt>vertex_index_map(VertexIndexMap vertexIndices)</tt> </p> 152 <blockquote> 153 This maps each vertex to an integer in the range 154 [0, <tt>num_vertices(g)</tt>). This is only necessary if the default is 155 used for the assignment, index-in-heap, or distance maps. 156 <tt>VertexIndexMap</tt> must be a model of <a 157 href="../../property_map/doc/ReadablePropertyMap.html">Readable Property 158 Map</a>. The value type of the map must be an integer type. The 159 key type must be the graph's vertex descriptor type.<br> 160 <b>Default:</b> <tt>get(boost::vertex_index, g)</tt> 161 Note: if you use this default, make sure your graph has 162 an internal <tt>vertex_index</tt> property. For example, 163 <tt>adjacency_list</tt> with <tt>VertexList=listS</tt> does 164 not have an internal <tt>vertex_index</tt> property. 165 </blockquote> 166 167 <p>UTIL: <tt>vertex_assignment_map(AssignmentMap assignments)</tt></p> 168 <blockquote> 169 <tt>AssignmentMap</tt> must be a model of <a 170 href="../../property_map/doc/ReadWritePropertyMap.html">Read/Write Property 171 Map</a>. The key and value types must be the graph's vertex descriptor 172 type.<br> 173 <b>Default:</b> A <tt>boost::iterator_property_map</tt> using a 174 <tt>std::vector</tt> of <tt>num_vertices(g)</tt> vertex descriptors and 175 <tt>vertexIndices</tt> for the index map. 176 </blockquote> 177 178 <p>UTIL: <tt>max_priority_queue(MaxPriorityQueue& pq)</tt></p> 179 <blockquote> 180 <tt>MaxPriorityQueue</tt> must be a model of <a 181 href="./KeyedUpdatableQueue.html">Keyed Updatable Queue</a> and a 182 max-<a href="./UpdatableQueue.html#concept%3AUpdatablePriorityQueue"> 183 Updatable Priority Queue</a>. The value type must be the graph's vertex 184 descriptor and the key type must be the weight type. 185 <b>Default:</b> A <tt>boost::d_ary_heap_indirect</tt> using a default 186 index-in-heap and distance map. 187 </blockquote> 188 189 <p>UTIL: <tt>index_in_heap_map(IndexInHeapMap indicesInHeap)</tt></p> 190 <blockquote> 191 This parameter only has an effect when the default max-priority queue is used.<br> 192 <tt>IndexInHeapMap</tt> must be a model of <a 193 href="../../property_map/doc/ReadWritePropertyMap.html">Read/Write Property 194 Map</a>. The key type must be the graph's vertex descriptor type. The 195 value type must be a size type 196 (<tt>typename std::vector<vertex_descriptor>::size_type</tt>).<br> 197 <b>Default:</b> A <tt>boost::iterator_property_map</tt> using a 198 <tt>std::vector</tt> of <tt>num_vertices(g)</tt> size type objects and 199 <tt>vertexIndices</tt> for the index map. 200 </blockquote> 201 202 <p>UTIL: <tt>distance_map(DistanceMap wAs)</tt></p> 203 <blockquote> 204 This parameter only has an effect when the default max-priority queue is used.<br> 205 <tt>DistanceMap</tt> must be a model of <a 206 href="../../property_map/doc/ReadWritePropertyMap.html">Read/Write Property 207 Map</a>. The key type must be the graph's vertex descriptor type. The 208 value type must be the weight type 209 (<tt>typename boost::property_traits<WeightMap>::value_type</tt>). 210 <br> 211 <b>Default:</b> A <tt>boost::iterator_property_map</tt> using a 212 <tt>std::vector</tt> of <tt>num_vertices(g)</tt> weight type objects 213 and <tt>vertexIndices</tt> for the index map. 214 </blockquote> 215 216 <h3>Returns</h3> 217 <p>void</p> 218 219 <h3>Throws</h3> 220 221 <p><tt>bad_graph</tt> 222 <blockquote> 223 If <tt>num_vertices(g)</tt> is less than 2 224 </blockquote></p> 225 226 <p><tt>std::invalid_argument</tt> 227 <blockquote> 228 If a max-priority queue is given as an argument and it is not empty 229 </blockquote>. 230 231 <h3><a name="SECTION001340300000000000000"> 232 Complexity</a> 233 </h3> 234 235 <p> 236 The time complexity is <i>O(E + V)</i>. 237 </p> 238 239 <h3>References</h3> 240 <ul> 241 <li>David Matula (1993). <q><a href="http://dl.acm.org/citation.cfm?id=313872&dl=ACM&coll=DL&CFID=85991501&CFTOKEN=44461131">A linear time 2 + epsilon approximation algorightm for edge connectivity</a></q> 242 </li> 243 <li>Cai, Weiqing and Matula, David W. 244 Partitioning by maximum adjacency search of graphs. 245 Partitioning Data Sets: Dimacs Workshop, April 19-21, 1993. 246 Vol 19. Page 55. 1995. Amer Mathematical Society</li> 247 } 248 </ul> 249 250 <h3>Visitor Event Points</h3> 251 252 <ul> 253 <li><b><tt>vis.initialize_vertex(s, g)</tt></b> is invoked on every 254 vertex of the graph before the start of the graph search.</li> 255 256 <li><b><tt>vis.start_vertex(s, g)</tt></b> is invoked on the source 257 vertex once before processing its out edges.</li> 258 259 <li><b><tt>vis.examine_edge(e, g)</tt></b> is invoked on every out-edge 260 of each vertex after it is started.</li> 261 262 <li><b><tt>vis.finish_vertex(u, g)</tt></b> is invoked on a vertex after 263 all of its out edges have been examined and the reach counts of the 264 unvisited targets have been updated.</li> 265 </ul> 266 267 <h3>Notes</h3> 268 269 <p><a name="1">[1]</a> 270 Since the visitor parameter is passed by value, if your visitor 271 contains state then any changes to the state during the algorithm 272 will be made to a copy of the visitor object, not the visitor object 273 passed in. Therefore you may want the visitor to hold this state by 274 pointer or reference.</p> 275 276 <hr> 277 <table> 278 <tr valign=top> 279 <td nowrap>Copyright © 2012</td><td> 280 Fernando Vilas 281 </td></tr></table> 282 283 </body> 284 </html> -
libs/graph/test/Jamfile.v2
123 123 [ run two_graphs_common_spanning_trees_test.cpp ] 124 124 [ run random_spanning_tree_test.cpp ../build//boost_graph ] 125 125 [ run graphml_test.cpp ../build//boost_graph : : "graphml_test.xml" ] 126 [ run mas_test.cpp ../../test/build//boost_unit_test_framework/<link>static : $(TEST_DIR) ] 126 127 [ run stoer_wagner_test.cpp ../../test/build//boost_unit_test_framework/<link>static : $(TEST_DIR) ] 127 128 [ compile filtered_graph_properties_dijkstra.cpp ] 128 129 [ run vf2_sub_graph_iso_test.cpp ] -
libs/graph/test/mas_test.cpp
1 // Copyright Fernando Vilas 2012. 2 // Based on stoer_wagner_test.cpp by Daniel Trebbien. 3 // Distributed under the Boost Software License, Version 1.0. 4 // (See accompanying file LICENSE_1_0.txt or the copy at 5 // http://www.boost.org/LICENSE_1_0.txt) 6 7 #include <fstream> 8 #include <iostream> 9 #include <map> 10 #include <vector> 11 #include <string> 12 #include <boost/graph/adjacency_list.hpp> 13 #include <boost/graph/connected_components.hpp> 14 #include <boost/graph/exception.hpp> 15 #include <boost/graph/graph_traits.hpp> 16 #include <boost/graph/read_dimacs.hpp> 17 #include <boost/graph/maximum_adjacency_search.hpp> 18 #include <boost/graph/visitors.hpp> 19 #include <boost/graph/property_maps/constant_property_map.hpp> 20 #include <boost/property_map/property_map.hpp> 21 #include <boost/test/unit_test.hpp> 22 #include <boost/tuple/tuple.hpp> 23 #include <boost/tuple/tuple_comparison.hpp> 24 #include <boost/tuple/tuple_io.hpp> 25 26 #include <boost/graph/iteration_macros.hpp> 27 28 typedef boost::adjacency_list<boost::vecS, boost::vecS, boost::undirectedS, boost::no_property, boost::property<boost::edge_weight_t, int> > undirected_graph; 29 typedef boost::property_map<undirected_graph, boost::edge_weight_t>::type weight_map_type; 30 typedef boost::property_traits<weight_map_type>::value_type weight_type; 31 32 typedef boost::adjacency_list<boost::vecS, boost::vecS, boost::undirectedS> undirected_unweighted_graph; 33 34 std::string test_dir; 35 36 boost::unit_test::test_suite* init_unit_test_suite( int argc, char* argv[] ) { 37 if (argc != 2) { 38 std::cerr << "Usage: " << argv[0] << " path-to-libs-graph-test" << std::endl; 39 throw boost::unit_test::framework::setup_error("Invalid command line arguments"); 40 } 41 test_dir = argv[1]; 42 return 0; 43 } 44 45 struct edge_t 46 { 47 unsigned long first; 48 unsigned long second; 49 }; 50 51 template <typename Graph, typename KeyedUpdatablePriorityQueue> 52 class mas_edge_connectivity_visitor : public boost::default_mas_visitor { 53 public: 54 typedef typename boost::graph_traits<Graph>::vertex_descriptor vertex_descriptor; 55 typedef typename KeyedUpdatablePriorityQueue::key_type weight_type; 56 #if 0 57 mas_edge_connectivity_visitor(const mas_edge_connectivity_visitor<Graph, KeyedUpdatablePriorityQueue>& r) 58 : m_pq(r.m_pq), m_curr(r.m_curr), m_prev(r.m_prev), 59 m_reach_weight(r.m_reach_weight) { 60 BOOST_TEST_MESSAGE( "COPY CTOR" ); 61 } 62 #endif 63 explicit mas_edge_connectivity_visitor(KeyedUpdatablePriorityQueue& pq) 64 : m_pq(pq), 65 m_curr(new vertex_descriptor(0)), m_prev(new vertex_descriptor(0)), 66 m_reach_weight(new weight_type(0)) { 67 // BOOST_TEST_MESSAGE( "CTOR" ); 68 } 69 70 void clear() { 71 *m_curr = 0; 72 *m_prev = 0; 73 *m_reach_weight = 0; 74 } 75 76 //template <typename Vertex> //, typename Graph> 77 //void start_vertex(Vertex u, const Graph& g) { 78 void start_vertex(vertex_descriptor u, const Graph& g) { 79 *m_prev = *m_curr; 80 *m_curr = u; 81 //BOOST_TEST_MESSAGE( "Initializing Vertex(weight): " << u << "(" << *m_reach_weight << ")" ); 82 *m_reach_weight = get(m_pq.keys(), u); 83 } 84 85 vertex_descriptor curr() const { return *m_curr; } 86 vertex_descriptor prev() const { return *m_prev; } 87 weight_type reach_weight() const { return *m_reach_weight; } 88 89 private: 90 91 const KeyedUpdatablePriorityQueue& m_pq; 92 boost::shared_ptr<vertex_descriptor> m_curr, m_prev; 93 boost::shared_ptr<weight_type> m_reach_weight; 94 }; 95 96 97 // the example from Stoer & Wagner (1997) 98 // Check various implementations of the ArgPack where 99 // the weights are provided in it, and one case where 100 // they are not. 101 BOOST_AUTO_TEST_CASE(test0) 102 { 103 typedef boost::graph_traits<undirected_graph>::vertex_descriptor vertex_descriptor; 104 typedef boost::graph_traits<undirected_graph>::edge_descriptor edge_descriptor; 105 106 edge_t edges[] = {{0, 1}, {1, 2}, {2, 3}, 107 {0, 4}, {1, 4}, {1, 5}, {2, 6}, {3, 6}, {3, 7}, {4, 5}, {5, 6}, {6, 7}}; 108 weight_type ws[] = {2, 3, 4, 3, 2, 2, 2, 2, 2, 3, 1, 3}; 109 undirected_graph g(edges, edges + 12, ws, 8, 12); 110 111 weight_map_type weights = get(boost::edge_weight, g); 112 113 std::map<vertex_descriptor, vertex_descriptor> assignment; 114 boost::associative_property_map<std::map<vertex_descriptor, vertex_descriptor> > assignments(assignment); 115 116 typedef boost::shared_array_property_map<weight_type, boost::property_map<undirected_graph, boost::vertex_index_t>::const_type> distances_type; 117 distances_type distances = boost::make_shared_array_property_map(num_vertices(g), weight_type(0), get(boost::vertex_index, g)); 118 typedef std::vector<vertex_descriptor>::size_type index_in_heap_type; 119 typedef boost::shared_array_property_map<index_in_heap_type, boost::property_map<undirected_graph, boost::vertex_index_t>::const_type> indicesInHeap_type; 120 indicesInHeap_type indicesInHeap = boost::make_shared_array_property_map(num_vertices(g), index_in_heap_type(-1), get(boost::vertex_index, g)); 121 boost::d_ary_heap_indirect<vertex_descriptor, 22, indicesInHeap_type, distances_type, std::greater<weight_type> > pq(distances, indicesInHeap); 122 123 mas_edge_connectivity_visitor<undirected_graph,boost::d_ary_heap_indirect<vertex_descriptor, 22, indicesInHeap_type, distances_type, std::greater<weight_type> > > test_vis(pq); 124 125 boost::maximum_adjacency_search(g, 126 boost::weight_map(weights). 127 visitor(test_vis). 128 root_vertex(*vertices(g).first). 129 vertex_assignment_map(assignments). 130 max_priority_queue(pq)); 131 132 BOOST_CHECK_EQUAL(test_vis.curr(), vertex_descriptor(7)); 133 BOOST_CHECK_EQUAL(test_vis.prev(), vertex_descriptor(6)); 134 BOOST_CHECK_EQUAL(test_vis.reach_weight(), 5); 135 136 test_vis.clear(); 137 boost::maximum_adjacency_search(g, 138 boost::weight_map(weights). 139 visitor(test_vis). 140 root_vertex(*vertices(g).first). 141 max_priority_queue(pq)); 142 143 BOOST_CHECK_EQUAL(test_vis.curr(), vertex_descriptor(7)); 144 BOOST_CHECK_EQUAL(test_vis.prev(), vertex_descriptor(6)); 145 BOOST_CHECK_EQUAL(test_vis.reach_weight(), 5); 146 147 test_vis.clear(); 148 boost::maximum_adjacency_search(g, 149 boost::weight_map(weights). 150 visitor(test_vis). 151 max_priority_queue(pq)); 152 153 BOOST_CHECK_EQUAL(test_vis.curr(), vertex_descriptor(7)); 154 BOOST_CHECK_EQUAL(test_vis.prev(), vertex_descriptor(6)); 155 BOOST_CHECK_EQUAL(test_vis.reach_weight(), 5); 156 157 boost::maximum_adjacency_search(g, 158 boost::weight_map(weights). 159 visitor(boost::make_mas_visitor(boost::null_visitor()))); 160 161 boost::maximum_adjacency_search(g, 162 boost::weight_map(weights)); 163 164 boost::maximum_adjacency_search(g, 165 boost::root_vertex(*vertices(g).first)); 166 167 test_vis.clear(); 168 boost::maximum_adjacency_search(g, 169 boost::weight_map(boost::make_constant_property<edge_descriptor>(weight_type(1))). 170 visitor(test_vis). 171 max_priority_queue(pq)); 172 BOOST_CHECK_EQUAL(test_vis.curr(), vertex_descriptor(7)); 173 BOOST_CHECK_EQUAL(test_vis.prev(), vertex_descriptor(3)); 174 BOOST_CHECK_EQUAL(test_vis.reach_weight(), 2); 175 176 } 177 178 // Check the unweighted case 179 // with and without providing a weight_map 180 BOOST_AUTO_TEST_CASE(test1) 181 { 182 typedef boost::graph_traits<undirected_unweighted_graph>::vertex_descriptor vertex_descriptor; 183 typedef boost::graph_traits<undirected_unweighted_graph>::edge_descriptor edge_descriptor; 184 185 edge_t edge_list[] = {{0, 1}, {1, 2}, {2, 3}, 186 {0, 4}, {1, 4}, {1, 5}, {2, 6}, {3, 6}, {3, 7}, {4, 5}, {5, 6}, {6, 7}}; 187 undirected_unweighted_graph g(edge_list, edge_list + 12, 8); 188 189 std::map<vertex_descriptor, vertex_descriptor> assignment; 190 boost::associative_property_map<std::map<vertex_descriptor, vertex_descriptor> > assignments(assignment); 191 192 typedef unsigned weight_type; 193 typedef boost::shared_array_property_map<weight_type, boost::property_map<undirected_graph, boost::vertex_index_t>::const_type> distances_type; 194 distances_type distances = boost::make_shared_array_property_map(num_vertices(g), weight_type(0), get(boost::vertex_index, g)); 195 typedef std::vector<vertex_descriptor>::size_type index_in_heap_type; 196 typedef boost::shared_array_property_map<index_in_heap_type, boost::property_map<undirected_graph, boost::vertex_index_t>::const_type> indicesInHeap_type; 197 indicesInHeap_type indicesInHeap = boost::make_shared_array_property_map(num_vertices(g), index_in_heap_type(-1), get(boost::vertex_index, g)); 198 boost::d_ary_heap_indirect<vertex_descriptor, 22, indicesInHeap_type, distances_type, std::greater<weight_type> > pq(distances, indicesInHeap); 199 200 mas_edge_connectivity_visitor<undirected_unweighted_graph,boost::d_ary_heap_indirect<vertex_descriptor, 22, indicesInHeap_type, distances_type, std::greater<weight_type> > > test_vis(pq); 201 202 boost::maximum_adjacency_search(g, 203 boost::weight_map(boost::make_constant_property<edge_descriptor>(weight_type(1))).visitor(test_vis).max_priority_queue(pq)); 204 205 BOOST_CHECK_EQUAL(test_vis.curr(), vertex_descriptor(7)); 206 BOOST_CHECK_EQUAL(test_vis.prev(), vertex_descriptor(3)); 207 BOOST_CHECK_EQUAL(test_vis.reach_weight(), weight_type(2)); 208 209 weight_type ws[] = {2, 3, 4, 3, 2, 2, 2, 2, 2, 3, 1, 3}; 210 std::map<edge_descriptor, weight_type> wm; 211 212 weight_type i = 0; 213 BGL_FORALL_EDGES_T(e, g, undirected_unweighted_graph) { 214 wm[e] = ws[i]; 215 ++i; 216 } 217 boost::associative_property_map<std::map<edge_descriptor, weight_type> > ws_map(wm); 218 219 boost::maximum_adjacency_search(g, boost::weight_map(ws_map).visitor(test_vis).max_priority_queue(pq)); 220 BOOST_CHECK_EQUAL(test_vis.curr(), vertex_descriptor(7)); 221 BOOST_CHECK_EQUAL(test_vis.prev(), vertex_descriptor(6)); 222 BOOST_CHECK_EQUAL(test_vis.reach_weight(), weight_type(5)); 223 224 } 225 226 #include <boost/graph/iteration_macros_undef.hpp> 227