Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-07-15 08:35:58

0001 // Copyright 2005 The Trustees of Indiana University.
0002 
0003 // Use, modification and distribution is subject to the Boost Software
0004 // License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
0005 // http://www.boost.org/LICENSE_1_0.txt)
0006 
0007 //  Authors: Douglas Gregor
0008 //           Andrew Lumsdaine
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 #include <boost/throw_exception.hpp>
0028 
0029 namespace boost
0030 {
0031 namespace graph
0032 {
0033 
0034     class BOOST_SYMBOL_VISIBLE metis_exception : public std::exception
0035     {
0036     };
0037     class BOOST_SYMBOL_VISIBLE metis_input_exception : public metis_exception
0038     {
0039     };
0040 
0041     class metis_reader
0042     {
0043     public:
0044         typedef std::size_t vertices_size_type;
0045         typedef std::size_t edges_size_type;
0046         typedef double vertex_weight_type;
0047         typedef double edge_weight_type;
0048 
0049         class edge_iterator
0050         {
0051         public:
0052             typedef std::input_iterator_tag iterator_category;
0053             typedef std::pair< vertices_size_type, vertices_size_type >
0054                 value_type;
0055             typedef const value_type& reference;
0056             typedef const value_type* pointer;
0057             typedef std::ptrdiff_t difference_type;
0058 
0059         private:
0060             class postincrement_proxy
0061             {
0062                 postincrement_proxy(const value_type& value) : value(value) {}
0063 
0064             public:
0065                 reference operator*() const { return value; }
0066 
0067             private:
0068                 value_type value;
0069                 friend class edge_iterator;
0070             };
0071 
0072         public:
0073             edge_iterator& operator++();
0074             postincrement_proxy operator++(int);
0075 
0076             reference operator*() const { return self->edge; }
0077             pointer operator->() const { return &self->edge; }
0078 
0079             // Default copy constructor and assignment operator are okay
0080 
0081         private:
0082             edge_iterator(metis_reader* self);
0083             void advance(bool skip_initial_read);
0084 
0085             metis_reader* self;
0086 
0087             friend class metis_reader;
0088             friend bool operator==(edge_iterator, edge_iterator);
0089             friend bool operator!=(edge_iterator, edge_iterator);
0090         };
0091         friend class edge_iterator;
0092 
0093         class edge_weight_iterator
0094         {
0095         public:
0096             typedef std::input_iterator_tag iterator_category;
0097             typedef edge_weight_type value_type;
0098             typedef const value_type& reference;
0099             typedef const value_type* pointer;
0100 
0101             // Default copy constructor and assignment operator are okay
0102 
0103             reference operator*() const { return self->edge_weight; }
0104             pointer operator->() const { return &self->edge_weight; }
0105 
0106             edge_weight_iterator& operator++() { return *this; }
0107             edge_weight_iterator operator++(int) { return *this; }
0108 
0109         private:
0110             edge_weight_iterator(metis_reader* self) : self(self) {}
0111 
0112             metis_reader* self;
0113 
0114             friend class metis_reader;
0115         };
0116 
0117         metis_reader(std::istream& in) : in(in), edge_weight(1.0) { start(); }
0118 
0119         edge_iterator begin();
0120         edge_iterator end();
0121         edge_weight_iterator weight_begin();
0122 
0123         vertices_size_type num_vertices() const { return n_vertices; }
0124         edges_size_type num_edges() const { return n_edges; }
0125 
0126         std::size_t num_vertex_weights() const { return n_vertex_weights; }
0127 
0128         vertex_weight_type vertex_weight(vertices_size_type v, std::size_t n)
0129         {
0130             return vertex_weights[v * num_vertex_weights() + n];
0131         }
0132 
0133         bool has_edge_weights() const { return edge_weights; }
0134 
0135     private:
0136         void start();
0137 
0138         // Configuration information
0139         std::istream& in;
0140 
0141         // Information about the current METIS file
0142         vertices_size_type n_vertices;
0143         edges_size_type n_edges;
0144         std::size_t n_vertex_weights;
0145         bool edge_weights;
0146 
0147         // Information about the current edge/vertex
0148         std::istringstream line_in;
0149         std::pair< vertices_size_type, vertices_size_type > edge;
0150         std::vector< vertex_weight_type > vertex_weights;
0151         edge_weight_type edge_weight;
0152 
0153         friend bool operator==(edge_iterator, edge_iterator);
0154         friend bool operator!=(edge_iterator, edge_iterator);
0155     };
0156 
0157     class metis_distribution
0158     {
0159     public:
0160         typedef int process_id_type;
0161         typedef std::size_t size_type;
0162         typedef std::vector< process_id_type >::iterator iterator;
0163 
0164         metis_distribution(std::istream& in, process_id_type my_id);
0165 
0166         size_type block_size(process_id_type id, size_type) const;
0167         process_id_type operator()(size_type n) const { return vertices[n]; }
0168         size_type local(size_type n) const;
0169         size_type global(size_type n) const { return global(my_id, n); }
0170         size_type global(process_id_type id, size_type n) const;
0171 
0172         iterator begin() { return vertices.begin(); }
0173         iterator end() { return vertices.end(); }
0174 
0175     private:
0176         process_id_type my_id;
0177         std::vector< process_id_type > vertices;
0178     };
0179 
0180 #if !defined(BOOST_GRAPH_METIS_NO_INLINE) || defined(BOOST_GRAPH_METIS_SOURCE)
0181     BOOST_GRAPH_METIS_INLINE_KEYWORD
0182     bool operator==(
0183         metis_reader::edge_iterator x, metis_reader::edge_iterator y)
0184     {
0185         return (x.self == y.self
0186             || (x.self && x.self->edge.first == x.self->num_vertices())
0187             || (y.self && y.self->edge.first == y.self->num_vertices()));
0188     }
0189 
0190     BOOST_GRAPH_METIS_INLINE_KEYWORD
0191     bool operator!=(
0192         metis_reader::edge_iterator x, metis_reader::edge_iterator y)
0193     {
0194         return !(x == y);
0195     }
0196 
0197     BOOST_GRAPH_METIS_INLINE_KEYWORD
0198     metis_reader::edge_iterator::edge_iterator(metis_reader* self) : self(self)
0199     {
0200         if (self)
0201             advance(true);
0202     }
0203 
0204     BOOST_GRAPH_METIS_INLINE_KEYWORD
0205     metis_reader::edge_iterator& metis_reader::edge_iterator::operator++()
0206     {
0207         advance(false);
0208         return *this;
0209     }
0210 
0211     BOOST_GRAPH_METIS_INLINE_KEYWORD
0212     void metis_reader::edge_iterator::advance(bool skip_initial_read)
0213     {
0214         do
0215         {
0216 
0217             if (!skip_initial_read)
0218             {
0219                 // Try to read the next edge
0220                 if (self->line_in >> std::ws >> self->edge.second)
0221                 {
0222                     --self->edge.second;
0223                     if (self->has_edge_weights())
0224                     {
0225                         if (!(self->line_in >> self->edge_weight))
0226                             boost::throw_exception(metis_input_exception());
0227                     }
0228                     return;
0229                 }
0230 
0231                 // Check if we're done
0232                 ++self->edge.first;
0233                 if (self->edge.first == self->num_vertices())
0234                     return;
0235             }
0236 
0237             // Find the next line
0238             std::string line;
0239             while (getline(self->in, line) && !line.empty() && line[0] == '%')
0240             {
0241                 /* Keep reading lines in the loop header... */
0242             }
0243             if (!self->in)
0244                 boost::throw_exception(metis_input_exception());
0245             self->line_in.str(line);
0246             self->line_in.clear();
0247 
0248             // Read the next line
0249             std::size_t weights_left = self->n_vertex_weights;
0250             vertex_weight_type weight;
0251             while (weights_left > 0)
0252             {
0253                 if (self->line_in >> weight)
0254                     self->vertex_weights.push_back(weight);
0255                 else
0256                     boost::throw_exception(metis_input_exception());
0257                 --weights_left;
0258             }
0259 
0260             // Successive iterations will pick up edges for this vertex.
0261             skip_initial_read = false;
0262         } while (true);
0263     }
0264 
0265     BOOST_GRAPH_METIS_INLINE_KEYWORD
0266     metis_reader::edge_iterator::postincrement_proxy
0267     metis_reader::edge_iterator::operator++(int)
0268     {
0269         postincrement_proxy result(**this);
0270         ++(*this);
0271         return result;
0272     }
0273 
0274     BOOST_GRAPH_METIS_INLINE_KEYWORD
0275     metis_reader::edge_iterator metis_reader::begin()
0276     {
0277         if (edge.first != 0)
0278             start();
0279         return edge_iterator(this);
0280     }
0281 
0282     BOOST_GRAPH_METIS_INLINE_KEYWORD
0283     metis_reader::edge_iterator metis_reader::end() { return edge_iterator(0); }
0284 
0285     BOOST_GRAPH_METIS_INLINE_KEYWORD
0286     metis_reader::edge_weight_iterator metis_reader::weight_begin()
0287     {
0288         return edge_weight_iterator(this);
0289     }
0290 
0291     BOOST_GRAPH_METIS_INLINE_KEYWORD
0292     void metis_reader::start()
0293     {
0294         in.seekg(0, std::ios::beg);
0295         std::string line;
0296         while (getline(in, line) && !line.empty() && line[0] == '%')
0297         {
0298             /* Keep getting lines in loop header. */
0299         }
0300 
0301         if (!in || line.empty())
0302             boost::throw_exception(metis_input_exception());
0303 
0304         // Determine number of vertices and edges in the graph
0305         line_in.str(line);
0306         if (!(line_in >> n_vertices >> n_edges))
0307             boost::throw_exception(metis_input_exception());
0308 
0309         // Determine whether vertex or edge weights are included in the graph
0310         int fmt = 0;
0311         line_in >> fmt;
0312         n_vertex_weights = fmt / 10;
0313         edge_weights = (fmt % 10 == 1);
0314 
0315         // Determine how many (if any!) vertex weights are included
0316         if (n_vertex_weights)
0317             line_in >> n_vertex_weights;
0318 
0319         // Setup the iteration data structures
0320         edge_weight = 1.0;
0321         edge.first = 0;
0322         edge.second = 0;
0323         vertex_weights.reserve(n_vertex_weights * num_vertices());
0324     }
0325 
0326     metis_distribution::metis_distribution(
0327         std::istream& in, process_id_type my_id)
0328     : my_id(my_id)
0329     , vertices(std::istream_iterator< process_id_type >(in),
0330           std::istream_iterator< process_id_type >())
0331     {
0332     }
0333 
0334     metis_distribution::size_type metis_distribution::block_size(
0335         process_id_type id, size_type) const
0336     {
0337         return std::count(vertices.begin(), vertices.end(), id);
0338     }
0339 
0340     metis_distribution::size_type metis_distribution::local(size_type n) const
0341     {
0342         return std::count(vertices.begin(), vertices.begin() + n, vertices[n]);
0343     }
0344 
0345     metis_distribution::size_type metis_distribution::global(
0346         process_id_type id, size_type n) const
0347     {
0348         std::vector< process_id_type >::const_iterator i = vertices.begin();
0349         while (*i != id)
0350             ++i;
0351 
0352         while (n > 0)
0353         {
0354             do
0355             {
0356                 ++i;
0357             } while (*i != id);
0358             --n;
0359         }
0360 
0361         return i - vertices.begin();
0362     }
0363 
0364 #endif
0365 
0366 }
0367 } // end namespace boost::graph
0368 
0369 #endif // BOOST_GRAPH_METIS_HPP