annotate DEPENDENCIES/generic/include/boost/graph/ssca_graph_generator.hpp @ 133:4acb5d8d80b6 tip

Don't fail environmental check if README.md exists (but .txt and no-suffix don't)
author Chris Cannam
date Tue, 30 Jul 2019 12:25:44 +0100
parents 2665513ce2d3
children
rev   line source
Chris@16 1 // Copyright 2004, 2005 The Trustees of Indiana University.
Chris@16 2
Chris@16 3 // Use, modification and distribution is subject to the Boost Software
Chris@16 4 // License, Version 1.0. (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: Nick Edmonds
Chris@16 8 // Andrew Lumsdaine
Chris@16 9 #ifndef BOOST_GRAPH_SSCA_GENERATOR_HPP
Chris@16 10 #define BOOST_GRAPH_SSCA_GENERATOR_HPP
Chris@16 11
Chris@16 12 #include <iterator>
Chris@16 13 #include <utility>
Chris@16 14 #include <vector>
Chris@16 15 #include <queue>
Chris@16 16 #include <boost/config.hpp>
Chris@16 17 #include <boost/random/uniform_int.hpp>
Chris@16 18 #include <boost/graph/graph_traits.hpp>
Chris@16 19 #include <boost/type_traits/is_base_and_derived.hpp>
Chris@16 20 #include <boost/type_traits/is_same.hpp>
Chris@16 21
Chris@16 22 enum Direction {FORWARD = 1, BACKWARD = 2, BOTH = FORWARD | BACKWARD};
Chris@16 23
Chris@16 24 namespace boost {
Chris@16 25
Chris@16 26 // This generator generates graphs according to the method specified
Chris@16 27 // in SSCA 1.1. Current versions of SSCA use R-MAT graphs
Chris@16 28
Chris@16 29 template<typename RandomGenerator, typename Graph>
Chris@16 30 class ssca_iterator
Chris@16 31 {
Chris@16 32 typedef typename graph_traits<Graph>::directed_category directed_category;
Chris@16 33 typedef typename graph_traits<Graph>::vertices_size_type
Chris@16 34 vertices_size_type;
Chris@16 35
Chris@16 36 public:
Chris@16 37 typedef std::input_iterator_tag iterator_category;
Chris@16 38 typedef std::pair<vertices_size_type, vertices_size_type> value_type;
Chris@16 39 typedef const value_type& reference;
Chris@16 40 typedef const value_type* pointer;
Chris@16 41 typedef void difference_type;
Chris@16 42
Chris@16 43 // No argument constructor, set to terminating condition
Chris@16 44 ssca_iterator()
Chris@16 45 : gen(), verticesRemaining(0) { }
Chris@16 46
Chris@16 47 // Initialize for edge generation
Chris@16 48 ssca_iterator(RandomGenerator& gen, vertices_size_type totVertices,
Chris@16 49 vertices_size_type maxCliqueSize, double probUnidirectional,
Chris@16 50 int maxParallelEdges, double probIntercliqueEdges)
Chris@16 51 : gen(&gen), totVertices(totVertices), maxCliqueSize(maxCliqueSize),
Chris@16 52 probUnidirectional(probUnidirectional), maxParallelEdges(maxParallelEdges),
Chris@16 53 probIntercliqueEdges(probIntercliqueEdges), currentClique(0),
Chris@16 54 verticesRemaining(totVertices)
Chris@16 55 {
Chris@16 56 cliqueNum = std::vector<int>(totVertices, -1);
Chris@16 57 current = std::make_pair(0,0);
Chris@16 58 }
Chris@16 59
Chris@16 60 reference operator*() const { return current; }
Chris@16 61 pointer operator->() const { return &current; }
Chris@16 62
Chris@16 63 ssca_iterator& operator++()
Chris@16 64 {
Chris@16 65 BOOST_USING_STD_MIN();
Chris@16 66 while (values.empty() && verticesRemaining > 0) { // If there are no values left, generate a new clique
Chris@16 67 uniform_int<vertices_size_type> clique_size(1, maxCliqueSize);
Chris@16 68 uniform_int<vertices_size_type> rand_vertex(0, totVertices-1);
Chris@16 69 uniform_int<int> num_parallel_edges(1, maxParallelEdges);
Chris@16 70 uniform_int<short> direction(0,1);
Chris@16 71 uniform_01<RandomGenerator> prob(*gen);
Chris@16 72 std::vector<vertices_size_type> cliqueVertices;
Chris@16 73
Chris@16 74 cliqueVertices.clear();
Chris@16 75 vertices_size_type size = min BOOST_PREVENT_MACRO_SUBSTITUTION (clique_size(*gen), verticesRemaining);
Chris@16 76 while (cliqueVertices.size() < size) {
Chris@16 77 vertices_size_type v = rand_vertex(*gen);
Chris@16 78 if (cliqueNum[v] == -1) {
Chris@16 79 cliqueNum[v] = currentClique;
Chris@16 80 cliqueVertices.push_back(v);
Chris@16 81 verticesRemaining--;
Chris@16 82 }
Chris@16 83 } // Nick: This is inefficient when only a few vertices remain...
Chris@16 84 // I should probably just select the remaining vertices
Chris@16 85 // in order when only a certain fraction remain.
Chris@16 86
Chris@16 87 typename std::vector<vertices_size_type>::iterator first, second;
Chris@16 88 for (first = cliqueVertices.begin(); first != cliqueVertices.end(); ++first)
Chris@16 89 for (second = first+1; second != cliqueVertices.end(); ++second) {
Chris@16 90 Direction d;
Chris@16 91 int edges;
Chris@16 92
Chris@16 93 d = prob() < probUnidirectional ? (direction(*gen) == 0 ? FORWARD : BACKWARD) : BOTH;
Chris@16 94
Chris@16 95 if (d & FORWARD) {
Chris@16 96 edges = num_parallel_edges(*gen);
Chris@16 97 for (int i = 0; i < edges; ++i)
Chris@16 98 values.push(std::make_pair(*first, *second));
Chris@16 99 }
Chris@16 100
Chris@16 101 if (d & BACKWARD) {
Chris@16 102 edges = num_parallel_edges(*gen);
Chris@16 103 for (int i = 0; i < edges; ++i)
Chris@16 104 values.push(std::make_pair(*second, *first));
Chris@16 105 }
Chris@16 106 }
Chris@16 107
Chris@16 108 if (verticesRemaining == 0) {
Chris@16 109 // Generate interclique edges
Chris@16 110 for (vertices_size_type i = 0; i < totVertices; ++i) {
Chris@16 111 double p = probIntercliqueEdges;
Chris@16 112 for (vertices_size_type d = 2; d < totVertices/2; d *= 2, p/= 2) {
Chris@16 113 vertices_size_type j = (i+d) % totVertices;
Chris@16 114 if (cliqueNum[j] != cliqueNum[i] && prob() < p) {
Chris@16 115 int edges = num_parallel_edges(*gen);
Chris@16 116 for (int i = 0; i < edges; ++i)
Chris@16 117 values.push(std::make_pair(i, j));
Chris@16 118 }
Chris@16 119 }
Chris@16 120 }
Chris@16 121 }
Chris@16 122
Chris@16 123 currentClique++;
Chris@16 124 }
Chris@16 125
Chris@16 126 if (!values.empty()) { // If we're not done return a value
Chris@16 127 current = values.front();
Chris@16 128 values.pop();
Chris@16 129 }
Chris@16 130
Chris@16 131 return *this;
Chris@16 132 }
Chris@16 133
Chris@16 134 ssca_iterator operator++(int)
Chris@16 135 {
Chris@16 136 ssca_iterator temp(*this);
Chris@16 137 ++(*this);
Chris@16 138 return temp;
Chris@16 139 }
Chris@16 140
Chris@16 141 bool operator==(const ssca_iterator& other) const
Chris@16 142 {
Chris@16 143 return verticesRemaining == other.verticesRemaining && values.empty() && other.values.empty();
Chris@16 144 }
Chris@16 145
Chris@16 146 bool operator!=(const ssca_iterator& other) const
Chris@16 147 { return !(*this == other); }
Chris@16 148
Chris@16 149 private:
Chris@16 150
Chris@16 151 // Parameters
Chris@16 152 RandomGenerator* gen;
Chris@16 153 vertices_size_type totVertices;
Chris@16 154 vertices_size_type maxCliqueSize;
Chris@16 155 double probUnidirectional;
Chris@16 156 int maxParallelEdges;
Chris@16 157 double probIntercliqueEdges;
Chris@16 158
Chris@16 159 // Internal data structures
Chris@16 160 std::vector<int> cliqueNum;
Chris@16 161 std::queue<value_type> values;
Chris@16 162 int currentClique;
Chris@16 163 vertices_size_type verticesRemaining;
Chris@16 164 value_type current;
Chris@16 165 };
Chris@16 166
Chris@16 167 } // end namespace boost
Chris@16 168
Chris@16 169 #endif // BOOST_GRAPH_SSCA_GENERATOR_HPP