Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-30 09:43:04

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 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             // Default copy constructor and assignment operator are okay
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             // Default copy constructor and assignment operator are okay
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         // Configuration information
0137         std::istream& in;
0138 
0139         // Information about the current METIS file
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         // Information about the current edge/vertex
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                 // Try to read the next edge
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                 // Check if we're done
0230                 ++self->edge.first;
0231                 if (self->edge.first == self->num_vertices())
0232                     return;
0233             }
0234 
0235             // Find the next line
0236             std::string line;
0237             while (getline(self->in, line) && !line.empty() && line[0] == '%')
0238             {
0239                 /* Keep reading lines in the loop header... */
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             // Read the next line
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             // Successive iterations will pick up edges for this vertex.
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             /* Keep getting lines in loop header. */
0297         }
0298 
0299         if (!in || line.empty())
0300             boost::throw_exception(metis_input_exception());
0301 
0302         // Determine number of vertices and edges in the graph
0303         line_in.str(line);
0304         if (!(line_in >> n_vertices >> n_edges))
0305             boost::throw_exception(metis_input_exception());
0306 
0307         // Determine whether vertex or edge weights are included in the graph
0308         int fmt = 0;
0309         line_in >> fmt;
0310         n_vertex_weights = fmt / 10;
0311         edge_weights = (fmt % 10 == 1);
0312 
0313         // Determine how many (if any!) vertex weights are included
0314         if (n_vertex_weights)
0315             line_in >> n_vertex_weights;
0316 
0317         // Setup the iteration data structures
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 } // end namespace boost::graph
0366 
0367 #endif // BOOST_GRAPH_METIS_HPP