loop_erased_random_walk.hpp 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  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_LOOP_ERASED_RANDOM_WALK_HPP
  8. #define BOOST_GRAPH_LOOP_ERASED_RANDOM_WALK_HPP
  9. #include <boost/graph/graph_traits.hpp>
  10. #include <boost/graph/properties.hpp>
  11. #include <boost/graph/random.hpp>
  12. #include <boost/next_prior.hpp>
  13. #include <vector>
  14. #include <boost/assert.hpp>
  15. namespace boost {
  16. struct BOOST_SYMBOL_VISIBLE loop_erased_random_walk_stuck : public std::exception {
  17. virtual ~loop_erased_random_walk_stuck() throw() {}
  18. inline virtual const char* what() const throw() {
  19. return "Loop-erased random walk found a vertex with no out-edges";
  20. }
  21. };
  22. // Do a loop-erased random walk from vertex s to any vertex colored black (or
  23. // actually any color other than white or gray) in the color map. The color
  24. // white is for vertices that are not part of the path, while gray is for
  25. // those that are on the path (for cycle detection). The vector path is used
  26. // for temporary storage and as the result of the algorithm; while all
  27. // elements of the path except the last have their colors set to gray upon
  28. // return. Vertex s must start off colored white.
  29. //
  30. // Useful references:
  31. // http://everything2.com/title/loop-erased+random+walk
  32. // Wikipedia page on "Loop-Erased Random Walk"
  33. template <typename Graph, typename ColorMap, typename NextEdge>
  34. void loop_erased_random_walk(
  35. const Graph& g,
  36. typename boost::graph_traits<Graph>::vertex_descriptor s,
  37. NextEdge next_edge,
  38. ColorMap color,
  39. std::vector<typename boost::graph_traits<Graph>::vertex_descriptor>& path
  40. ) {
  41. typedef typename boost::graph_traits<Graph>::vertex_descriptor vertex_descriptor;
  42. typedef typename boost::graph_traits<Graph>::edge_descriptor edge_descriptor;
  43. typedef typename boost::property_traits<ColorMap>::value_type color_t;
  44. typedef boost::color_traits<color_t> color_gen;
  45. BOOST_ASSERT (get(color, s) == color_gen::white());
  46. path.clear();
  47. path.push_back(s);
  48. put(color, s, color_gen::gray());
  49. while (true) {
  50. edge_descriptor e = next_edge(s, g);
  51. vertex_descriptor t = target(e, g);
  52. color_t t_color = get(color, t);
  53. if (t_color == color_gen::white()) {
  54. path.push_back(t);
  55. put(color, t, color_gen::gray());
  56. s = t;
  57. } else if (t_color == color_gen::gray()) {
  58. // Found a loop; delete from path from the first occurrence of t to the
  59. // end, coloring vertices white.
  60. typename std::vector<vertex_descriptor>::iterator it = std::find(path.begin(), path.end(), t);
  61. BOOST_ASSERT (it != path.end());
  62. ++it;
  63. for (typename std::vector<vertex_descriptor>::iterator j = it; j != path.end(); ++j) {
  64. put(color, *j, color_gen::white());
  65. }
  66. path.erase(it, path.end());
  67. s = t;
  68. } else {
  69. // Done
  70. path.push_back(t);
  71. break;
  72. }
  73. }
  74. }
  75. template <typename Graph, typename Gen>
  76. class unweighted_random_out_edge_gen {
  77. Gen& gen;
  78. typedef boost::graph_traits<Graph> gt;
  79. public:
  80. unweighted_random_out_edge_gen(Gen& gen): gen(gen) {}
  81. typename gt::edge_descriptor
  82. operator()(typename gt::vertex_descriptor src, const Graph& g) const {
  83. if (out_degree(src, g) == 0) throw loop_erased_random_walk_stuck();
  84. return boost::random_out_edge(g, src, gen);
  85. }
  86. };
  87. template <typename Graph, typename WeightMap, typename Gen>
  88. class weighted_random_out_edge_gen {
  89. WeightMap weight;
  90. Gen& gen;
  91. typedef boost::graph_traits<Graph> gt;
  92. public:
  93. weighted_random_out_edge_gen(const WeightMap& weight, Gen& gen): weight(weight), gen(gen) {}
  94. typename gt::edge_descriptor
  95. operator()(typename gt::vertex_descriptor src, const Graph& g) const {
  96. if (out_degree(src, g) == 0) throw loop_erased_random_walk_stuck();
  97. return boost::weighted_random_out_edge(g, src, weight, gen);
  98. }
  99. };
  100. }
  101. #endif // BOOST_GRAPH_LOOP_ERASED_RANDOM_WALK_HPP