Ticket #6780: max_adj_search_v7.patch
File max_adj_search_v7.patch, 37.7 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 * The algorithm returns the last 2 vertices visited (s and t), and 38 * the key from the priority queue of the last vertex (t) when 39 * removed. 40 * 41 */ 42 43 #include <boost/concept_check.hpp> 44 #include <boost/concept/assert.hpp> 45 #include <boost/graph/buffer_concepts.hpp> 46 #include <boost/graph/exception.hpp> 47 #include <boost/graph/graph_concepts.hpp> 48 #include <boost/graph/iteration_macros.hpp> 49 #include <boost/graph/named_function_params.hpp> 50 #include <boost/graph/visitors.hpp> 51 #include <boost/tuple/tuple.hpp> 52 53 #include <set> 54 55 namespace boost { 56 template <class Visitor, class Graph> 57 struct MASVisitorConcept { 58 void constraints() { 59 boost::function_requires< boost::CopyConstructibleConcept<Visitor> >(); 60 vis.initialize_vertex(u, g); 61 vis.start_vertex(u, g); 62 vis.examine_edge(e, g); 63 vis.finish_vertex(u, g); 64 } 65 Visitor vis; 66 Graph g; 67 typename boost::graph_traits<Graph>::vertex_descriptor u; 68 typename boost::graph_traits<Graph>::edge_descriptor e; 69 }; 70 71 template <class Visitors = null_visitor> 72 class mas_visitor { 73 public: 74 mas_visitor() { } 75 mas_visitor(Visitors vis) : m_vis(vis) { } 76 77 template <class Vertex, class Graph> 78 void 79 initialize_vertex(Vertex u, Graph& g) 80 { 81 invoke_visitors(m_vis, u, g, ::boost::on_initialize_vertex()); 82 } 83 84 template <class Vertex, class Graph> 85 void 86 start_vertex(Vertex u, Graph& g) 87 { 88 invoke_visitors(m_vis, u, g, ::boost::on_start_vertex()); 89 } 90 91 template <class Edge, class Graph> 92 void 93 examine_edge(Edge e, Graph& g) 94 { 95 invoke_visitors(m_vis, e, g, ::boost::on_examine_edge()); 96 } 97 98 template <class Vertex, class Graph> 99 void 100 finish_vertex(Vertex u, Graph& g) 101 { 102 invoke_visitors(m_vis, u, g, ::boost::on_finish_vertex()); 103 } 104 105 BOOST_GRAPH_EVENT_STUB(on_initialize_vertex,mas) 106 BOOST_GRAPH_EVENT_STUB(on_start_vertex,mas) 107 BOOST_GRAPH_EVENT_STUB(on_examine_edge,mas) 108 BOOST_GRAPH_EVENT_STUB(on_finish_vertex,mas) 109 110 protected: 111 Visitors m_vis; 112 }; 113 template <class Visitors> 114 mas_visitor<Visitors> 115 make_mas_visitor(Visitors vis) { 116 return mas_visitor<Visitors>(vis); 117 } 118 typedef mas_visitor<> default_mas_visitor; 119 120 namespace detail { 121 template <class Graph, class WeightMap, class MASVisitor, class VertexAssignmentMap, class KeyedUpdatablePriorityQueue> 122 boost::tuple<typename boost::graph_traits<Graph>::vertex_descriptor, typename boost::graph_traits<Graph>::vertex_descriptor, typename KeyedUpdatablePriorityQueue::key_type> 123 maximum_adjacency_search(const Graph& g, WeightMap weights, MASVisitor vis, const typename boost::graph_traits<Graph>::vertex_descriptor start, VertexAssignmentMap assignments, KeyedUpdatablePriorityQueue pq) { 124 typedef typename boost::graph_traits<Graph>::vertex_descriptor vertex_descriptor; 125 typedef typename boost::graph_traits<Graph>::vertices_size_type vertices_size_type; 126 typedef typename boost::graph_traits<Graph>::edge_descriptor edge_descriptor; 127 typedef typename boost::property_traits<WeightMap>::value_type weight_type; 128 129 std::set<vertex_descriptor> assignedVertices; 130 131 // initialize `assignments` (all vertices are initially 132 // assigned to themselves) 133 BGL_FORALL_VERTICES_T(v, g, Graph) { 134 put(assignments, v, v); 135 } 136 137 typename KeyedUpdatablePriorityQueue::key_map keys = pq.keys(); 138 139 // set number of visited neighbors for all vertices to 0 140 BGL_FORALL_VERTICES_T(v, g, Graph) { 141 if (v == get(assignments, v)) { // foreach u \in V do 142 put(keys, v, weight_type(0)); vis.initialize_vertex(v, g); 143 144 pq.push(v); 145 } 146 } 147 assert(pq.size() >= 2); 148 149 // Give the starting vertex high priority 150 put(keys, start, get(keys, start) + num_vertices(g) + 1); 151 pq.update(start); 152 153 // start traversing the graph 154 vertex_descriptor s, t; 155 weight_type w; 156 while (!pq.empty()) { // while PQ \neq {} do 157 const vertex_descriptor u = pq.top(); // u = extractmax(PQ) 158 w = get(keys, u); 159 pq.pop(); vis.start_vertex(u, g); 160 161 // set s and t to the last and next-to-last vertices extracted 162 s = t; t = u; 163 164 BGL_FORALL_OUTEDGES_T(u, e, g, Graph) { // foreach (u, v) \in E do 165 vis.examine_edge(e, g); 166 167 const vertex_descriptor v = get(assignments, target(e, g)); 168 169 if (pq.contains(v)) { // if v \in PQ then 170 put(keys, v, get(keys, v) + get(weights, e)); // increasekey(PQ, v, wA(v) + w(u, v)) 171 pq.update(v); 172 } 173 } 174 175 typename std::set<vertex_descriptor>::const_iterator assignedVertexIt, assignedVertexEnd = assignedVertices.end(); 176 for (assignedVertexIt = assignedVertices.begin(); assignedVertexIt != assignedVertexEnd; ++assignedVertexIt) { 177 const vertex_descriptor uPrime = *assignedVertexIt; 178 179 if (get(assignments, uPrime) == u) { 180 BGL_FORALL_OUTEDGES_T(uPrime, e, g, Graph) { // foreach (u, v) \in E do 181 vis.examine_edge(e, g); 182 183 const vertex_descriptor v = get(assignments, target(e, g)); 184 185 if (pq.contains(v)) { // if v \in PQ then 186 put(keys, v, get(keys, v) + get(weights, e)); // increasekey(PQ, v, wA(v) + w(u, v)) 187 pq.update(v); 188 } 189 } 190 } 191 } 192 vis.finish_vertex(u, g); 193 } 194 return boost::make_tuple(s,t,w); 195 } 196 } // end namespace detail 197 198 template <class Graph, class WeightMap, class MASVisitor, class VertexAssignmentMap, class KeyedUpdatablePriorityQueue> 199 boost::tuple<typename boost::graph_traits<Graph>::vertex_descriptor, typename boost::graph_traits<Graph>::vertex_descriptor, typename KeyedUpdatablePriorityQueue::key_type> 200 maximum_adjacency_search(const Graph& g, WeightMap weights, MASVisitor vis, const typename boost::graph_traits<Graph>::vertex_descriptor start, VertexAssignmentMap assignments, KeyedUpdatablePriorityQueue pq) { 201 BOOST_CONCEPT_ASSERT((boost::IncidenceGraphConcept<Graph>)); 202 BOOST_CONCEPT_ASSERT((boost::VertexListGraphConcept<Graph>)); 203 typedef typename boost::graph_traits<Graph>::vertex_descriptor vertex_descriptor; 204 typedef typename boost::graph_traits<Graph>::vertices_size_type vertices_size_type; 205 typedef typename boost::graph_traits<Graph>::edge_descriptor edge_descriptor; 206 BOOST_CONCEPT_ASSERT((boost::Convertible<typename boost::graph_traits<Graph>::directed_category, boost::undirected_tag>)); 207 BOOST_CONCEPT_ASSERT((boost::ReadablePropertyMapConcept<WeightMap, edge_descriptor>)); 208 typedef typename boost::property_traits<WeightMap>::value_type weight_type; 209 boost::function_requires< MASVisitorConcept<MASVisitor, Graph> >(); 210 BOOST_CONCEPT_ASSERT((boost::ReadWritePropertyMapConcept<VertexAssignmentMap, vertex_descriptor>)); 211 BOOST_CONCEPT_ASSERT((boost::Convertible<vertex_descriptor, typename boost::property_traits<VertexAssignmentMap>::value_type>)); 212 BOOST_CONCEPT_ASSERT((boost::KeyedUpdatableQueueConcept<KeyedUpdatablePriorityQueue>)); 213 214 vertices_size_type n = num_vertices(g); 215 if (n < 2) 216 throw boost::bad_graph("the input graph must have at least two vertices."); 217 else if (!pq.empty()) 218 throw std::invalid_argument("the max-priority queue must be empty initially."); 219 220 return detail::maximum_adjacency_search(g, weights, 221 vis, start, 222 assignments, pq); 223 } 224 225 namespace graph { 226 namespace detail { 227 template <class Graph> 228 struct maximum_adjacency_search_impl { 229 230 typedef typename boost::graph_traits<Graph>::vertex_descriptor vertex_descriptor; 231 232 //TODO: This assumes that the weight map has edge_weight_t values in it. 233 // If this is not true, it may fail to compile. We should really rely on 234 // the ArgPack, but the named parameter macros require a result_type. 235 // Can this be fixed? 236 typedef typename boost::tuple<vertex_descriptor, vertex_descriptor, 237 typename boost::property_traits<typename property_map<Graph, edge_weight_t>::type>::value_type> 238 result_type; 239 240 template <typename ArgPack> 241 result_type 242 operator() (const Graph& g, const ArgPack& arg_pack) const { 243 using namespace boost::graph::keywords; 244 typedef typename std::vector<vertex_descriptor>::size_type heap_container_size_type; 245 typedef typename parameter::value_type<ArgPack, tag::weight_map, typename property_map<Graph, edge_weight_t>::type >::type WeightMap; 246 typedef typename boost::property_traits<WeightMap>::value_type weight_type; 247 248 return boost::maximum_adjacency_search 249 (g, 250 arg_pack[_weight_map | get(edge_weight, g)], 251 arg_pack[_visitor | make_mas_visitor(null_visitor())], 252 arg_pack[_root_vertex | *vertices(g).first], 253 arg_pack[_vertex_assignment_map | boost::detail::make_property_map_from_arg_pack_gen<tag::vertex_assignment_map, vertex_descriptor>(vertex_descriptor())(g, arg_pack)], 254 unwrap_ref(arg_pack[_max_priority_queue | boost::detail::make_priority_queue_from_arg_pack_gen<tag::max_priority_queue, weight_type, vertex_descriptor, std::greater<weight_type> >(choose_param(get_param(arg_pack, boost::distance_zero_t()), weight_type(0)))(g, arg_pack)])); 255 } 256 }; 257 } 258 BOOST_GRAPH_MAKE_FORWARDING_FUNCTION(maximum_adjacency_search,1,5) 259 } 260 // Named parameter interface 261 BOOST_GRAPH_MAKE_OLD_STYLE_PARAMETER_FUNCTION(maximum_adjacency_search, 1) 262 263 } // end namespace boost 264 265 #include <boost/graph/iteration_macros_undef.hpp> 266 267 #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; 62 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); 30 template < typename ParityMap, typename WeightType, typename WeightMap > 31 class mas_min_cut_visitor : public boost::default_mas_visitor { 32 public: 33 mas_min_cut_visitor(ParityMap parity, 34 WeightType& cutweight, 35 const WeightMap& weight_map) 36 : m_bestParity(parity), 37 m_parity(parity), 38 m_bestWeight(cutweight), 39 m_cutweight(0), 40 m_visited(0), 41 m_weightMap(weight_map) 42 { 43 // set here since the init list sets the reference 44 m_bestWeight = (std::numeric_limits<WeightType>::max)(); 45 46 // reallocate the parity map since it is for internal 47 // bookkeeping here only. 48 // TODO: specific to one-bit color map. make it not depend on that. 49 m_parity.data.reset(new unsigned char[(m_parity.n + m_parity.bits_per_char - 1) / m_parity.bits_per_char]); 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 put(m_parity, u, parity_type(0)); 57 put(m_bestParity, u, parity_type(0)); 58 } 59 60 template < typename Edge, typename Graph > 61 void examine_edge(Edge e, const Graph & g) 62 { 63 WeightType w = get(m_weightMap, e); 64 65 // if the target of e is already marked then decrease cutweight 66 // otherwise, increase it 67 if (get(m_parity, boost::target(e, g))) { 68 m_cutweight -= w; 69 } else { 70 m_cutweight += w; 72 71 } 73 72 } 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); 73 74 template < typename Vertex, typename Graph > 75 void finish_vertex(Vertex u, const Graph & g) 76 { 77 typedef typename boost::property_traits<ParityMap>::value_type parity_type; 78 ++m_visited; 79 put(m_parity, u, parity_type(1)); 80 81 if (m_cutweight < m_bestWeight && m_visited < num_vertices(g)) { 82 m_bestWeight = m_cutweight; 83 BGL_FORALL_VERTICES_T(i, g, Graph) { 84 put(m_bestParity,i, get(m_parity,i)); 93 85 } 94 86 } 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 87 } 112 113 return boost::make_tuple(s, t, w); 114 } 115 88 89 inline void clear() { 90 m_bestWeight = (std::numeric_limits<WeightType>::max)(); 91 m_visited = 0; 92 m_cutweight = 0; 93 } 94 95 private: 96 ParityMap m_bestParity; 97 ParityMap m_parity; 98 WeightType & m_bestWeight; 99 WeightType m_cutweight; 100 unsigned m_visited; 101 const WeightMap& m_weightMap; 102 }; 103 116 104 /** 117 105 * \brief Computes a min-cut of the input graph 118 106 * … … 138 126 template <class UndirectedGraph, class WeightMap, class ParityMap, class VertexAssignmentMap, class KeyedUpdatablePriorityQueue> 139 127 typename boost::property_traits<WeightMap>::value_type 140 128 stoer_wagner_min_cut(const UndirectedGraph& g, WeightMap weights, ParityMap parities, VertexAssignmentMap assignments, KeyedUpdatablePriorityQueue& pq) { 129 typedef typename boost::graph_traits<UndirectedGraph>::vertex_descriptor vertex_descriptor; 130 typedef typename boost::graph_traits<UndirectedGraph>::vertices_size_type vertices_size_type; 131 typedef typename boost::graph_traits<UndirectedGraph>::edge_descriptor edge_descriptor; 132 typedef typename boost::property_traits<WeightMap>::value_type weight_type; 133 typedef typename boost::property_traits<ParityMap>::value_type parity_type; 134 135 typename graph_traits<UndirectedGraph>::vertex_iterator u_iter, u_end; 136 137 weight_type bestW = (std::numeric_limits<weight_type>::max)(); 138 weight_type bestThisTime = (std::numeric_limits<weight_type>::max)(); 139 vertex_descriptor bestStart; 140 141 detail::mas_min_cut_visitor<ParityMap, weight_type, WeightMap> 142 vis(parities, bestThisTime, weights); 143 144 // for each node in the graph, 145 for (boost::tie(u_iter, u_end) = vertices(g); u_iter != u_end; ++u_iter) { 146 // run the MAS and find the min cut 147 vis.clear(); 148 boost::maximum_adjacency_search(g, 149 boost::vertex_assignment_map(assignments). 150 weight_map(weights). 151 visitor(vis). 152 root_vertex(*u_iter). 153 max_priority_queue(pq)); 154 if (bestThisTime < bestW) { 155 bestW = bestThisTime; 156 bestStart = *u_iter; 157 } 158 } 159 160 // Run one more time, starting from the best start location, to 161 // ensure the visitor has the best values. 162 vis.clear(); 163 boost::maximum_adjacency_search(g, 164 boost::vertex_assignment_map(assignments). 165 weight_map(weights). 166 visitor(vis). 167 root_vertex(bestStart). 168 max_priority_queue(pq)); 169 170 return bestW; 171 } 172 } // end `namespace detail` within `namespace boost` 173 174 template <class UndirectedGraph, class WeightMap, class ParityMap, class VertexAssignmentMap, class KeyedUpdatablePriorityQueue> 175 typename boost::property_traits<WeightMap>::value_type 176 stoer_wagner_min_cut(const UndirectedGraph& g, WeightMap weights, ParityMap parities, VertexAssignmentMap assignments, KeyedUpdatablePriorityQueue& pq) { 141 177 BOOST_CONCEPT_ASSERT((boost::IncidenceGraphConcept<UndirectedGraph>)); 142 178 BOOST_CONCEPT_ASSERT((boost::VertexListGraphConcept<UndirectedGraph>)); 143 179 typedef typename boost::graph_traits<UndirectedGraph>::vertex_descriptor vertex_descriptor; … … 151 187 BOOST_CONCEPT_ASSERT((boost::ReadWritePropertyMapConcept<VertexAssignmentMap, vertex_descriptor>)); 152 188 BOOST_CONCEPT_ASSERT((boost::Convertible<vertex_descriptor, typename boost::property_traits<VertexAssignmentMap>::value_type>)); 153 189 BOOST_CONCEPT_ASSERT((boost::KeyedUpdatableQueueConcept<KeyedUpdatablePriorityQueue>)); 154 190 155 191 vertices_size_type n = num_vertices(g); 156 192 if (n < 2) 157 193 throw boost::bad_graph("the input graph must have at least two vertices."); 158 194 else if (!pq.empty()) 159 195 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); 196 197 return detail::stoer_wagner_min_cut(g, weights, 198 parities, assignments, pq); 199 } 200 201 namespace graph { 202 namespace detail { 203 template <class UndirectedGraph, class WeightMap> 204 struct stoer_wagner_min_cut_impl { 205 typedef typename boost::property_traits<WeightMap>::value_type result_type; 206 template <typename ArgPack> 207 result_type operator() (const UndirectedGraph& g, WeightMap weights, const ArgPack& arg_pack) const { 208 using namespace boost::graph::keywords; 209 typedef typename boost::graph_traits<UndirectedGraph>::vertex_descriptor vertex_descriptor; 210 typedef typename std::vector<vertex_descriptor>::size_type heap_container_size_type; 211 typedef typename boost::property_traits<WeightMap>::value_type weight_type; 212 typedef typename boost::property_map<UndirectedGraph, boost::vertex_index_t>::type index_map; 213 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; 214 gen_type gen(choose_param(get_param(arg_pack, boost::distance_zero_t()), weight_type(0))); 215 typename boost::result_of<gen_type(const UndirectedGraph&, const ArgPack&)>::type pq = gen(g, arg_pack); 216 217 return boost::stoer_wagner_min_cut(g, 218 weights, 219 arg_pack[_parity_map | boost::make_one_bit_color_map<index_map>(num_vertices(g),get(boost::vertex_index, g))], 220 boost::detail::make_property_map_from_arg_pack_gen<boost::graph::keywords::tag::vertex_assignment_map, vertex_descriptor>(vertex_descriptor())(g, arg_pack), 221 pq 222 ); 166 223 } 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; 207 } 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 ); 224 }; 231 225 } 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 226 BOOST_GRAPH_MAKE_FORWARDING_FUNCTION(stoer_wagner_min_cut,2,3) 227 } 228 229 // Named parameter interface 230 BOOST_GRAPH_MAKE_OLD_STYLE_PARAMETER_FUNCTION(stoer_wagner_min_cut, 2) 231 239 232 } // end `namespace boost` 240 233 241 234 #include <boost/graph/iteration_macros_undef.hpp> -
libs/graph/doc/maximum_adjacency_search.html
1 <html> 2 <!-- 3 Copyright (c) Fernando Vilas 2012 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 tuple<typename graph_traits<Graph>::vertex_descriptor, 27 typename graph_traits<Graph>::vertex_descriptor, 28 unsigned long> 29 maximum_adjacency_search(const Graph& g, 30 const bgl_named_params<P, T, R>& params); 31 32 <i>// non-named parameter versions</i> 33 template <class Graph, class WeightMap, class MASVisitor> 34 tuple<typename graph_traits<Graph>::vertex_descriptor, 35 typename graph_traits<Graph>::vertex_descriptor, 36 unsigned long> 37 maximum_adjacency_search(const Graph& g, WeightMap weights, MASVisitor vis, 38 const typename graph_traits<Graph>::vertex_descriptor start); 39 40 </pre> 41 42 <p> 43 The <tt>maximum_adjacency_search()</tt> function performs a traversal 44 of the vertices in an undirected graph. The next vertex visited is the 45 vertex that has the most visited neighbors at any time. In the case of 46 an unweighted, undirected graph, the number of visited neighbors of the 47 very last vertex visited in the graph is also the number of edge-disjoint 48 paths between that vertex and the next-to-last vertex visited. 49 </p> 50 51 <p> 52 The <tt>maximum_adjacency_search()</tt> function invokes user-defined 53 actions at certain event-points within the algorithm. This provides a 54 mechanism for adapting the generic MAS algorithm to the many situations 55 in which it can be used. In the pseudo-code below, the event points 56 for MAS are the labels on the right. The user-defined actions must be 57 provided in the form of a visitor object, that is, an object whose type 58 meets the requirements for a MAS Visitor. 59 </p> 60 61 <table> 62 <tr> 63 <td valign="top"> 64 <pre> 65 MAS(<i>G</i>) 66 <b>for</b> each vertex <i>u in V</i> 67 <i>reach_count[u] := 0</i> 68 <b>end for</b> 69 // for the starting vertex s 70 <i>reach_count[s] := 1</i> 71 <b>for</b> each unvisited vertex <i>u in V</i> 72 <b>call</b> MAS-VISIT(<i>G</i>, <i>u</i>) 73 remove u from the list on unvisited vertices 74 <b>for</b> each out edge from <i>u</i> to <i>t</i> 75 <b>if</b> <i>t</i> has not yet been visited 76 increment <i>reach_count[t]</i> 77 <b>end if</b> 78 <b>end for</b> each out edge 79 <b>call</b> MAS-VISIT(<i>G</i>, <i>u</i>) 80 <b>end for</b> each unvisited vertex 81 <pre> 82 </td> 83 <td valign="top"> 84 <pre> 85 - 86 - 87 initialize vertex <i>u</i> 88 - 89 - 90 - 91 - 92 examine vertex <i>u</i> 93 - 94 examine edge <i>(u,t)</i> 95 - 96 - 97 - 98 - 99 finish vertex <i>u</i> 100 - 101 </pre> 102 </td> 103 </tr> 104 </table> 105 106 <h3>Where Defined</h3> 107 108 <p> 109 <a href="../../../boost/graph/maximum_adjacency_search.hpp"><tt>boost/graph/maximum_adjacency_search.hpp</tt></a></p> 110 111 <h3>Parameters</h3> 112 113 IN: <tt>const UndirectedGraph& g</tt></p> 114 <blockquote> 115 A connected, directed graph. The graph type must 116 be a model of <a href="./IncidenceGraph.html">Incidence Graph</a> 117 and <a href="./VertexListGraph.html">Vertex List Graph</a>.<br> 118 </blockquote> 119 120 <h3>Named Parameters</h3> 121 122 <p>IN: <tt>WeightMap weights</tt></p> 123 <blockquote> 124 The weight or length of each edge in the graph. The 125 <tt>WeightMap</tt> type must be a model of 126 <a href="../../property_map/doc/ReadablePropertyMap.html">Readable 127 Property Map</a> and its value type must be <a class="external" 128 href="http://www.sgi.com/tech/stl/LessThanComparable.html"> 129 Less Than Comparable</a> and summable. The key type of this map 130 needs to be the graph's edge descriptor type. 131 <b>Default:</b> <tt>get(edge_weight, g)</tt><br> 132 </blockquote> 133 134 IN: <tt>visitor(MASVisitor vis)</tt></p> 135 <blockquote> 136 A visitor object that is invoked inside the algorithm at the 137 event-points specified by the MAS Visitor concept. The visitor 138 object is passed by value <a href="#1">[1]</a>. <br> 139 <b>Default:</b> <tt>mas_visitor<null_visitor></tt><br> 140 </blockquote> 141 142 IN: <tt>root_vertex(typename 143 graph_traits<VertexListGraph>::vertex_descriptor start)</tt></p> 144 <blockquote> 145 This specifies the vertex that the depth-first search should 146 originate from. The type is the type of a vertex descriptor for the 147 given graph.<br> 148 <b>Default:</b> <tt>*vertices(g).first</tt><br> 149 </blockquote> 150 151 <h4>Expert Parameters</h4> 152 153 <p>IN: <tt>vertex_index_map(VertexIndexMap vertexIndices)</tt> </p> 154 <blockquote> 155 This maps each vertex to an integer in the range 156 [0, <tt>num_vertices(g)</tt>). This is only necessary if the default is 157 used for the assignment, index-in-heap, or distance maps. 158 <tt>VertexIndexMap</tt> must be a model of <a 159 href="../../property_map/doc/ReadablePropertyMap.html">Readable Property 160 Map</a>. The value type of the map must be an integer type. The 161 key type must be the graph's vertex descriptor type.<br> 162 <b>Default:</b> <tt>get(boost::vertex_index, g)</tt> 163 Note: if you use this default, make sure your graph has 164 an internal <tt>vertex_index</tt> property. For example, 165 <tt>adjacency_list</tt> with <tt>VertexList=listS</tt> does 166 not have an internal <tt>vertex_index</tt> property. 167 </blockquote> 168 169 <p>UTIL: <tt>vertex_assignment_map(AssignmentMap assignments)</tt></p> 170 <blockquote> 171 <tt>AssignmentMap</tt> must be a model of <a 172 href="../../property_map/doc/ReadWritePropertyMap.html">Read/Write Property 173 Map</a>. The key and value types must be the graph's vertex descriptor 174 type.<br> 175 <b>Default:</b> A <tt>boost::iterator_property_map</tt> using a 176 <tt>std::vector</tt> of <tt>num_vertices(g)</tt> vertex descriptors and 177 <tt>vertexIndices</tt> for the index map. 178 </blockquote> 179 180 <p>UTIL: <tt>max_priority_queue(MaxPriorityQueue& pq)</tt></p> 181 <blockquote> 182 <tt>MaxPriorityQueue</tt> must be a model of <a 183 href="./KeyedUpdatableQueue.html">Keyed Updatable Queue</a> and a 184 max-<a href="./UpdatableQueue.html#concept%3AUpdatablePriorityQueue"> 185 Updatable Priority Queue</a>. The value type must be the graph's vertex 186 descriptor and the key type must be the weight type. 187 <b>Default:</b> A <tt>boost::d_ary_heap_indirect</tt> using a default 188 index-in-heap and distance map. 189 </blockquote> 190 191 <p>UTIL: <tt>index_in_heap_map(IndexInHeapMap indicesInHeap)</tt></p> 192 <blockquote> 193 This parameter only has an effect when the default max-priority queue is used.<br> 194 <tt>IndexInHeapMap</tt> must be a model of <a 195 href="../../property_map/doc/ReadWritePropertyMap.html">Read/Write Property 196 Map</a>. The key type must be the graph's vertex descriptor type. The 197 value type must be a size type 198 (<tt>typename std::vector<vertex_descriptor>::size_type</tt>).<br> 199 <b>Default:</b> A <tt>boost::iterator_property_map</tt> using a 200 <tt>std::vector</tt> of <tt>num_vertices(g)</tt> size type objects and 201 <tt>vertexIndices</tt> for the index map. 202 </blockquote> 203 204 <p>UTIL: <tt>distance_map(DistanceMap wAs)</tt></p> 205 <blockquote> 206 This parameter only has an effect when the default max-priority queue is used.<br> 207 <tt>DistanceMap</tt> must be a model of <a 208 href="../../property_map/doc/ReadWritePropertyMap.html">Read/Write Property 209 Map</a>. The key type must be the graph's vertex descriptor type. The 210 value type must be the weight type 211 (<tt>typename boost::property_traits<WeightMap>::value_type</tt>). 212 <br> 213 <b>Default:</b> A <tt>boost::iterator_property_map</tt> using a 214 <tt>std::vector</tt> of <tt>num_vertices(g)</tt> weight type objects 215 and <tt>vertexIndices</tt> for the index map. 216 </blockquote> 217 218 <h3>Returns</h3> 219 <p>The last 2 vertices visited, and the priority of the last vertex when 220 removed. In an unweighted, undirected graph, this is the number of 221 edge-disjoint paths between these 2 vertices.</p> 222 223 <h3>Throws</h3> 224 225 <p><tt>bad_graph</tt> 226 <blockquote> 227 If <tt>num_vertices(g)</tt> is less than 2 228 </blockquote></p> 229 230 <p><tt>std::invalid_argument</tt> 231 <blockquote> 232 If a max-priority queue is given as an argument and it is not empty 233 </blockquote>. 234 235 <h3><a name="SECTION001340300000000000000"> 236 Complexity</a> 237 </h3> 238 239 <p> 240 The time complexity is <i>O(E + V)</i>. 241 </p> 242 243 <h3>References</h3> 244 <ul> 245 <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> 246 </li> 247 </ul> 248 249 <h3>Visitor Event Points</h3> 250 251 <ul> 252 <li><b><tt>vis.initialize_vertex(s, g)</tt></b> is invoked on every 253 vertex of the graph before the start of the graph search.</li> 254 255 <li><b><tt>vis.start_vertex(s, g)</tt></b> is invoked on the source 256 vertex once before processing its out edges.</li> 257 258 <li><b><tt>vis.examine_edge(e, g)</tt></b> is invoked on every out-edge 259 of each vertex after it is started.</li> 260 261 <li><b><tt>vis.finish_vertex(u, g)</tt></b> is invoked on a vertex after 262 all of its out edges have been examined and the reach counts of the 263 unvisited targets have been updated.</li> 264 </ul> 265 266 <h3>Notes</h3> 267 268 <p><a name="1">[1]</a> 269 Since the visitor parameter is passed by value, if your visitor 270 contains state then any changes to the state during the algorithm 271 will be made to a copy of the visitor object, not the visitor object 272 passed in. Therefore you may want the visitor to hold this state by 273 pointer or reference.</p> 274 275 <hr> 276 <table> 277 <tr valign=top> 278 <td nowrap>Copyright © 2012</td><td> 279 Fernando Vilas 280 </td></tr></table> 281 282 </body> 283 </html>