34 #include <unordered_map>
36 #include <boost/graph/stoer_wagner_min_cut.hpp>
37 #include <boost/property_map/property_map.hpp>
38 #include <boost/typeof/typeof.hpp>
41 #include "Graclus/metisLib/metis.h"
52 GraclusGraph(
const std::vector<std::pair<int, int>>& edges,
53 const std::vector<int>& weights) {
54 CHECK_EQ(edges.size(), weights.size());
56 std::unordered_map<int, std::vector<std::pair<int, int>>> adjacency_list;
57 for (
size_t i = 0; i < edges.size(); ++i) {
58 const auto& edge = edges[i];
59 const auto weight = weights[i];
60 const int vertex_idx1 = GetVertexIdx(edge.first);
61 const int vertex_idx2 = GetVertexIdx(edge.second);
62 adjacency_list[vertex_idx1].emplace_back(vertex_idx2, weight);
63 adjacency_list[vertex_idx2].emplace_back(vertex_idx1, weight);
66 xadj_.reserve(vertex_id_to_idx_.size() + 1);
67 adjncy_.reserve(2 * edges.size());
68 adjwgt_.reserve(2 * edges.size());
71 for (
size_t i = 0; i < vertex_id_to_idx_.size(); ++i) {
72 xadj_.push_back(edge_idx);
74 if (adjacency_list.count(i) == 0) {
78 for (
const auto& edge : adjacency_list[i]) {
80 adjncy_.push_back(edge.first);
81 adjwgt_.push_back(edge.second);
85 xadj_.push_back(edge_idx);
87 CHECK_EQ(edge_idx, 2 * edges.size());
88 CHECK_EQ(xadj_.size(), vertex_id_to_idx_.size() + 1);
89 CHECK_EQ(adjncy_.size(), 2 * edges.size());
90 CHECK_EQ(adjwgt_.size(), 2 * edges.size());
94 data.nvtxs = vertex_id_to_idx_.size();
95 data.nedges = 2 * edges.size();
98 data.xadj = xadj_.data();
99 data.adjncy = adjncy_.data();
102 data.adjwgt = adjwgt_.data();
104 data.adjwgtsum =
nullptr;
105 data.label =
nullptr;
110 data.bndptr =
data.bndind =
nullptr;
111 data.rinfo =
nullptr;
112 data.vrinfo =
nullptr;
113 data.nrinfo =
nullptr;
116 data.nvwgt =
nullptr;
117 data.npwgts =
nullptr;
119 data.vsize =
nullptr;
121 data.coarser =
data.finer =
nullptr;
124 int GetVertexIdx(
const int id) {
125 const auto it = vertex_id_to_idx_.find(
id);
126 if (it == vertex_id_to_idx_.end()) {
127 const int idx = vertex_id_to_idx_.size();
128 vertex_id_to_idx_.emplace(
id, idx);
129 vertex_idx_to_id_.emplace(idx,
id);
136 int GetVertexId(
const int idx) {
return vertex_idx_to_id_.at(idx); }
141 std::unordered_map<int, int> vertex_id_to_idx_;
142 std::unordered_map<int, int> vertex_idx_to_id_;
143 std::vector<idxtype> xadj_;
144 std::vector<idxtype> adjncy_;
145 std::vector<idxtype> adjwgt_;
151 const std::vector<std::pair<int, int>>& edges,
152 const std::vector<int>& weights,
int* cut_weight,
153 std::vector<char>* cut_labels) {
154 CHECK_EQ(edges.size(), weights.size());
155 CHECK_GE(edges.size(), 2);
157 typedef boost::property<boost::edge_weight_t, int> edge_weight_t;
158 typedef boost::adjacency_list<boost::vecS, boost::vecS, boost::undirectedS,
159 boost::no_property, edge_weight_t>
162 int max_vertex_index = 0;
163 for (
const auto& edge : edges) {
164 CHECK_GE(edge.first, 0);
165 CHECK_GE(edge.second, 0);
166 max_vertex_index = std::max(max_vertex_index, edge.first);
167 max_vertex_index = std::max(max_vertex_index, edge.second);
170 const undirected_graph_t graph(edges.begin(), edges.end(), weights.begin(),
171 max_vertex_index + 1, edges.size());
173 const auto parities = boost::make_one_bit_color_map(
177 boost::stoer_wagner_min_cut(graph, boost::get(boost::edge_weight, graph),
178 boost::parity_map(parities));
180 cut_labels->resize(boost::num_vertices(graph));
181 for (
size_t i = 0; i < boost::num_vertices(graph); ++i) {
182 (*cut_labels)[i] = boost::get(parities, i);
187 const std::vector<std::pair<int, int>>& edges,
188 const std::vector<int>& weights,
const int num_parts) {
189 GraclusGraph graph(edges, weights);
192 amax((graph.data.nvtxs) / (40 * log2_metis(num_parts)), 20 * (num_parts));
194 std::vector<idxtype> cut_labels(graph.data.nvtxs);
200 int chain_length = 0;
202 int var_num_parts = num_parts;
204 MLKKM_PartGraphKway(&graph.data.nvtxs, graph.data.xadj, graph.data.adjncy,
205 graph.data.vwgt, graph.data.adjwgt, &wgtflag, &numflag,
206 &var_num_parts, &chain_length, options, &edgecut,
207 cut_labels.data(), levels);
209 float lbvec[MAXNCON];
210 ComputePartitionBalance(&graph.data, num_parts, cut_labels.data(), lbvec);
212 ComputeNCut(&graph.data, &cut_labels[0], num_parts);
214 std::unordered_map<int, int> labels;
215 for (
size_t idx = 0; idx < cut_labels.size(); ++idx) {
216 labels.emplace(graph.GetVertexId(idx), cut_labels[idx]);
std::unordered_map< int, int > ComputeNormalizedMinGraphCut(const std::vector< std::pair< int, int >> &edges, const std::vector< int > &weights, const int num_parts)
void ComputeMinGraphCutStoerWagner(const std::vector< std::pair< int, int >> &edges, const std::vector< int > &weights, int *cut_weight, std::vector< char > *cut_labels)