Chris@16
|
1 // Copyright 2004 The Trustees of Indiana University.
|
Chris@16
|
2
|
Chris@16
|
3 // Distributed under the Boost Software License, Version 1.0.
|
Chris@16
|
4 // (See accompanying file LICENSE_1_0.txt or copy at
|
Chris@16
|
5 // http://www.boost.org/LICENSE_1_0.txt)
|
Chris@16
|
6
|
Chris@16
|
7 // Authors: Douglas Gregor
|
Chris@16
|
8 // Andrew Lumsdaine
|
Chris@16
|
9 #ifndef BOOST_GRAPH_SMALL_WORLD_GENERATOR_HPP
|
Chris@16
|
10 #define BOOST_GRAPH_SMALL_WORLD_GENERATOR_HPP
|
Chris@16
|
11
|
Chris@16
|
12 #include <iterator>
|
Chris@16
|
13 #include <utility>
|
Chris@16
|
14 #include <boost/random/uniform_01.hpp>
|
Chris@16
|
15 #include <boost/random/uniform_int.hpp>
|
Chris@16
|
16
|
Chris@16
|
17 namespace boost {
|
Chris@16
|
18
|
Chris@16
|
19 // Assumes undirected
|
Chris@16
|
20 template<typename RandomGenerator, typename Graph>
|
Chris@16
|
21 class small_world_iterator
|
Chris@16
|
22 {
|
Chris@16
|
23 typedef typename graph_traits<Graph>::vertices_size_type
|
Chris@16
|
24 vertices_size_type;
|
Chris@16
|
25
|
Chris@16
|
26 public:
|
Chris@16
|
27 typedef std::input_iterator_tag iterator_category;
|
Chris@16
|
28 typedef std::pair<vertices_size_type, vertices_size_type> value_type;
|
Chris@16
|
29 typedef const value_type& reference;
|
Chris@16
|
30 typedef const value_type* pointer;
|
Chris@16
|
31 typedef void difference_type;
|
Chris@16
|
32
|
Chris@16
|
33 small_world_iterator() : gen(0) {}
|
Chris@16
|
34 small_world_iterator(RandomGenerator& gen, vertices_size_type n,
|
Chris@16
|
35 vertices_size_type k, double prob = 0.0,
|
Chris@16
|
36 bool allow_self_loops = false)
|
Chris@16
|
37 : gen(&gen), n(n), k(k), prob(prob), source(0),
|
Chris@16
|
38 target(allow_self_loops? 0 : 1),
|
Chris@16
|
39 allow_self_loops(allow_self_loops),
|
Chris@16
|
40 current(0, allow_self_loops? 0 : 1)
|
Chris@16
|
41 { }
|
Chris@16
|
42
|
Chris@16
|
43 reference operator*() const { return current; }
|
Chris@16
|
44 pointer operator->() const { return ¤t; }
|
Chris@16
|
45
|
Chris@16
|
46 small_world_iterator& operator++()
|
Chris@16
|
47 {
|
Chris@16
|
48 target = (target + 1) % n;
|
Chris@16
|
49 if (target == (source + k/2 + 1) % n) {
|
Chris@16
|
50 ++source;
|
Chris@16
|
51 if (allow_self_loops) target = source;
|
Chris@16
|
52 else target = (source + 1) % n;
|
Chris@16
|
53 }
|
Chris@16
|
54 current.first = source;
|
Chris@16
|
55
|
Chris@16
|
56 uniform_01<RandomGenerator, double> rand01(*gen);
|
Chris@16
|
57 uniform_int<vertices_size_type> rand_vertex_gen(0, n-1);
|
Chris@16
|
58 double x = rand01();
|
Chris@16
|
59 *gen = rand01.base(); // GRRRR
|
Chris@16
|
60 if (x < prob) {
|
Chris@16
|
61 vertices_size_type lower = (source + n - k/2) % n;
|
Chris@16
|
62 vertices_size_type upper = (source + k/2) % n;
|
Chris@16
|
63 do {
|
Chris@16
|
64 current.second = rand_vertex_gen(*gen);
|
Chris@16
|
65 } while ((current.second >= lower && current.second <= upper)
|
Chris@16
|
66 || (upper < lower
|
Chris@16
|
67 && (current.second >= lower || current.second <= upper)));
|
Chris@16
|
68 } else {
|
Chris@16
|
69 current.second = target;
|
Chris@16
|
70 }
|
Chris@16
|
71 return *this;
|
Chris@16
|
72 }
|
Chris@16
|
73
|
Chris@16
|
74 small_world_iterator operator++(int)
|
Chris@16
|
75 {
|
Chris@16
|
76 small_world_iterator temp(*this);
|
Chris@16
|
77 ++(*this);
|
Chris@16
|
78 return temp;
|
Chris@16
|
79 }
|
Chris@16
|
80
|
Chris@16
|
81 bool operator==(const small_world_iterator& other) const
|
Chris@16
|
82 {
|
Chris@16
|
83 if (!gen && other.gen) return other == *this;
|
Chris@16
|
84 else if (gen && !other.gen) return source == n;
|
Chris@16
|
85 else if (!gen && !other.gen) return true;
|
Chris@16
|
86 return source == other.source && target == other.target;
|
Chris@16
|
87 }
|
Chris@16
|
88
|
Chris@16
|
89 bool operator!=(const small_world_iterator& other) const
|
Chris@16
|
90 { return !(*this == other); }
|
Chris@16
|
91
|
Chris@16
|
92 private:
|
Chris@16
|
93 void next()
|
Chris@16
|
94 {
|
Chris@16
|
95 uniform_int<vertices_size_type> rand_vertex(0, n-1);
|
Chris@16
|
96 current.first = rand_vertex(*gen);
|
Chris@16
|
97 do {
|
Chris@16
|
98 current.second = rand_vertex(*gen);
|
Chris@16
|
99 } while (current.first == current.second && !allow_self_loops);
|
Chris@16
|
100 }
|
Chris@16
|
101
|
Chris@16
|
102 RandomGenerator* gen;
|
Chris@16
|
103 vertices_size_type n;
|
Chris@16
|
104 vertices_size_type k;
|
Chris@16
|
105 double prob;
|
Chris@16
|
106 vertices_size_type source;
|
Chris@16
|
107 vertices_size_type target;
|
Chris@16
|
108 bool allow_self_loops;
|
Chris@16
|
109 value_type current;
|
Chris@16
|
110 };
|
Chris@16
|
111
|
Chris@16
|
112 } // end namespace boost
|
Chris@16
|
113
|
Chris@16
|
114 #endif // BOOST_GRAPH_SMALL_WORLD_GENERATOR_HPP
|