All Classes Namespaces Files Functions Variables Typedefs Enumerations Friends Macros Pages
k_cut.hpp
Go to the documentation of this file.
1 //=======================================================================
2 // Copyright (c) 2013 Piotr Smulewicz
3 //
4 // Distributed under the Boost Software License, Version 1.0. (See
5 // accompanying file LICENSE_1_0.txt or copy at
6 // http://www.boost.org/LICENSE_1_0.txt)
7 //=======================================================================
15 #ifndef PAAL_K_CUT_HPP
16 #define PAAL_K_CUT_HPP
17 
18 #include "paal/utils/functors.hpp"
20 #include "paal/utils/irange.hpp"
21 
22 #include <boost/graph/adjacency_list.hpp>
23 #include <boost/graph/copy.hpp>
24 #include <boost/graph/iteration_macros.hpp>
25 #include <boost/graph/one_bit_color_map.hpp>
26 #include <boost/graph/stoer_wagner_min_cut.hpp>
27 #include <boost/graph/subgraph.hpp>
28 #include <boost/range/as_array.hpp>
29 
30 #include <queue>
31 
32 namespace paal {
33 namespace greedy {
34 
53 template<typename InGraph, class OutputIterator, typename VertexIndexMap, typename EdgeWeightMap>
54 auto k_cut(const InGraph& graph, unsigned int number_of_parts,OutputIterator result,
55  VertexIndexMap index_map, EdgeWeightMap weight_map) ->
56  typename boost::property_traits<EdgeWeightMap>::value_type{
57  using cost_t = typename boost::property_traits<EdgeWeightMap>::value_type;
58  using Vertex = typename boost::graph_traits<InGraph>::vertex_descriptor;
59 
60  using Graph = boost::adjacency_list<
61  boost::vecS, boost::vecS, boost::undirectedS, boost::no_property,
62  boost::property<boost::edge_weight_t, cost_t,
63  boost::property<boost::edge_index_t, int>>>;
64 
65  assert(num_vertices(graph) >= number_of_parts);
66 
67  std::vector<int> vertex_to_part(num_vertices(graph));
68  using VertexIndexToVertex = typename std::vector<Vertex>;
69  using VertexIndexToVertexIndex = std::vector<int>;
70  VertexIndexToVertex vertex_in_subgraph_to_vertex(num_vertices(graph));
71  VertexIndexToVertexIndex vertex_to_vertex_in_subgraph(num_vertices(graph));
72  int vertex_in_part;
73  int parts = 1;
74  // cuts contain pair(x,y)
75  // x is the cost of the cut
76  // y and y+1 are index parts of graph after make a cut
77  std::priority_queue<
78  std::pair<cost_t,int>,
79  std::vector<std::pair<cost_t,int> >
80  ,utils::greater> cuts;
81 
82  int id_part = 0;
83 
84  //get part id and compute minimum cost of cut of that part and add it to queue
85  auto make_cut = [&](int id) {
86  vertex_in_part=0;
87  for (auto v: boost::as_array(vertices(graph))) {
88  if (vertex_to_part[get(index_map, v)] == id) {
89  vertex_in_subgraph_to_vertex[vertex_in_part] = v;
90  vertex_to_vertex_in_subgraph[get(index_map, v)] = vertex_in_part;
91  ++vertex_in_part;
92  }
93  }
94  Graph part(vertex_in_part);
95  for (auto edge : boost::as_array(edges(graph))) {
96  auto sour = get(index_map, source(edge,graph));
97  auto targ = get(index_map, target(edge,graph));
98  if (vertex_to_part[sour] == id &&
99  vertex_to_part[targ] == id &&
100  sour != targ) {
101  add_edge(vertex_to_vertex_in_subgraph[sour],
102  vertex_to_vertex_in_subgraph[targ],
103  get(weight_map, edge),
104  part);
105  }
106  }
107  if (vertex_in_part < 2) {
108  ++id_part;
109  *result = std::make_pair(vertex_in_subgraph_to_vertex[0], id_part);
110  ++result;
111  return;
112  }
113  auto parities = boost::make_one_bit_color_map(num_vertices(part),
114  get(boost::vertex_index, part));
115  auto cut_cost = boost::stoer_wagner_min_cut(part,
116  get(boost::edge_weight, part),
117  boost::parity_map(parities));
118 
119  for (auto i : irange(num_vertices(part))) {
120  vertex_to_part[get(index_map, vertex_in_subgraph_to_vertex[i])] =
121  parts + get(parities, i); //return value convertable to 0/1
122  }
123  cuts.push(std::make_pair(cut_cost, parts));
124  parts += 2;
125  };
126 
127  make_cut(0);
128  cost_t k_cut_cost = cost_t();
129  while (--number_of_parts) {
130  auto cut = cuts.top();
131  cuts.pop();
132  k_cut_cost += cut.first;
133  make_cut(cut.second);
134  make_cut(cut.second + 1);
135  }
136 
137  while (!cuts.empty()) {
138  auto cut = cuts.top();
139  cuts.pop();
140  ++id_part;
141  for (auto v: boost::as_array(vertices(graph))) {
142  if (vertex_to_part[get(index_map, v)] == cut.second ||
143  vertex_to_part[get(index_map, v)] == cut.second + 1) {
144  *result = std::make_pair(v, id_part);
145  ++result;
146  }
147  }
148  }
149  return k_cut_cost;
150 }
151 
169 template<typename InGraph
170  ,class OutputIterator
171  ,typename T
172  ,typename P
173  ,typename R>
174 auto k_cut(const InGraph& graph, unsigned int number_of_parts,
175  OutputIterator result, const boost::bgl_named_params<P, T, R>& params) ->
176  typename boost::property_traits<
177  puretype(boost::choose_const_pmap(get_param(params, boost::edge_weight), graph, boost::edge_weight))
178  >::value_type {
179  return k_cut(graph, number_of_parts, result,
180  boost::choose_const_pmap(get_param(params, boost::vertex_index), graph,boost::vertex_index),
181  boost::choose_const_pmap(get_param(params, boost::edge_weight), graph,boost::edge_weight)
182  );
183 }
184 
198 template<typename InGraph, class OutputIterator>
199 auto k_cut(const InGraph& graph, unsigned int number_of_parts, OutputIterator result) ->
200  typename boost::property_traits<puretype(get(boost::edge_weight,graph))>::value_type{
201  return k_cut(graph, number_of_parts, result, boost::no_named_parameters());
202 }
203 
204 }
205 }
206 
207 #endif // PAAL_K_CUT_HPP
#define puretype(t)
for given expression returns its type with removed const and reference
auto irange(T begin, T end)
irange
Definition: irange.hpp:22
This file contains set of simple useful functors or functor adapters.
greater functor
Definition: functors.hpp:478
auto k_cut(const InGraph &graph, unsigned int number_of_parts, OutputIterator result, VertexIndexMap index_map, EdgeWeightMap weight_map) -> typename boost::property_traits< EdgeWeightMap >::value_type
this is solve k_cut problem and return cut_cost example:
Definition: k_cut.hpp:54