2 #ifndef ANDRES_GRAPH_TWOCUT_LIFTED_KERNIGHAN_LIN_HXX
3 #define ANDRES_GRAPH_TWOCUT_LIFTED_KERNIGHAN_LIN_HXX
10 namespace twocut_lifted {
13 std::size_t numberOfIterations { std::numeric_limits<std::size_t>::max() };
14 double epsilon { 1e-9 };
17 template<
typename ORIGINAL_GRAPH>
32 template<
typename ORIGINAL_GRAPH,
typename LIFTED_GRAPH,
typename SET,
typename ECA>
35 const ORIGINAL_GRAPH& original_graph,
36 const LIFTED_GRAPH& lifted_graph,
37 const ECA& edge_costs,
47 double difference { std::numeric_limits<double>::lowest() };
48 std::size_t new_label;
51 auto gain_from_merging = .0;
53 auto compute_differences = [&](
const SET& A, std::size_t label_A, std::size_t label_B)
55 for (
long int i = 0; i < A.size(); ++i)
59 std::size_t ref_cnt = 0;
61 for (
auto it = lifted_graph.adjacenciesFromVertexBegin(A[i]); it != lifted_graph.adjacenciesFromVertexEnd(A[i]); ++it)
66 diffInt += edge_costs[it->edge()];
67 else if (lbl == label_B)
68 diffExt += edge_costs[it->edge()];
71 for (
auto it = original_graph.adjacenciesFromVertexBegin(A[i]); it != original_graph.adjacenciesFromVertexEnd(A[i]); ++it)
79 gain_from_merging += diffExt;
90 compute_differences(A, label_A, label_B);
91 compute_differences(B, label_B, label_A);
93 gain_from_merging /= 2.0;
95 std::vector<std::size_t> border;
105 std::vector<Move> moves;
106 double cumulative_diff = .0;
107 std::pair<double, std::size_t> max_move { std::numeric_limits<double>::lowest(), 0 };
109 for (std::size_t k = 0; k < settings.numberOfIterations; ++k)
113 if (B.empty() && k == 0)
124 std::size_t size = border.size();
126 for (std::size_t i = 0; i < size; )
128 std::swap(border[i], border[--size]);
140 border.erase(border.begin() + size, border.end());
148 if (old_label == label_A)
149 m.new_label = label_B;
151 m.new_label = label_A;
154 for (
auto it = lifted_graph.adjacenciesFromVertexBegin(m.v); it != lifted_graph.adjacenciesFromVertexEnd(m.v); ++it)
162 if (lbl == m.new_label)
163 buffer.
differences[it->vertex()] -= 2.0*edge_costs[it->edge()];
165 else if (lbl == old_label)
166 buffer.
differences[it->vertex()] += 2.0*edge_costs[it->edge()];
169 for (
auto it = original_graph.adjacenciesFromVertexBegin(m.v); it != original_graph.adjacenciesFromVertexEnd(m.v); ++it)
177 if (lbl == m.new_label)
180 else if (lbl == old_label)
185 border.push_back(it->vertex());
191 buffer.
differences[m.v] = std::numeric_limits<double>::lowest();
195 cumulative_diff += m.difference;
197 if (cumulative_diff > max_move.first)
198 max_move = std::make_pair(cumulative_diff, moves.size());
202 if (gain_from_merging > max_move.first && gain_from_merging > settings.epsilon)
204 A.insert(A.end(), B.begin(), B.end());
214 return gain_from_merging;
216 else if (max_move.first > settings.epsilon)
219 for (std::size_t i = max_move.second; i < moves.size(); ++i)
223 if (moves[i].new_label == label_B)
233 A.erase(std::partition(A.begin(), A.end(), [&](std::size_t a) {
return !buffer.
is_moved[a]; }), A.end());
234 B.erase(std::partition(B.begin(), B.end(), [&](std::size_t b) {
return !buffer.
is_moved[b]; }), B.end());
236 for (std::size_t i = 0; i < max_move.second; ++i)
238 if (moves[i].new_label == label_B)
239 B.push_back(moves[i].v);
241 A.push_back(moves[i].v);
243 return max_move.first;
246 for (std::size_t i = 0; i < moves.size(); ++i)
247 if (moves[i].new_label == label_B)
255 template<
typename ORIGINAL_GRAPH,
typename LIFTED_GRAPH,
typename SET,
typename ECA>
258 const ORIGINAL_GRAPH& original_graph,
259 const LIFTED_GRAPH& lifted_graph,
260 const ECA& edge_costs,
266 return kernighanLin(original_graph, lifted_graph, edge_costs, A, B, buffer, settings);