annotate DEPENDENCIES/generic/include/boost/graph/metis.hpp @ 118:770eb830ec19 emscripten

Typo fix
author Chris Cannam
date Wed, 18 May 2016 16:14:08 +0100
parents 2665513ce2d3
children
rev   line source
Chris@16 1 // Copyright 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: Douglas Gregor
Chris@16 8 // Andrew Lumsdaine
Chris@16 9 #ifndef BOOST_GRAPH_METIS_HPP
Chris@16 10 #define BOOST_GRAPH_METIS_HPP
Chris@16 11
Chris@16 12 #ifdef BOOST_GRAPH_METIS_NO_INLINE
Chris@16 13 # define BOOST_GRAPH_METIS_INLINE_KEYWORD
Chris@16 14 #else
Chris@16 15 # define BOOST_GRAPH_METIS_INLINE_KEYWORD inline
Chris@16 16 #endif
Chris@16 17
Chris@16 18 #include <string>
Chris@16 19 #include <iostream>
Chris@16 20 #include <iterator>
Chris@16 21 #include <utility>
Chris@16 22 #include <sstream>
Chris@16 23 #include <exception>
Chris@16 24 #include <vector>
Chris@16 25 #include <algorithm>
Chris@16 26
Chris@16 27 namespace boost { namespace graph {
Chris@16 28
Chris@16 29 class metis_exception : public std::exception {};
Chris@16 30 class metis_input_exception : public metis_exception {};
Chris@16 31
Chris@16 32 class metis_reader
Chris@16 33 {
Chris@16 34 public:
Chris@16 35 typedef std::size_t vertices_size_type;
Chris@16 36 typedef std::size_t edges_size_type;
Chris@16 37 typedef double vertex_weight_type;
Chris@16 38 typedef double edge_weight_type;
Chris@16 39
Chris@16 40 class edge_iterator
Chris@16 41 {
Chris@16 42 public:
Chris@16 43 typedef std::input_iterator_tag iterator_category;
Chris@16 44 typedef std::pair<vertices_size_type, vertices_size_type> value_type;
Chris@16 45 typedef const value_type& reference;
Chris@16 46 typedef const value_type* pointer;
Chris@16 47 typedef std::ptrdiff_t difference_type;
Chris@16 48
Chris@16 49 private:
Chris@16 50 class postincrement_proxy
Chris@16 51 {
Chris@16 52 postincrement_proxy(const value_type& value) : value(value) { }
Chris@16 53
Chris@16 54 public:
Chris@16 55 reference operator*() const { return value; }
Chris@16 56
Chris@16 57 private:
Chris@16 58 value_type value;
Chris@16 59 friend class edge_iterator;
Chris@16 60 };
Chris@16 61
Chris@16 62 public:
Chris@16 63 edge_iterator& operator++();
Chris@16 64 postincrement_proxy operator++(int);
Chris@16 65
Chris@16 66 reference operator*() const { return self->edge; }
Chris@16 67 pointer operator->() const { return &self->edge; }
Chris@16 68
Chris@16 69 // Default copy constructor and assignment operator are okay
Chris@16 70
Chris@16 71 private:
Chris@16 72 edge_iterator(metis_reader* self);
Chris@16 73 void advance(bool skip_initial_read);
Chris@16 74
Chris@16 75 metis_reader* self;
Chris@16 76
Chris@16 77 friend class metis_reader;
Chris@16 78 friend bool operator==(edge_iterator, edge_iterator);
Chris@16 79 friend bool operator!=(edge_iterator, edge_iterator);
Chris@16 80 };
Chris@16 81 friend class edge_iterator;
Chris@16 82
Chris@16 83 class edge_weight_iterator
Chris@16 84 {
Chris@16 85 public:
Chris@16 86 typedef std::input_iterator_tag iterator_category;
Chris@16 87 typedef edge_weight_type value_type;
Chris@16 88 typedef const value_type& reference;
Chris@16 89 typedef const value_type* pointer;
Chris@16 90
Chris@16 91 // Default copy constructor and assignment operator are okay
Chris@16 92
Chris@16 93 reference operator*() const { return self->edge_weight; }
Chris@16 94 pointer operator->() const { return &self->edge_weight; }
Chris@16 95
Chris@16 96 edge_weight_iterator& operator++() { return *this; }
Chris@16 97 edge_weight_iterator operator++(int) { return *this; }
Chris@16 98
Chris@16 99 private:
Chris@16 100 edge_weight_iterator(metis_reader* self) : self(self) { }
Chris@16 101
Chris@16 102 metis_reader* self;
Chris@16 103
Chris@16 104 friend class metis_reader;
Chris@16 105 };
Chris@16 106
Chris@16 107 metis_reader(std::istream& in) : in(in), edge_weight(1.0) { start(); }
Chris@16 108
Chris@16 109 edge_iterator begin();
Chris@16 110 edge_iterator end();
Chris@16 111 edge_weight_iterator weight_begin();
Chris@16 112
Chris@16 113 vertices_size_type num_vertices() const { return n_vertices; }
Chris@16 114 edges_size_type num_edges() const { return n_edges; }
Chris@16 115
Chris@16 116 std::size_t num_vertex_weights() const { return n_vertex_weights; }
Chris@16 117
Chris@16 118 vertex_weight_type vertex_weight(vertices_size_type v, std::size_t n)
Chris@16 119 { return vertex_weights[v*num_vertex_weights() + n]; }
Chris@16 120
Chris@16 121 bool has_edge_weights() const { return edge_weights; }
Chris@16 122
Chris@16 123 private:
Chris@16 124 void start();
Chris@16 125
Chris@16 126 // Configuration information
Chris@16 127 std::istream& in;
Chris@16 128
Chris@16 129 // Information about the current METIS file
Chris@16 130 vertices_size_type n_vertices;
Chris@16 131 edges_size_type n_edges;
Chris@16 132 std::size_t n_vertex_weights;
Chris@16 133 bool edge_weights;
Chris@16 134
Chris@16 135 // Information about the current edge/vertex
Chris@16 136 std::istringstream line_in;
Chris@16 137 std::pair<vertices_size_type, vertices_size_type> edge;
Chris@16 138 std::vector<vertex_weight_type> vertex_weights;
Chris@16 139 edge_weight_type edge_weight;
Chris@16 140
Chris@16 141 friend bool operator==(edge_iterator, edge_iterator);
Chris@16 142 friend bool operator!=(edge_iterator, edge_iterator);
Chris@16 143 };
Chris@16 144
Chris@16 145 class metis_distribution
Chris@16 146 {
Chris@16 147 public:
Chris@16 148 typedef int process_id_type;
Chris@16 149 typedef std::size_t size_type;
Chris@16 150 typedef std::vector<process_id_type>::iterator iterator;
Chris@16 151
Chris@16 152 metis_distribution(std::istream& in, process_id_type my_id);
Chris@16 153
Chris@16 154 size_type block_size(process_id_type id, size_type) const;
Chris@16 155 process_id_type operator()(size_type n) const { return vertices[n]; }
Chris@16 156 size_type local(size_type n) const;
Chris@16 157 size_type global(size_type n) const { return global(my_id, n); }
Chris@16 158 size_type global(process_id_type id, size_type n) const;
Chris@16 159
Chris@16 160 iterator begin() { return vertices.begin(); }
Chris@16 161 iterator end() { return vertices.end(); }
Chris@16 162
Chris@16 163 private:
Chris@16 164 std::istream& in;
Chris@16 165 process_id_type my_id;
Chris@16 166 std::vector<process_id_type> vertices;
Chris@16 167 };
Chris@16 168
Chris@16 169 #if !defined(BOOST_GRAPH_METIS_NO_INLINE) || defined(BOOST_GRAPH_METIS_SOURCE)
Chris@16 170 BOOST_GRAPH_METIS_INLINE_KEYWORD
Chris@16 171 bool operator==(metis_reader::edge_iterator x, metis_reader::edge_iterator y)
Chris@16 172 {
Chris@16 173 return (x.self == y.self
Chris@16 174 || (x.self && x.self->edge.first == x.self->num_vertices())
Chris@16 175 || (y.self && y.self->edge.first == y.self->num_vertices()));
Chris@16 176 }
Chris@16 177
Chris@16 178 BOOST_GRAPH_METIS_INLINE_KEYWORD
Chris@16 179 bool operator!=(metis_reader::edge_iterator x, metis_reader::edge_iterator y)
Chris@16 180 {
Chris@16 181 return !(x == y);
Chris@16 182 }
Chris@16 183
Chris@16 184 BOOST_GRAPH_METIS_INLINE_KEYWORD
Chris@16 185 metis_reader::edge_iterator::edge_iterator(metis_reader* self)
Chris@16 186 : self(self)
Chris@16 187 {
Chris@16 188 if (self) advance(true);
Chris@16 189 }
Chris@16 190
Chris@16 191 BOOST_GRAPH_METIS_INLINE_KEYWORD
Chris@16 192 metis_reader::edge_iterator& metis_reader::edge_iterator::operator++()
Chris@16 193 {
Chris@16 194 advance(false);
Chris@16 195 return *this;
Chris@16 196 }
Chris@16 197
Chris@16 198 BOOST_GRAPH_METIS_INLINE_KEYWORD
Chris@16 199 void metis_reader::edge_iterator::advance(bool skip_initial_read)
Chris@16 200 {
Chris@16 201 do {
Chris@16 202
Chris@16 203 if (!skip_initial_read) {
Chris@16 204 // Try to read the next edge
Chris@16 205 if (self->line_in >> std::ws >> self->edge.second) {
Chris@16 206 --self->edge.second;
Chris@16 207 if (self->has_edge_weights()) {
Chris@16 208 if (!(self->line_in >> self->edge_weight))
Chris@16 209 boost::throw_exception(metis_input_exception());
Chris@16 210 }
Chris@16 211 return;
Chris@16 212 }
Chris@16 213
Chris@16 214 // Check if we're done
Chris@16 215 ++self->edge.first;
Chris@16 216 if (self->edge.first == self->num_vertices())
Chris@16 217 return;
Chris@16 218 }
Chris@16 219
Chris@16 220 // Find the next line
Chris@16 221 std::string line;
Chris@16 222 while (getline(self->in, line) && !line.empty() && line[0] == '%') {
Chris@16 223 /* Keep reading lines in the loop header... */
Chris@16 224 }
Chris@16 225 if (!self->in) boost::throw_exception(metis_input_exception());
Chris@16 226 self->line_in.str(line);
Chris@16 227 self->line_in.clear();
Chris@16 228
Chris@16 229 // Read the next line
Chris@16 230 std::size_t weights_left = self->n_vertex_weights;
Chris@16 231 vertex_weight_type weight;
Chris@16 232 while (weights_left > 0) {
Chris@16 233 if (self->line_in >> weight) self->vertex_weights.push_back(weight);
Chris@16 234 else boost::throw_exception(metis_input_exception());
Chris@16 235 --weights_left;
Chris@16 236 }
Chris@16 237
Chris@16 238 // Successive iterations will pick up edges for this vertex.
Chris@16 239 skip_initial_read = false;
Chris@16 240 } while (true);
Chris@16 241 }
Chris@16 242
Chris@16 243 BOOST_GRAPH_METIS_INLINE_KEYWORD
Chris@16 244 metis_reader::edge_iterator::postincrement_proxy
Chris@16 245 metis_reader::edge_iterator::operator++(int)
Chris@16 246 {
Chris@16 247 postincrement_proxy result(**this);
Chris@16 248 ++(*this);
Chris@16 249 return result;
Chris@16 250 }
Chris@16 251
Chris@16 252 BOOST_GRAPH_METIS_INLINE_KEYWORD
Chris@16 253 metis_reader::edge_iterator metis_reader::begin()
Chris@16 254 {
Chris@16 255 if (edge.first != 0) start();
Chris@16 256 return edge_iterator(this);
Chris@16 257 }
Chris@16 258
Chris@16 259 BOOST_GRAPH_METIS_INLINE_KEYWORD
Chris@16 260 metis_reader::edge_iterator metis_reader::end()
Chris@16 261 {
Chris@16 262 return edge_iterator(0);
Chris@16 263 }
Chris@16 264
Chris@16 265 BOOST_GRAPH_METIS_INLINE_KEYWORD
Chris@16 266 metis_reader::edge_weight_iterator metis_reader::weight_begin()
Chris@16 267 {
Chris@16 268 return edge_weight_iterator(this);
Chris@16 269 }
Chris@16 270
Chris@16 271 BOOST_GRAPH_METIS_INLINE_KEYWORD
Chris@16 272 void metis_reader::start()
Chris@16 273 {
Chris@16 274 in.seekg(0, std::ios::beg);
Chris@16 275 std::string line;
Chris@16 276 while (getline(in, line) && !line.empty() && line[0] == '%') {
Chris@16 277 /* Keep getting lines in loop header. */
Chris@16 278 }
Chris@16 279
Chris@16 280 if (!in || line.empty()) boost::throw_exception(metis_input_exception());
Chris@16 281
Chris@16 282 // Determine number of vertices and edges in the graph
Chris@16 283 line_in.str(line);
Chris@16 284 if (!(line_in >> n_vertices >> n_edges)) boost::throw_exception(metis_input_exception());
Chris@16 285
Chris@16 286 // Determine whether vertex or edge weights are included in the graph
Chris@16 287 int fmt = 0;
Chris@16 288 line_in >> fmt;
Chris@16 289 n_vertex_weights = fmt / 10;
Chris@16 290 edge_weights = (fmt % 10 == 1);
Chris@16 291
Chris@16 292 // Determine how many (if any!) vertex weights are included
Chris@16 293 if (n_vertex_weights) line_in >> n_vertex_weights;
Chris@16 294
Chris@16 295 // Setup the iteration data structures
Chris@16 296 edge_weight = 1.0;
Chris@16 297 edge.first = 0;
Chris@16 298 edge.second = 0;
Chris@16 299 vertex_weights.reserve(n_vertex_weights * num_vertices());
Chris@16 300 }
Chris@16 301
Chris@16 302 metis_distribution::metis_distribution(std::istream& in, process_id_type my_id)
Chris@16 303 : in(in), my_id(my_id),
Chris@16 304 vertices(std::istream_iterator<process_id_type>(in),
Chris@16 305 std::istream_iterator<process_id_type>())
Chris@16 306 {
Chris@16 307 }
Chris@16 308
Chris@16 309
Chris@16 310 metis_distribution::size_type
Chris@16 311 metis_distribution::block_size(process_id_type id, size_type) const
Chris@16 312 {
Chris@16 313 return std::count(vertices.begin(), vertices.end(), id);
Chris@16 314 }
Chris@16 315
Chris@16 316 metis_distribution::size_type metis_distribution::local(size_type n) const
Chris@16 317 {
Chris@16 318 return std::count(vertices.begin(), vertices.begin() + n, vertices[n]);
Chris@16 319 }
Chris@16 320
Chris@16 321 metis_distribution::size_type
Chris@16 322 metis_distribution::global(process_id_type id, size_type n) const
Chris@16 323 {
Chris@16 324 std::vector<process_id_type>::const_iterator i = vertices.begin();
Chris@16 325 while (*i != id) ++i;
Chris@16 326
Chris@16 327 while (n > 0) {
Chris@16 328 do { ++i; } while (*i != id);
Chris@16 329 --n;
Chris@16 330 }
Chris@16 331
Chris@16 332 return i - vertices.begin();
Chris@16 333 }
Chris@16 334
Chris@16 335 #endif
Chris@16 336
Chris@16 337 } } // end namespace boost::graph
Chris@16 338
Chris@16 339 #endif // BOOST_GRAPH_METIS_HPP