random_spanning_tree.hpp 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  1. // Copyright 2010 The Trustees of Indiana University.
  2. // Distributed under the Boost Software License, Version 1.0.
  3. // (See accompanying file LICENSE_1_0.txt or copy at
  4. // http://www.boost.org/LICENSE_1_0.txt)
  5. // Authors: Jeremiah Willcock
  6. // Andrew Lumsdaine
  7. #ifndef BOOST_GRAPH_RANDOM_SPANNING_TREE_HPP
  8. #define BOOST_GRAPH_RANDOM_SPANNING_TREE_HPP
  9. #include <vector>
  10. #include <boost/assert.hpp>
  11. #include <boost/graph/loop_erased_random_walk.hpp>
  12. #include <boost/graph/random.hpp>
  13. #include <boost/graph/iteration_macros.hpp>
  14. #include <boost/property_map/property_map.hpp>
  15. #include <boost/config.hpp>
  16. #include <boost/graph/graph_traits.hpp>
  17. #include <boost/graph/graph_concepts.hpp>
  18. #include <boost/graph/properties.hpp>
  19. #include <boost/graph/named_function_params.hpp>
  20. namespace boost
  21. {
  22. namespace detail
  23. {
  24. // Use Wilson's algorithm (based on loop-free random walks) to generate a
  25. // random spanning tree. The distribution of edges used is controlled by
  26. // the next_edge() function, so this version allows either weighted or
  27. // unweighted selection of trees.
  28. // Algorithm is from http://en.wikipedia.org/wiki/Uniform_spanning_tree
  29. template < typename Graph, typename PredMap, typename ColorMap,
  30. typename NextEdge >
  31. void random_spanning_tree_internal(const Graph& g,
  32. typename graph_traits< Graph >::vertex_descriptor s, PredMap pred,
  33. ColorMap color, NextEdge next_edge)
  34. {
  35. typedef
  36. typename graph_traits< Graph >::vertex_descriptor vertex_descriptor;
  37. BOOST_ASSERT(num_vertices(g)
  38. >= 1); // g must also be undirected (or symmetric) and connected
  39. typedef color_traits< typename property_traits< ColorMap >::value_type >
  40. color_gen;
  41. BGL_FORALL_VERTICES_T(v, g, Graph) put(color, v, color_gen::white());
  42. std::vector< vertex_descriptor > path;
  43. put(color, s, color_gen::black());
  44. put(pred, s, graph_traits< Graph >::null_vertex());
  45. BGL_FORALL_VERTICES_T(v, g, Graph)
  46. {
  47. if (get(color, v) != color_gen::white())
  48. continue;
  49. loop_erased_random_walk(g, v, next_edge, color, path);
  50. for (typename std::vector<
  51. vertex_descriptor >::const_reverse_iterator i
  52. = path.rbegin();
  53. boost::next(i)
  54. != (typename std::vector<
  55. vertex_descriptor >::const_reverse_iterator)path.rend();
  56. ++i)
  57. {
  58. typename std::vector<
  59. vertex_descriptor >::const_reverse_iterator j
  60. = i;
  61. ++j;
  62. BOOST_ASSERT(get(color, *j) == color_gen::gray());
  63. put(color, *j, color_gen::black());
  64. put(pred, *j, *i);
  65. }
  66. }
  67. }
  68. }
  69. // Compute a uniformly-distributed spanning tree on a graph. Use Wilson's
  70. // algorithm:
  71. // @inproceedings{wilson96generating,
  72. // author = {Wilson, David Bruce},
  73. // title = {Generating random spanning trees more quickly than the cover
  74. // time}, booktitle = {STOC '96: Proceedings of the twenty-eighth annual ACM
  75. // symposium on Theory of computing}, year = {1996}, isbn = {0-89791-785-5},
  76. // pages = {296--303},
  77. // location = {Philadelphia, Pennsylvania, United States},
  78. // doi = {http://doi.acm.org/10.1145/237814.237880},
  79. // publisher = {ACM},
  80. // address = {New York, NY, USA},
  81. // }
  82. //
  83. template < typename Graph, typename Gen, typename PredMap, typename ColorMap >
  84. void random_spanning_tree(const Graph& g, Gen& gen,
  85. typename graph_traits< Graph >::vertex_descriptor root, PredMap pred,
  86. static_property_map< double >, ColorMap color)
  87. {
  88. unweighted_random_out_edge_gen< Graph, Gen > random_oe(gen);
  89. detail::random_spanning_tree_internal(g, root, pred, color, random_oe);
  90. }
  91. // Compute a weight-distributed spanning tree on a graph.
  92. template < typename Graph, typename Gen, typename PredMap, typename WeightMap,
  93. typename ColorMap >
  94. void random_spanning_tree(const Graph& g, Gen& gen,
  95. typename graph_traits< Graph >::vertex_descriptor root, PredMap pred,
  96. WeightMap weight, ColorMap color)
  97. {
  98. weighted_random_out_edge_gen< Graph, WeightMap, Gen > random_oe(
  99. weight, gen);
  100. detail::random_spanning_tree_internal(g, root, pred, color, random_oe);
  101. }
  102. template < typename Graph, typename Gen, typename P, typename T, typename R >
  103. void random_spanning_tree(
  104. const Graph& g, Gen& gen, const bgl_named_params< P, T, R >& params)
  105. {
  106. using namespace boost::graph::keywords;
  107. typedef bgl_named_params< P, T, R > params_type;
  108. BOOST_GRAPH_DECLARE_CONVERTED_PARAMETERS(params_type, params)
  109. typedef typename graph_traits< Graph >::vertex_descriptor vertex_descriptor;
  110. vertex_descriptor default_vertex = *vertices(g).first;
  111. vertex_descriptor start_vertex = arg_pack[_root_vertex | default_vertex];
  112. typename boost::parameter::binding< arg_pack_type,
  113. boost::graph::keywords::tag::predecessor_map >::type pred_map
  114. = arg_pack[_predecessor_map];
  115. static_property_map< double > default_weight_map(1.);
  116. typename boost::parameter::value_type< arg_pack_type,
  117. boost::graph::keywords::tag::weight_map,
  118. static_property_map< double > >::type e_w_map
  119. = arg_pack[_weight_map | default_weight_map];
  120. typename boost::detail::map_maker< Graph, arg_pack_type,
  121. boost::graph::keywords::tag::color_map,
  122. boost::default_color_type >::map_type c_map
  123. = boost::detail::make_color_map_from_arg_pack(g, arg_pack);
  124. random_spanning_tree(g, gen, start_vertex, pred_map, e_w_map, c_map);
  125. }
  126. }
  127. #include <boost/graph/iteration_macros_undef.hpp>
  128. #endif // BOOST_GRAPH_RANDOM_SPANNING_TREE_HPP