// Copyright (C) 2006-2013 Tiago de Paula Peixoto // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License // as published by the Free Software Foundation; either version 3 // of the License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program. If not, see . #ifndef GRAPH_HISTOGRAMS_HH #define GRAPH_HISTOGRAMS_HH #include #include #include #include #include #include #include "numpy_bind.hh" #include "histogram.hh" #include "shared_map.hh" namespace graph_tool { using namespace std; using namespace boost; class VertexHistogramFiller { public: template void operator()(const Graph& g, typename graph_traits::vertex_descriptor v, DegreeSelector& deg, Hist& hist) { typename Hist::point_t p; p[0] = deg(v, g); hist.PutValue(p); } }; class EdgeHistogramFiller { public: template void operator()(const Graph& g, typename graph_traits::vertex_descriptor v, EdgeProperty& eprop, Hist& hist) { typename Hist::point_t p; typename graph_traits::out_edge_iterator e, e_begin, e_end; tie(e_begin,e_end) = out_edges(v,g); for(e = e_begin; e != e_end; ++e) { p[0] = eprop[*e]; hist.PutValue(p); } } }; // generalized functor to obtain histogram of different types of "degrees" template struct get_histogram { get_histogram(python::object& hist, const vector& bins, python::object& ret_bins) : _hist(hist), _bins(bins), _ret_bins(ret_bins) {} template void operator()(const Graph& g, DegreeSelector deg) const { typedef typename DegreeSelector::value_type value_type; typedef Histogram hist_t; HistogramFiller filler; vector bins(_bins.size()); for (size_t i = 0; i < bins.size(); ++i) { // we'll attempt to recover from out of bounds conditions try { bins[i] = numeric_cast(_bins[i]); } catch (boost::numeric::negative_overflow&) { bins[i] = boost::numeric::bounds::lowest(); } catch (boost::numeric::positive_overflow&) { bins[i] = boost::numeric::bounds::highest(); } } // sort the bins sort(bins.begin(), bins.end()); // clean bins of zero size vector temp_bin(1); temp_bin[0] = bins[0]; for (size_t j = 1; j < bins.size(); ++j) { if (bins[j] > bins[j-1]) temp_bin.push_back(bins[j]); } bins = temp_bin; boost::array, 1> bin_list; bin_list[0] = bins; hist_t hist(bin_list); SharedHistogram s_hist(hist); int i, N = num_vertices(g); #pragma omp parallel for default(shared) private(i) \ firstprivate(s_hist) schedule(static, 100) for (i = 0; i < N; ++i) { typename graph_traits::vertex_descriptor v = vertex(i, g); if (v == graph_traits::null_vertex()) continue; filler(g, v, deg, s_hist); } s_hist.Gather(); bin_list = hist.GetBins(); python::object ret_bins = wrap_vector_owned(bin_list[0]); _ret_bins = ret_bins; _hist = wrap_multi_array_owned(hist.GetArray()); } python::object& _hist; const vector& _bins; python::object& _ret_bins; }; } // graph_tool namespace #endif // GRAPH_HISTOGRAMS_HH