// Copyright (C) 2006-2012 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 . #include "graph.hh" #include "graph_filtering.hh" #include "graph_properties.hh" #include "graph_selectors.hh" #include "graph_util.hh" #include "random.hh" #include using namespace std; using namespace boost; using namespace graph_tool; struct do_random_matching { template void operator()(const Graph& g, VertexIndex vertex_index, WeightMap weight, MatchMap match, bool minimize, RNG& rng) const { typedef typename graph_traits::vertex_descriptor vertex_t; typedef typename graph_traits::edge_descriptor edge_t; typedef typename property_traits::value_type wval_t; vector vlist; typename graph_traits::vertex_iterator v, v_end; for (tie(v, v_end) = vertices(g); v != v_end; ++v) vlist.push_back(*v); unchecked_vector_property_map matched(vertex_index, num_vertices(g)); typedef random_permutation_iterator::iterator, RNG> random_vertex_iter; random_vertex_iter vr(vlist.begin(), vlist.end(), rng), vr_end(vlist.end(), vlist.end(), rng); for (; vr != vr_end; ++vr) { vertex_t v = *vr; if (matched[v]) continue; wval_t min_w = minimize ? numeric_limits::max() : numeric_limits::min() ; vector candidates; typename graph_traits::out_edge_iterator e, e_end; for(tie(e, e_end) = out_edges(v, g); e != e_end; ++e) { vertex_t w = target(*e, g); if (matched[w]) continue; if ((minimize && (weight[*e] < min_w)) || (!minimize && (weight[*e] > min_w))) { min_w = weight[*e]; candidates.clear(); } if (weight[*e] == min_w) candidates.push_back(*e); } if (!candidates.empty()) { tr1::uniform_int<> sample(0, candidates.size() - 1); size_t j = sample(rng); match[candidates[j]] = true; matched[v] = true; matched[target(candidates[j], g)] = true; } } } }; void random_matching(GraphInterface& gi, boost::any weight, boost::any match, bool minimize, rng_t& rng) { typedef ConstantPropertyMap weight_map_t; typedef mpl::push_back::type edge_props_t; if(weight.empty()) weight = weight_map_t(1); run_action<>() (gi, bind(do_random_matching(), _1, gi.GetVertexIndex(), _2, _3, minimize, ref(rng)), edge_props_t(), edge_scalar_properties())(weight, match); } void export_random_matching() { python::def("random_matching", &random_matching); }