Index: boost/graph/maximum_adjacency_search.hpp =================================================================== --- boost/graph/maximum_adjacency_search.hpp (revision 0) +++ boost/graph/maximum_adjacency_search.hpp (working copy) @@ -0,0 +1,267 @@ +// +//======================================================================= +// Copyright 2012 Fernando Vilas +// 2010 Daniel Trebbien +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +//======================================================================= +// + +// The maximum adjacency search algorithm was originally part of the +// Stoer-Wagner min cut implementation by Daniel Trebbien. It has been +// broken out into its own file to be a public search algorithm, with +// visitor concepts. +#ifndef BOOST_GRAPH_MAXIMUM_ADJACENCY_SEARCH_H +#define BOOST_GRAPH_MAXIMUM_ADJACENCY_SEARCH_H + +/** + * This is an implementation of the maximum adjacency search on an + * undirected graph. It allows a visitor object to perform some + * operation on each vertex as that vertex is visited. + * + * The algorithm runs as follows: + * + * Initialize all nodes to be unvisited (reach count = 0) + * and call vis.initialize_vertex + * For i = number of nodes in graph downto 1 + * Select the unvisited node with the highest reach count + * The user provides the starting node to break the first tie, + * but future ties are broken arbitrarily + * Visit the node by calling vis.start_vertex + * Increment the reach count for all unvisited neighbors + * and call vis.examine_edge for each of these edges + * Mark the node as visited and call vis.finish_vertex + * + * The algorithm returns the last 2 vertices visited (s and t), and + * the key from the priority queue of the last vertex (t) when + * removed. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +namespace boost { +template +struct MASVisitorConcept { + void constraints() { + boost::function_requires< boost::CopyConstructibleConcept >(); + vis.initialize_vertex(u, g); + vis.start_vertex(u, g); + vis.examine_edge(e, g); + vis.finish_vertex(u, g); + } + Visitor vis; + Graph g; + typename boost::graph_traits::vertex_descriptor u; + typename boost::graph_traits::edge_descriptor e; +}; + +template +class mas_visitor { +public: + mas_visitor() { } + mas_visitor(Visitors vis) : m_vis(vis) { } + + template + void + initialize_vertex(Vertex u, Graph& g) + { + invoke_visitors(m_vis, u, g, ::boost::on_initialize_vertex()); + } + + template + void + start_vertex(Vertex u, Graph& g) + { + invoke_visitors(m_vis, u, g, ::boost::on_start_vertex()); + } + + template + void + examine_edge(Edge e, Graph& g) + { + invoke_visitors(m_vis, e, g, ::boost::on_examine_edge()); + } + + template + void + finish_vertex(Vertex u, Graph& g) + { + invoke_visitors(m_vis, u, g, ::boost::on_finish_vertex()); + } + + BOOST_GRAPH_EVENT_STUB(on_initialize_vertex,mas) + BOOST_GRAPH_EVENT_STUB(on_start_vertex,mas) + BOOST_GRAPH_EVENT_STUB(on_examine_edge,mas) + BOOST_GRAPH_EVENT_STUB(on_finish_vertex,mas) + +protected: + Visitors m_vis; +}; +template +mas_visitor +make_mas_visitor(Visitors vis) { + return mas_visitor(vis); +} +typedef mas_visitor<> default_mas_visitor; + +namespace detail { + template + boost::tuple::vertex_descriptor, typename boost::graph_traits::vertex_descriptor, typename KeyedUpdatablePriorityQueue::key_type> + maximum_adjacency_search(const Graph& g, WeightMap weights, MASVisitor vis, const typename boost::graph_traits::vertex_descriptor start, VertexAssignmentMap assignments, KeyedUpdatablePriorityQueue pq) { + typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; + typedef typename boost::graph_traits::vertices_size_type vertices_size_type; + typedef typename boost::graph_traits::edge_descriptor edge_descriptor; + typedef typename boost::property_traits::value_type weight_type; + + std::set assignedVertices; + + // initialize `assignments` (all vertices are initially + // assigned to themselves) + BGL_FORALL_VERTICES_T(v, g, Graph) { + put(assignments, v, v); + } + + typename KeyedUpdatablePriorityQueue::key_map keys = pq.keys(); + + // set number of visited neighbors for all vertices to 0 + BGL_FORALL_VERTICES_T(v, g, Graph) { + if (v == get(assignments, v)) { // foreach u \in V do + put(keys, v, weight_type(0)); vis.initialize_vertex(v, g); + + pq.push(v); + } + } + assert(pq.size() >= 2); + + // Give the starting vertex high priority + put(keys, start, get(keys, start) + num_vertices(g) + 1); + pq.update(start); + + // start traversing the graph + vertex_descriptor s, t; + weight_type w; + while (!pq.empty()) { // while PQ \neq {} do + const vertex_descriptor u = pq.top(); // u = extractmax(PQ) + w = get(keys, u); + pq.pop(); vis.start_vertex(u, g); + + // set s and t to the last and next-to-last vertices extracted + s = t; t = u; + + BGL_FORALL_OUTEDGES_T(u, e, g, Graph) { // foreach (u, v) \in E do + vis.examine_edge(e, g); + + const vertex_descriptor v = get(assignments, target(e, g)); + + if (pq.contains(v)) { // if v \in PQ then + put(keys, v, get(keys, v) + get(weights, e)); // increasekey(PQ, v, wA(v) + w(u, v)) + pq.update(v); + } + } + + typename std::set::const_iterator assignedVertexIt, assignedVertexEnd = assignedVertices.end(); + for (assignedVertexIt = assignedVertices.begin(); assignedVertexIt != assignedVertexEnd; ++assignedVertexIt) { + const vertex_descriptor uPrime = *assignedVertexIt; + + if (get(assignments, uPrime) == u) { + BGL_FORALL_OUTEDGES_T(uPrime, e, g, Graph) { // foreach (u, v) \in E do + vis.examine_edge(e, g); + + const vertex_descriptor v = get(assignments, target(e, g)); + + if (pq.contains(v)) { // if v \in PQ then + put(keys, v, get(keys, v) + get(weights, e)); // increasekey(PQ, v, wA(v) + w(u, v)) + pq.update(v); + } + } + } + } + vis.finish_vertex(u, g); + } + return boost::make_tuple(s,t,w); + } +} // end namespace detail + + template + boost::tuple::vertex_descriptor, typename boost::graph_traits::vertex_descriptor, typename KeyedUpdatablePriorityQueue::key_type> +maximum_adjacency_search(const Graph& g, WeightMap weights, MASVisitor vis, const typename boost::graph_traits::vertex_descriptor start, VertexAssignmentMap assignments, KeyedUpdatablePriorityQueue pq) { + BOOST_CONCEPT_ASSERT((boost::IncidenceGraphConcept)); + BOOST_CONCEPT_ASSERT((boost::VertexListGraphConcept)); + typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; + typedef typename boost::graph_traits::vertices_size_type vertices_size_type; + typedef typename boost::graph_traits::edge_descriptor edge_descriptor; + BOOST_CONCEPT_ASSERT((boost::Convertible::directed_category, boost::undirected_tag>)); + BOOST_CONCEPT_ASSERT((boost::ReadablePropertyMapConcept)); + typedef typename boost::property_traits::value_type weight_type; + boost::function_requires< MASVisitorConcept >(); + BOOST_CONCEPT_ASSERT((boost::ReadWritePropertyMapConcept)); + BOOST_CONCEPT_ASSERT((boost::Convertible::value_type>)); + BOOST_CONCEPT_ASSERT((boost::KeyedUpdatableQueueConcept)); + + vertices_size_type n = num_vertices(g); + if (n < 2) + throw boost::bad_graph("the input graph must have at least two vertices."); + else if (!pq.empty()) + throw std::invalid_argument("the max-priority queue must be empty initially."); + + return detail::maximum_adjacency_search(g, weights, + vis, start, + assignments, pq); +} + +namespace graph { + namespace detail { + template + struct maximum_adjacency_search_impl { + + typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; + + //TODO: This assumes that the weight map has edge_weight_t values in it. + // If this is not true, it may fail to compile. We should really rely on + // the ArgPack, but the named parameter macros require a result_type. + // Can this be fixed? + typedef typename boost::tuple::type>::value_type> + result_type; + + template + result_type + operator() (const Graph& g, const ArgPack& arg_pack) const { + using namespace boost::graph::keywords; + typedef typename std::vector::size_type heap_container_size_type; + typedef typename parameter::value_type::type >::type WeightMap; + typedef typename boost::property_traits::value_type weight_type; + + return boost::maximum_adjacency_search + (g, + arg_pack[_weight_map | get(edge_weight, g)], + arg_pack[_visitor | make_mas_visitor(null_visitor())], + arg_pack[_root_vertex | *vertices(g).first], + arg_pack[_vertex_assignment_map | boost::detail::make_property_map_from_arg_pack_gen(vertex_descriptor())(g, arg_pack)], + unwrap_ref(arg_pack[_max_priority_queue | boost::detail::make_priority_queue_from_arg_pack_gen >(choose_param(get_param(arg_pack, boost::distance_zero_t()), weight_type(0)))(g, arg_pack)])); + } + }; + } + BOOST_GRAPH_MAKE_FORWARDING_FUNCTION(maximum_adjacency_search,1,5) +} + // Named parameter interface + BOOST_GRAPH_MAKE_OLD_STYLE_PARAMETER_FUNCTION(maximum_adjacency_search, 1) + +} // end namespace boost + +#include + +#endif // BOOST_GRAPH_MAXIMUM_ADJACENCY_SEARCH_H Index: boost/graph/stoer_wagner_min_cut.hpp =================================================================== --- boost/graph/stoer_wagner_min_cut.hpp (revision 80811) +++ boost/graph/stoer_wagner_min_cut.hpp (working copy) @@ -15,104 +15,91 @@ #include #include #include -#include +#include #include #include #include #include #include +#include namespace boost { - + namespace detail { - - /** - * \brief Performs a phase of the Stoer-Wagner min-cut algorithm - * - * Performs a phase of the Stoer-Wagner min-cut algorithm. - * - * As described by Stoer & Wagner (1997), a phase is simply a maximum adjacency search - * (also called a maximum cardinality search), which results in the selection of two vertices - * \em s and \em t, and, as a side product, a minimum s-t cut of - * the input graph. Here, the input graph is basically \p g, but some vertices are virtually - * assigned to others as a way of viewing \p g as a graph with some sets of - * vertices merged together. - * - * This implementation is a translation of pseudocode by Professor Uri Zwick, - * School of Computer Science, Tel Aviv University. - * - * \pre \p g is a connected, undirected graph - * \param[in] g the input graph - * \param[in] assignments a read/write property map from each vertex to the vertex that it is assigned to - * \param[in] assignedVertices a list of vertices that are assigned to others - * \param[in] weights a readable property map from each edge to its weight (a non-negative value) - * \param[out] pq a keyed, updatable max-priority queue - * \returns a tuple (\em s, \em t, \em w) of the "s" and "t" - * of the minimum s-t cut and the cut weight \em w - * of the minimum s-t cut. - * \see http://www.cs.tau.ac.il/~zwick/grad-algo-08/gmc.pdf - * - * \author Daniel Trebbien - * \date 2010-09-11 - */ - template - boost::tuple::vertex_descriptor, typename boost::graph_traits::vertex_descriptor, typename boost::property_traits::value_type> - stoer_wagner_phase(const UndirectedGraph& g, VertexAssignmentMap assignments, const std::set::vertex_descriptor>& assignedVertices, WeightMap weights, KeyedUpdatablePriorityQueue& pq) { - typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; - typedef typename boost::property_traits::value_type weight_type; - - BOOST_ASSERT(pq.empty()); - typename KeyedUpdatablePriorityQueue::key_map keys = pq.keys(); - - BGL_FORALL_VERTICES_T(v, g, UndirectedGraph) { - if (v == get(assignments, v)) { // foreach u \in V do - put(keys, v, weight_type(0)); - - pq.push(v); + template < typename ParityMap, typename WeightType, typename WeightMap > + class mas_min_cut_visitor : public boost::default_mas_visitor { + public: + mas_min_cut_visitor(ParityMap parity, + WeightType& cutweight, + const WeightMap& weight_map) + : m_bestParity(parity), + m_parity(parity), + m_bestWeight(cutweight), + m_cutweight(0), + m_visited(0), + m_weightMap(weight_map) + { + // set here since the init list sets the reference + m_bestWeight = (std::numeric_limits::max)(); + + // reallocate the parity map since it is for internal + // bookkeeping here only. + // TODO: specific to one-bit color map. make it not depend on that. + m_parity.data.reset(new unsigned char[(m_parity.n + m_parity.bits_per_char - 1) / m_parity.bits_per_char]); + } + + template < typename Vertex, typename Graph > + void initialize_vertex(Vertex u, const Graph & g) + { + typedef typename boost::property_traits::value_type parity_type; + put(m_parity, u, parity_type(0)); + put(m_bestParity, u, parity_type(0)); + } + + template < typename Edge, typename Graph > + void examine_edge(Edge e, const Graph & g) + { + WeightType w = get(m_weightMap, e); + + // if the target of e is already marked then decrease cutweight + // otherwise, increase it + if (get(m_parity, boost::target(e, g))) { + m_cutweight -= w; + } else { + m_cutweight += w; } } - - BOOST_ASSERT(pq.size() >= 2); - - vertex_descriptor s = boost::graph_traits::null_vertex(); - vertex_descriptor t = boost::graph_traits::null_vertex(); - weight_type w; - while (!pq.empty()) { // while PQ \neq {} do - const vertex_descriptor u = pq.top(); // u = extractmax(PQ) - w = get(keys, u); - pq.pop(); - - s = t; t = u; - - BGL_FORALL_OUTEDGES_T(u, e, g, UndirectedGraph) { // foreach (u, v) \in E do - const vertex_descriptor v = get(assignments, target(e, g)); - - if (pq.contains(v)) { // if v \in PQ then - put(keys, v, get(keys, v) + get(weights, e)); // increasekey(PQ, v, wA(v) + w(u, v)) - pq.update(v); + + template < typename Vertex, typename Graph > + void finish_vertex(Vertex u, const Graph & g) + { + typedef typename boost::property_traits::value_type parity_type; + ++m_visited; + put(m_parity, u, parity_type(1)); + + if (m_cutweight < m_bestWeight && m_visited < num_vertices(g)) { + m_bestWeight = m_cutweight; + BGL_FORALL_VERTICES_T(i, g, Graph) { + put(m_bestParity,i, get(m_parity,i)); } } - - typename std::set::const_iterator assignedVertexIt, assignedVertexEnd = assignedVertices.end(); - for (assignedVertexIt = assignedVertices.begin(); assignedVertexIt != assignedVertexEnd; ++assignedVertexIt) { - const vertex_descriptor uPrime = *assignedVertexIt; - - if (get(assignments, uPrime) == u) { - BGL_FORALL_OUTEDGES_T(uPrime, e, g, UndirectedGraph) { // foreach (u, v) \in E do - const vertex_descriptor v = get(assignments, target(e, g)); - - if (pq.contains(v)) { // if v \in PQ then - put(keys, v, get(keys, v) + get(weights, e)); // increasekey(PQ, v, wA(v) + w(u, v)) - pq.update(v); - } - } - } - } } - - return boost::make_tuple(s, t, w); - } - + + inline void clear() { + m_bestWeight = (std::numeric_limits::max)(); + m_visited = 0; + m_cutweight = 0; + } + + private: + ParityMap m_bestParity; + ParityMap m_parity; + WeightType & m_bestWeight; + WeightType m_cutweight; + unsigned m_visited; + const WeightMap& m_weightMap; + }; + /** * \brief Computes a min-cut of the input graph * @@ -137,7 +124,55 @@ */ template typename boost::property_traits::value_type stoer_wagner_min_cut(const UndirectedGraph& g, WeightMap weights, ParityMap parities, VertexAssignmentMap assignments, KeyedUpdatablePriorityQueue& pq) { + typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; + typedef typename boost::graph_traits::vertices_size_type vertices_size_type; + typedef typename boost::graph_traits::edge_descriptor edge_descriptor; + typedef typename boost::property_traits::value_type weight_type; + typedef typename boost::property_traits::value_type parity_type; + + typename graph_traits::vertex_iterator u_iter, u_end; + + weight_type bestW = (std::numeric_limits::max)(); + weight_type bestThisTime = (std::numeric_limits::max)(); + vertex_descriptor bestStart; + + detail::mas_min_cut_visitor + vis(parities, bestThisTime, weights); + + // for each node in the graph, + for (boost::tie(u_iter, u_end) = vertices(g); u_iter != u_end; ++u_iter) { + // run the MAS and find the min cut + vis.clear(); + boost::maximum_adjacency_search(g, + boost::vertex_assignment_map(assignments). + weight_map(weights). + visitor(vis). + root_vertex(*u_iter). + max_priority_queue(pq)); + if (bestThisTime < bestW) { + bestW = bestThisTime; + bestStart = *u_iter; + } + } + + // Run one more time, starting from the best start location, to + // ensure the visitor has the best values. + vis.clear(); + boost::maximum_adjacency_search(g, + boost::vertex_assignment_map(assignments). + weight_map(weights). + visitor(vis). + root_vertex(bestStart). + max_priority_queue(pq)); + + return bestW; + } + } // end `namespace detail` within `namespace boost` + + template + typename boost::property_traits::value_type + stoer_wagner_min_cut(const UndirectedGraph& g, WeightMap weights, ParityMap parities, VertexAssignmentMap assignments, KeyedUpdatablePriorityQueue& pq) { BOOST_CONCEPT_ASSERT((boost::IncidenceGraphConcept)); BOOST_CONCEPT_ASSERT((boost::VertexListGraphConcept)); typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; @@ -151,91 +186,48 @@ BOOST_CONCEPT_ASSERT((boost::ReadWritePropertyMapConcept)); BOOST_CONCEPT_ASSERT((boost::Convertible::value_type>)); BOOST_CONCEPT_ASSERT((boost::KeyedUpdatableQueueConcept)); - + vertices_size_type n = num_vertices(g); if (n < 2) throw boost::bad_graph("the input graph must have at least two vertices."); else if (!pq.empty()) throw std::invalid_argument("the max-priority queue must be empty initially."); - - std::set assignedVertices; - - // initialize `assignments` (all vertices are initially assigned to themselves) - BGL_FORALL_VERTICES_T(v, g, UndirectedGraph) { - put(assignments, v, v); + + return detail::stoer_wagner_min_cut(g, weights, + parities, assignments, pq); + } + +namespace graph { + namespace detail { + template + struct stoer_wagner_min_cut_impl { + typedef typename boost::property_traits::value_type result_type; + template + result_type operator() (const UndirectedGraph& g, WeightMap weights, const ArgPack& arg_pack) const { + using namespace boost::graph::keywords; + typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; + typedef typename std::vector::size_type heap_container_size_type; + typedef typename boost::property_traits::value_type weight_type; + typedef typename boost::property_map::type index_map; + typedef boost::detail::make_priority_queue_from_arg_pack_gen > gen_type; + gen_type gen(choose_param(get_param(arg_pack, boost::distance_zero_t()), weight_type(0))); + typename boost::result_of::type pq = gen(g, arg_pack); + + return boost::stoer_wagner_min_cut(g, + weights, + arg_pack[_parity_map | boost::make_one_bit_color_map(num_vertices(g),get(boost::vertex_index, g))], + boost::detail::make_property_map_from_arg_pack_gen(vertex_descriptor())(g, arg_pack), + pq + ); } - - vertex_descriptor s, t; - weight_type bestW; - - boost::tie(s, t, bestW) = boost::detail::stoer_wagner_phase(g, assignments, assignedVertices, weights, pq); - BOOST_ASSERT(s != t); - BGL_FORALL_VERTICES_T(v, g, UndirectedGraph) { - put(parities, v, parity_type(v == t ? 1 : 0)); - } - put(assignments, t, s); - assignedVertices.insert(t); - --n; - - for (; n >= 2; --n) { - weight_type w; - boost::tie(s, t, w) = boost::detail::stoer_wagner_phase(g, assignments, assignedVertices, weights, pq); - BOOST_ASSERT(s != t); - - if (w < bestW) { - BGL_FORALL_VERTICES_T(v, g, UndirectedGraph) { - put(parities, v, parity_type(get(assignments, v) == t ? 1 : 0)); - - if (get(assignments, v) == t) // all vertices that were assigned to t are now assigned to s - put(assignments, v, s); - } - - bestW = w; - } else { - BGL_FORALL_VERTICES_T(v, g, UndirectedGraph) { - if (get(assignments, v) == t) // all vertices that were assigned to t are now assigned to s - put(assignments, v, s); - } - } - put(assignments, t, s); - assignedVertices.insert(t); - } - - BOOST_ASSERT(pq.empty()); - - return bestW; - } - - } // end `namespace detail` within `namespace boost` - - template - inline typename boost::property_traits::value_type - stoer_wagner_min_cut(const UndirectedGraph& g, WeightMap weights, const boost::bgl_named_params& params) { - typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; - typedef typename std::vector::size_type heap_container_size_type; - typedef typename boost::property_traits::value_type weight_type; - - typedef boost::bgl_named_params params_type; - BOOST_GRAPH_DECLARE_CONVERTED_PARAMETERS(params_type, params) - - typedef boost::detail::make_priority_queue_from_arg_pack_gen > gen_type; - gen_type gen(choose_param(get_param(params, boost::distance_zero_t()), weight_type(0))); - typename boost::result_of::type pq = gen(g, arg_pack); - - return boost::detail::stoer_wagner_min_cut(g, - weights, - choose_param(get_param(params, boost::parity_map_t()), boost::dummy_property_map()), - boost::detail::make_property_map_from_arg_pack_gen(vertex_descriptor())(g, arg_pack), - pq - ); + }; } - - template - inline typename boost::property_traits::value_type - stoer_wagner_min_cut(const UndirectedGraph& g, WeightMap weights) { - return boost::stoer_wagner_min_cut(g, weights, boost::vertex_index_map(get(boost::vertex_index, g))); - } - + BOOST_GRAPH_MAKE_FORWARDING_FUNCTION(stoer_wagner_min_cut,2,3) +} + + // Named parameter interface + BOOST_GRAPH_MAKE_OLD_STYLE_PARAMETER_FUNCTION(stoer_wagner_min_cut, 2) + } // end `namespace boost` #include Index: libs/graph/doc/maximum_adjacency_search.html =================================================================== --- libs/graph/doc/maximum_adjacency_search.html (revision 0) +++ libs/graph/doc/maximum_adjacency_search.html (working copy) @@ -0,0 +1,283 @@ + + + +Boost Graph Library: Maximum Adjacency Search + +C++ Boost + +

+maximum_adjacency_search +

+ +

+

+// named parameter versions
+template <class Graph, class class P, class T, class R>
+tuple<typename graph_traits<Graph>::vertex_descriptor,
+      typename graph_traits<Graph>::vertex_descriptor,
+      unsigned long>
+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>
+tuple<typename graph_traits<Graph>::vertex_descriptor,
+      typename graph_traits<Graph>::vertex_descriptor,
+      unsigned long>
+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. +

+ +

+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

+

The last 2 vertices visited, and the priority of the last vertex when +removed. In an unweighted, undirected graph, this is the number of +edge-disjoint paths between these 2 vertices.

+ +

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