Mercurial > hg > vamp-build-and-test
diff DEPENDENCIES/generic/include/boost/graph/metis.hpp @ 16:2665513ce2d3
Add boost headers
author | Chris Cannam |
---|---|
date | Tue, 05 Aug 2014 11:11:38 +0100 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DEPENDENCIES/generic/include/boost/graph/metis.hpp Tue Aug 05 11:11:38 2014 +0100 @@ -0,0 +1,339 @@ +// Copyright 2005 The Trustees of Indiana University. + +// Use, modification and distribution is subject to the Boost Software +// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// Authors: Douglas Gregor +// Andrew Lumsdaine +#ifndef BOOST_GRAPH_METIS_HPP +#define BOOST_GRAPH_METIS_HPP + +#ifdef BOOST_GRAPH_METIS_NO_INLINE +# define BOOST_GRAPH_METIS_INLINE_KEYWORD +#else +# define BOOST_GRAPH_METIS_INLINE_KEYWORD inline +#endif + +#include <string> +#include <iostream> +#include <iterator> +#include <utility> +#include <sstream> +#include <exception> +#include <vector> +#include <algorithm> + +namespace boost { namespace graph { + +class metis_exception : public std::exception {}; +class metis_input_exception : public metis_exception {}; + +class metis_reader +{ + public: + typedef std::size_t vertices_size_type; + typedef std::size_t edges_size_type; + typedef double vertex_weight_type; + typedef double edge_weight_type; + + class edge_iterator + { + public: + typedef std::input_iterator_tag iterator_category; + typedef std::pair<vertices_size_type, vertices_size_type> value_type; + typedef const value_type& reference; + typedef const value_type* pointer; + typedef std::ptrdiff_t difference_type; + + private: + class postincrement_proxy + { + postincrement_proxy(const value_type& value) : value(value) { } + + public: + reference operator*() const { return value; } + + private: + value_type value; + friend class edge_iterator; + }; + + public: + edge_iterator& operator++(); + postincrement_proxy operator++(int); + + reference operator*() const { return self->edge; } + pointer operator->() const { return &self->edge; } + + // Default copy constructor and assignment operator are okay + + private: + edge_iterator(metis_reader* self); + void advance(bool skip_initial_read); + + metis_reader* self; + + friend class metis_reader; + friend bool operator==(edge_iterator, edge_iterator); + friend bool operator!=(edge_iterator, edge_iterator); + }; + friend class edge_iterator; + + class edge_weight_iterator + { + public: + typedef std::input_iterator_tag iterator_category; + typedef edge_weight_type value_type; + typedef const value_type& reference; + typedef const value_type* pointer; + + // Default copy constructor and assignment operator are okay + + reference operator*() const { return self->edge_weight; } + pointer operator->() const { return &self->edge_weight; } + + edge_weight_iterator& operator++() { return *this; } + edge_weight_iterator operator++(int) { return *this; } + + private: + edge_weight_iterator(metis_reader* self) : self(self) { } + + metis_reader* self; + + friend class metis_reader; + }; + + metis_reader(std::istream& in) : in(in), edge_weight(1.0) { start(); } + + edge_iterator begin(); + edge_iterator end(); + edge_weight_iterator weight_begin(); + + vertices_size_type num_vertices() const { return n_vertices; } + edges_size_type num_edges() const { return n_edges; } + + std::size_t num_vertex_weights() const { return n_vertex_weights; } + + vertex_weight_type vertex_weight(vertices_size_type v, std::size_t n) + { return vertex_weights[v*num_vertex_weights() + n]; } + + bool has_edge_weights() const { return edge_weights; } + + private: + void start(); + + // Configuration information + std::istream& in; + + // Information about the current METIS file + vertices_size_type n_vertices; + edges_size_type n_edges; + std::size_t n_vertex_weights; + bool edge_weights; + + // Information about the current edge/vertex + std::istringstream line_in; + std::pair<vertices_size_type, vertices_size_type> edge; + std::vector<vertex_weight_type> vertex_weights; + edge_weight_type edge_weight; + + friend bool operator==(edge_iterator, edge_iterator); + friend bool operator!=(edge_iterator, edge_iterator); +}; + +class metis_distribution +{ + public: + typedef int process_id_type; + typedef std::size_t size_type; + typedef std::vector<process_id_type>::iterator iterator; + + metis_distribution(std::istream& in, process_id_type my_id); + + size_type block_size(process_id_type id, size_type) const; + process_id_type operator()(size_type n) const { return vertices[n]; } + size_type local(size_type n) const; + size_type global(size_type n) const { return global(my_id, n); } + size_type global(process_id_type id, size_type n) const; + + iterator begin() { return vertices.begin(); } + iterator end() { return vertices.end(); } + + private: + std::istream& in; + process_id_type my_id; + std::vector<process_id_type> vertices; +}; + +#if !defined(BOOST_GRAPH_METIS_NO_INLINE) || defined(BOOST_GRAPH_METIS_SOURCE) +BOOST_GRAPH_METIS_INLINE_KEYWORD +bool operator==(metis_reader::edge_iterator x, metis_reader::edge_iterator y) +{ + return (x.self == y.self + || (x.self && x.self->edge.first == x.self->num_vertices()) + || (y.self && y.self->edge.first == y.self->num_vertices())); +} + +BOOST_GRAPH_METIS_INLINE_KEYWORD +bool operator!=(metis_reader::edge_iterator x, metis_reader::edge_iterator y) +{ + return !(x == y); +} + +BOOST_GRAPH_METIS_INLINE_KEYWORD +metis_reader::edge_iterator::edge_iterator(metis_reader* self) + : self(self) +{ + if (self) advance(true); +} + +BOOST_GRAPH_METIS_INLINE_KEYWORD +metis_reader::edge_iterator& metis_reader::edge_iterator::operator++() +{ + advance(false); + return *this; +} + +BOOST_GRAPH_METIS_INLINE_KEYWORD +void metis_reader::edge_iterator::advance(bool skip_initial_read) +{ + do { + + if (!skip_initial_read) { + // Try to read the next edge + if (self->line_in >> std::ws >> self->edge.second) { + --self->edge.second; + if (self->has_edge_weights()) { + if (!(self->line_in >> self->edge_weight)) + boost::throw_exception(metis_input_exception()); + } + return; + } + + // Check if we're done + ++self->edge.first; + if (self->edge.first == self->num_vertices()) + return; + } + + // Find the next line + std::string line; + while (getline(self->in, line) && !line.empty() && line[0] == '%') { + /* Keep reading lines in the loop header... */ + } + if (!self->in) boost::throw_exception(metis_input_exception()); + self->line_in.str(line); + self->line_in.clear(); + + // Read the next line + std::size_t weights_left = self->n_vertex_weights; + vertex_weight_type weight; + while (weights_left > 0) { + if (self->line_in >> weight) self->vertex_weights.push_back(weight); + else boost::throw_exception(metis_input_exception()); + --weights_left; + } + + // Successive iterations will pick up edges for this vertex. + skip_initial_read = false; + } while (true); +} + +BOOST_GRAPH_METIS_INLINE_KEYWORD +metis_reader::edge_iterator::postincrement_proxy +metis_reader::edge_iterator::operator++(int) +{ + postincrement_proxy result(**this); + ++(*this); + return result; +} + +BOOST_GRAPH_METIS_INLINE_KEYWORD +metis_reader::edge_iterator metis_reader::begin() +{ + if (edge.first != 0) start(); + return edge_iterator(this); +} + +BOOST_GRAPH_METIS_INLINE_KEYWORD +metis_reader::edge_iterator metis_reader::end() +{ + return edge_iterator(0); +} + +BOOST_GRAPH_METIS_INLINE_KEYWORD +metis_reader::edge_weight_iterator metis_reader::weight_begin() +{ + return edge_weight_iterator(this); +} + +BOOST_GRAPH_METIS_INLINE_KEYWORD +void metis_reader::start() +{ + in.seekg(0, std::ios::beg); + std::string line; + while (getline(in, line) && !line.empty() && line[0] == '%') { + /* Keep getting lines in loop header. */ + } + + if (!in || line.empty()) boost::throw_exception(metis_input_exception()); + + // Determine number of vertices and edges in the graph + line_in.str(line); + if (!(line_in >> n_vertices >> n_edges)) boost::throw_exception(metis_input_exception()); + + // Determine whether vertex or edge weights are included in the graph + int fmt = 0; + line_in >> fmt; + n_vertex_weights = fmt / 10; + edge_weights = (fmt % 10 == 1); + + // Determine how many (if any!) vertex weights are included + if (n_vertex_weights) line_in >> n_vertex_weights; + + // Setup the iteration data structures + edge_weight = 1.0; + edge.first = 0; + edge.second = 0; + vertex_weights.reserve(n_vertex_weights * num_vertices()); +} + +metis_distribution::metis_distribution(std::istream& in, process_id_type my_id) + : in(in), my_id(my_id), + vertices(std::istream_iterator<process_id_type>(in), + std::istream_iterator<process_id_type>()) +{ +} + + +metis_distribution::size_type +metis_distribution::block_size(process_id_type id, size_type) const +{ + return std::count(vertices.begin(), vertices.end(), id); +} + +metis_distribution::size_type metis_distribution::local(size_type n) const +{ + return std::count(vertices.begin(), vertices.begin() + n, vertices[n]); +} + +metis_distribution::size_type +metis_distribution::global(process_id_type id, size_type n) const +{ + std::vector<process_id_type>::const_iterator i = vertices.begin(); + while (*i != id) ++i; + + while (n > 0) { + do { ++i; } while (*i != id); + --n; + } + + return i - vertices.begin(); +} + +#endif + +} } // end namespace boost::graph + +#endif // BOOST_GRAPH_METIS_HPP