File indexing completed on 2025-01-30 09:43:04
0001
0002
0003
0004
0005
0006
0007
0008
0009 #ifndef BOOST_GRAPH_METIS_HPP
0010 #define BOOST_GRAPH_METIS_HPP
0011
0012 #ifdef BOOST_GRAPH_METIS_NO_INLINE
0013 #define BOOST_GRAPH_METIS_INLINE_KEYWORD
0014 #else
0015 #define BOOST_GRAPH_METIS_INLINE_KEYWORD inline
0016 #endif
0017
0018 #include <string>
0019 #include <iostream>
0020 #include <iterator>
0021 #include <utility>
0022 #include <sstream>
0023 #include <exception>
0024 #include <vector>
0025 #include <algorithm>
0026
0027 namespace boost
0028 {
0029 namespace graph
0030 {
0031
0032 class BOOST_SYMBOL_VISIBLE metis_exception : public std::exception
0033 {
0034 };
0035 class BOOST_SYMBOL_VISIBLE metis_input_exception : public metis_exception
0036 {
0037 };
0038
0039 class metis_reader
0040 {
0041 public:
0042 typedef std::size_t vertices_size_type;
0043 typedef std::size_t edges_size_type;
0044 typedef double vertex_weight_type;
0045 typedef double edge_weight_type;
0046
0047 class edge_iterator
0048 {
0049 public:
0050 typedef std::input_iterator_tag iterator_category;
0051 typedef std::pair< vertices_size_type, vertices_size_type >
0052 value_type;
0053 typedef const value_type& reference;
0054 typedef const value_type* pointer;
0055 typedef std::ptrdiff_t difference_type;
0056
0057 private:
0058 class postincrement_proxy
0059 {
0060 postincrement_proxy(const value_type& value) : value(value) {}
0061
0062 public:
0063 reference operator*() const { return value; }
0064
0065 private:
0066 value_type value;
0067 friend class edge_iterator;
0068 };
0069
0070 public:
0071 edge_iterator& operator++();
0072 postincrement_proxy operator++(int);
0073
0074 reference operator*() const { return self->edge; }
0075 pointer operator->() const { return &self->edge; }
0076
0077
0078
0079 private:
0080 edge_iterator(metis_reader* self);
0081 void advance(bool skip_initial_read);
0082
0083 metis_reader* self;
0084
0085 friend class metis_reader;
0086 friend bool operator==(edge_iterator, edge_iterator);
0087 friend bool operator!=(edge_iterator, edge_iterator);
0088 };
0089 friend class edge_iterator;
0090
0091 class edge_weight_iterator
0092 {
0093 public:
0094 typedef std::input_iterator_tag iterator_category;
0095 typedef edge_weight_type value_type;
0096 typedef const value_type& reference;
0097 typedef const value_type* pointer;
0098
0099
0100
0101 reference operator*() const { return self->edge_weight; }
0102 pointer operator->() const { return &self->edge_weight; }
0103
0104 edge_weight_iterator& operator++() { return *this; }
0105 edge_weight_iterator operator++(int) { return *this; }
0106
0107 private:
0108 edge_weight_iterator(metis_reader* self) : self(self) {}
0109
0110 metis_reader* self;
0111
0112 friend class metis_reader;
0113 };
0114
0115 metis_reader(std::istream& in) : in(in), edge_weight(1.0) { start(); }
0116
0117 edge_iterator begin();
0118 edge_iterator end();
0119 edge_weight_iterator weight_begin();
0120
0121 vertices_size_type num_vertices() const { return n_vertices; }
0122 edges_size_type num_edges() const { return n_edges; }
0123
0124 std::size_t num_vertex_weights() const { return n_vertex_weights; }
0125
0126 vertex_weight_type vertex_weight(vertices_size_type v, std::size_t n)
0127 {
0128 return vertex_weights[v * num_vertex_weights() + n];
0129 }
0130
0131 bool has_edge_weights() const { return edge_weights; }
0132
0133 private:
0134 void start();
0135
0136
0137 std::istream& in;
0138
0139
0140 vertices_size_type n_vertices;
0141 edges_size_type n_edges;
0142 std::size_t n_vertex_weights;
0143 bool edge_weights;
0144
0145
0146 std::istringstream line_in;
0147 std::pair< vertices_size_type, vertices_size_type > edge;
0148 std::vector< vertex_weight_type > vertex_weights;
0149 edge_weight_type edge_weight;
0150
0151 friend bool operator==(edge_iterator, edge_iterator);
0152 friend bool operator!=(edge_iterator, edge_iterator);
0153 };
0154
0155 class metis_distribution
0156 {
0157 public:
0158 typedef int process_id_type;
0159 typedef std::size_t size_type;
0160 typedef std::vector< process_id_type >::iterator iterator;
0161
0162 metis_distribution(std::istream& in, process_id_type my_id);
0163
0164 size_type block_size(process_id_type id, size_type) const;
0165 process_id_type operator()(size_type n) const { return vertices[n]; }
0166 size_type local(size_type n) const;
0167 size_type global(size_type n) const { return global(my_id, n); }
0168 size_type global(process_id_type id, size_type n) const;
0169
0170 iterator begin() { return vertices.begin(); }
0171 iterator end() { return vertices.end(); }
0172
0173 private:
0174 process_id_type my_id;
0175 std::vector< process_id_type > vertices;
0176 };
0177
0178 #if !defined(BOOST_GRAPH_METIS_NO_INLINE) || defined(BOOST_GRAPH_METIS_SOURCE)
0179 BOOST_GRAPH_METIS_INLINE_KEYWORD
0180 bool operator==(
0181 metis_reader::edge_iterator x, metis_reader::edge_iterator y)
0182 {
0183 return (x.self == y.self
0184 || (x.self && x.self->edge.first == x.self->num_vertices())
0185 || (y.self && y.self->edge.first == y.self->num_vertices()));
0186 }
0187
0188 BOOST_GRAPH_METIS_INLINE_KEYWORD
0189 bool operator!=(
0190 metis_reader::edge_iterator x, metis_reader::edge_iterator y)
0191 {
0192 return !(x == y);
0193 }
0194
0195 BOOST_GRAPH_METIS_INLINE_KEYWORD
0196 metis_reader::edge_iterator::edge_iterator(metis_reader* self) : self(self)
0197 {
0198 if (self)
0199 advance(true);
0200 }
0201
0202 BOOST_GRAPH_METIS_INLINE_KEYWORD
0203 metis_reader::edge_iterator& metis_reader::edge_iterator::operator++()
0204 {
0205 advance(false);
0206 return *this;
0207 }
0208
0209 BOOST_GRAPH_METIS_INLINE_KEYWORD
0210 void metis_reader::edge_iterator::advance(bool skip_initial_read)
0211 {
0212 do
0213 {
0214
0215 if (!skip_initial_read)
0216 {
0217
0218 if (self->line_in >> std::ws >> self->edge.second)
0219 {
0220 --self->edge.second;
0221 if (self->has_edge_weights())
0222 {
0223 if (!(self->line_in >> self->edge_weight))
0224 boost::throw_exception(metis_input_exception());
0225 }
0226 return;
0227 }
0228
0229
0230 ++self->edge.first;
0231 if (self->edge.first == self->num_vertices())
0232 return;
0233 }
0234
0235
0236 std::string line;
0237 while (getline(self->in, line) && !line.empty() && line[0] == '%')
0238 {
0239
0240 }
0241 if (!self->in)
0242 boost::throw_exception(metis_input_exception());
0243 self->line_in.str(line);
0244 self->line_in.clear();
0245
0246
0247 std::size_t weights_left = self->n_vertex_weights;
0248 vertex_weight_type weight;
0249 while (weights_left > 0)
0250 {
0251 if (self->line_in >> weight)
0252 self->vertex_weights.push_back(weight);
0253 else
0254 boost::throw_exception(metis_input_exception());
0255 --weights_left;
0256 }
0257
0258
0259 skip_initial_read = false;
0260 } while (true);
0261 }
0262
0263 BOOST_GRAPH_METIS_INLINE_KEYWORD
0264 metis_reader::edge_iterator::postincrement_proxy
0265 metis_reader::edge_iterator::operator++(int)
0266 {
0267 postincrement_proxy result(**this);
0268 ++(*this);
0269 return result;
0270 }
0271
0272 BOOST_GRAPH_METIS_INLINE_KEYWORD
0273 metis_reader::edge_iterator metis_reader::begin()
0274 {
0275 if (edge.first != 0)
0276 start();
0277 return edge_iterator(this);
0278 }
0279
0280 BOOST_GRAPH_METIS_INLINE_KEYWORD
0281 metis_reader::edge_iterator metis_reader::end() { return edge_iterator(0); }
0282
0283 BOOST_GRAPH_METIS_INLINE_KEYWORD
0284 metis_reader::edge_weight_iterator metis_reader::weight_begin()
0285 {
0286 return edge_weight_iterator(this);
0287 }
0288
0289 BOOST_GRAPH_METIS_INLINE_KEYWORD
0290 void metis_reader::start()
0291 {
0292 in.seekg(0, std::ios::beg);
0293 std::string line;
0294 while (getline(in, line) && !line.empty() && line[0] == '%')
0295 {
0296
0297 }
0298
0299 if (!in || line.empty())
0300 boost::throw_exception(metis_input_exception());
0301
0302
0303 line_in.str(line);
0304 if (!(line_in >> n_vertices >> n_edges))
0305 boost::throw_exception(metis_input_exception());
0306
0307
0308 int fmt = 0;
0309 line_in >> fmt;
0310 n_vertex_weights = fmt / 10;
0311 edge_weights = (fmt % 10 == 1);
0312
0313
0314 if (n_vertex_weights)
0315 line_in >> n_vertex_weights;
0316
0317
0318 edge_weight = 1.0;
0319 edge.first = 0;
0320 edge.second = 0;
0321 vertex_weights.reserve(n_vertex_weights * num_vertices());
0322 }
0323
0324 metis_distribution::metis_distribution(
0325 std::istream& in, process_id_type my_id)
0326 : my_id(my_id)
0327 , vertices(std::istream_iterator< process_id_type >(in),
0328 std::istream_iterator< process_id_type >())
0329 {
0330 }
0331
0332 metis_distribution::size_type metis_distribution::block_size(
0333 process_id_type id, size_type) const
0334 {
0335 return std::count(vertices.begin(), vertices.end(), id);
0336 }
0337
0338 metis_distribution::size_type metis_distribution::local(size_type n) const
0339 {
0340 return std::count(vertices.begin(), vertices.begin() + n, vertices[n]);
0341 }
0342
0343 metis_distribution::size_type metis_distribution::global(
0344 process_id_type id, size_type n) const
0345 {
0346 std::vector< process_id_type >::const_iterator i = vertices.begin();
0347 while (*i != id)
0348 ++i;
0349
0350 while (n > 0)
0351 {
0352 do
0353 {
0354 ++i;
0355 } while (*i != id);
0356 --n;
0357 }
0358
0359 return i - vertices.begin();
0360 }
0361
0362 #endif
0363
0364 }
0365 }
0366
0367 #endif