ACloudViewer  3.9.4
A Modern Library for 3D Data Processing
CutPursuit_L2.h
Go to the documentation of this file.
1 // ----------------------------------------------------------------------------
2 // - CloudViewer: www.cloudViewer.org -
3 // ----------------------------------------------------------------------------
4 // Copyright (c) 2018-2024 www.cloudViewer.org
5 // SPDX-License-Identifier: MIT
6 // ----------------------------------------------------------------------------
7 
8 #pragma once
9 
10 #include "CutPursuit.h"
11 
12 namespace CP {
13 template <typename T>
14 struct CutPursuit_L2 : public CutPursuit<T> {
15  //=============================================================================================
16  //============================= COMPUTE ENERGY
17  //===========================================
18  //=============================================================================================
19  std::pair<T, T> compute_energy() override {
20  VertexAttributeMap<T> vertex_attribute_map =
21  boost::get(boost::vertex_bundle, this->main_graph);
22  EdgeAttributeMap<T> edge_attribute_map =
23  boost::get(boost::edge_bundle, this->main_graph);
24  // the first element pair_energy of is the fidelity and the second the
25  // penalty
26  std::pair<T, T> pair_energy;
27  T energy = 0;
28  // #pragma omp parallel for private(i_dim) if (this->parameter.parallel)
29  // schedule(static) reduction(+:energy,i)
30  for (uint32_t ind_ver = 0; ind_ver < this->nVertex; ind_ver++) {
31  VertexDescriptor<T> i_ver =
32  boost::vertex(ind_ver, this->main_graph);
33  for (uint32_t i_dim = 0; i_dim < this->dim; i_dim++) {
34  energy += .5 * vertex_attribute_map(i_ver).weight *
35  pow(vertex_attribute_map(i_ver).observation[i_dim] -
36  vertex_attribute_map(i_ver).value[i_dim],
37  2);
38  }
39  }
40  pair_energy.first = energy;
41  energy = 0;
42  EdgeIterator<T> i_edg,
43  i_edg_end = boost::edges(this->main_graph).second;
44  for (i_edg = boost::edges(this->main_graph).first; i_edg != i_edg_end;
45  ++i_edg) {
46  if (!edge_attribute_map(*i_edg).realEdge) {
47  continue;
48  }
49  energy += .5 * edge_attribute_map(*i_edg).isActive *
50  this->parameter.reg_strenth *
51  edge_attribute_map(*i_edg).weight;
52  }
53  pair_energy.second = energy;
54  return pair_energy;
55  }
56 
57  //=============================================================================================
58  //============================= SPLIT
59  //===========================================
60  //=============================================================================================
61  size_t split()
62  override { // split the graph by trying to find the best binary
63  // partition each components is split into B and notB
64  // for each components we associate the value h_1 and
65  // h_2 to vertices in B or notB the affectation as well
66  // as h_1 and h_2 are computed alternatively
67  // tic();
68  //--------loading
69  // structures---------------------------------------------------------------
70  uint32_t nb_comp = static_cast<uint32_t>(this->components.size());
71  VertexAttributeMap<T> vertex_attribute_map =
72  boost::get(boost::vertex_bundle, this->main_graph);
73  VertexIndexMap<T> vertex_index_map =
74  boost::get(boost::vertex_index, this->main_graph);
75  // stores wether each vertex is B or not
76  std::vector<bool> binary_label(this->nVertex);
77  // initialize the binary partition with kmeans
78  this->init_labels(binary_label);
79  // centers is the value of each binary component in the optimal
80  // partition
81  VectorOfCentroids<T> centers(nb_comp, this->dim);
82  //-----main
83  // loop----------------------------------------------------------------
84  // the optimal flow is iteratively approximated
85  for (uint32_t i_step = 1; i_step <= this->parameter.flow_steps;
86  i_step++) {
87  // the regularization strength at this step
88  // compute h_1 and h_2
89  centers = VectorOfCentroids<T>(nb_comp, this->dim);
90  this->compute_centers(centers, nb_comp, binary_label);
91  this->set_capacities(centers);
92 
93  // update the capacities of the flow graph
94  boost::boykov_kolmogorov_max_flow(
95  this->main_graph,
100  get(boost::vertex_index, this->main_graph), this->source,
101  this->sink);
102 
103  for (uint32_t ind_com = 0; ind_com < nb_comp; ind_com++) {
104  if (this->saturated_components[ind_com]) {
105  continue;
106  }
107  for (uint32_t i_ver = 0;
108  i_ver < this->components[ind_com].size(); i_ver++) {
109  binary_label[vertex_index_map(
110  this->components[ind_com][i_ver])] =
111  (vertex_attribute_map(
112  this->components[ind_com][i_ver])
113  .color ==
114  vertex_attribute_map(this->sink).color);
115  }
116  }
117  }
118 
119  size_t saturation = this->activate_edges();
120  return saturation;
121  }
122 
123  //=============================================================================================
124  //============================= INIT_L2 ======
125  //===========================================
126  //=============================================================================================
127  inline void init_labels(
128  std::vector<bool>&
129  binary_label) { //-----initialize the labelling for each
130  // components with
131  // kmeans------------------------------
132  VertexAttributeMap<T> vertex_attribute_map =
133  boost::get(boost::vertex_bundle, this->main_graph);
134  VertexIndexMap<T> vertex_index_map =
135  boost::get(boost::vertex_index, this->main_graph);
136  uint32_t nb_comp = static_cast<uint32_t>(this->components.size());
137 
138  // #pragma omp parallel for private(ind_com) //if (nb_comp>=8)
139  // schedule(dynamic)
140 #ifdef OPENMP
141 #pragma omp parallel for if (nb_comp >= omp_get_num_threads()) schedule(dynamic)
142 #endif
143  for (uint32_t ind_com = 0; ind_com < nb_comp; ind_com++) {
144  std::vector<std::vector<T>> kernels(2, std::vector<T>(this->dim));
145  T total_weight[2];
146  T best_energy;
147  T current_energy;
148  uint32_t comp_size =
149  static_cast<uint32_t>(this->components[ind_com].size());
150  std::vector<bool> potential_label(comp_size);
151  std::vector<T> energy_array(comp_size);
152 
153  if (this->saturated_components[ind_com] || comp_size <= 1) {
154  continue;
155  }
156  for (uint32_t init_kmeans = 0;
157  init_kmeans < this->parameter.kmeans_resampling;
158  init_kmeans++) { // proceed to several initilialisation of
159  // kmeans and pick up the best one
160  //----- initialization with KM++ ------------------
161  uint32_t first_kernel = std::rand() % comp_size,
162  second_kernel = 0; // first kernel attributed
163  for (uint32_t i_dim = 0; i_dim < this->dim; i_dim++) {
164  kernels[0][i_dim] =
165  vertex_attribute_map(
166  this->components[ind_com][first_kernel])
167  .observation[i_dim];
168  }
169  best_energy = 0; // now compute the square distance of each
170  // pouint32_tto this kernel
171 #ifdef OPENMP
172 #pragma omp parallel for if (nb_comp < omp_get_num_threads()) \
173  shared(best_energy) schedule(static)
174 #endif
175  for (uint32_t i_ver = 0; i_ver < comp_size; i_ver++) {
176  energy_array[i_ver] = 0;
177  for (uint32_t i_dim = 0; i_dim < this->dim; i_dim++) {
178  energy_array[i_ver] +=
179  pow(vertex_attribute_map(
180  this->components[ind_com][i_ver])
181  .observation[i_dim] -
182  kernels[0][i_dim],
183  2) *
184  vertex_attribute_map(
185  this->components[ind_com][i_ver])
186  .weight;
187  }
188  best_energy += energy_array[i_ver];
189  } // we now generate a random number to determinate which node
190  // will be the second kernel
191  T random_sample = ((T)(rand())) / ((T)(RAND_MAX));
192  current_energy = best_energy * random_sample;
193  for (uint32_t i_ver = 0; i_ver < comp_size; i_ver++) {
194  current_energy -= energy_array[i_ver];
195  if (current_energy <
196  0) { // we have selected the second kernel
197  second_kernel = i_ver;
198  break;
199  }
200  }
201  for (uint32_t i_dim = 0; i_dim < this->dim;
202  i_dim++) { // now fill the second kernel
203  kernels[1][i_dim] =
204  vertex_attribute_map(
205  this->components[ind_com][second_kernel])
206  .observation[i_dim];
207  }
208  //----main kmeans loop-----
209  for (uint32_t ite_kmeans = 0;
210  ite_kmeans < this->parameter.kmeans_ite; ite_kmeans++) {
211  //--affectation step: associate each node with its closest
212  // kernel-------------------
213 #ifdef OPENMP
214 #pragma omp parallel for if (nb_comp < omp_get_num_threads()) \
215  shared(potential_label) schedule(static)
216 #endif
217  for (uint32_t i_ver = 0; i_ver < comp_size; i_ver++) {
218  std::vector<T> distance_kernels(2);
219  for (uint32_t i_dim = 0; i_dim < this->dim; i_dim++) {
220  distance_kernels[0] += pow(
221  vertex_attribute_map(
222  this->components[ind_com][i_ver])
223  .observation[i_dim] -
224  kernels[0][i_dim],
225  2);
226  distance_kernels[1] += pow(
227  vertex_attribute_map(
228  this->components[ind_com][i_ver])
229  .observation[i_dim] -
230  kernels[1][i_dim],
231  2);
232  }
233  potential_label[i_ver] =
234  distance_kernels[0] > distance_kernels[1];
235  }
236  //-----computation of the new
237  // kernels----------------------------
238  total_weight[0] = 0.;
239  total_weight[1] = 0.;
240  for (uint32_t i_dim = 0; i_dim < this->dim; i_dim++) {
241  kernels[0][i_dim] = 0;
242  kernels[1][i_dim] = 0;
243  }
244 #ifdef OPENMP
245 #pragma omp parallel for if (nb_comp < omp_get_num_threads()) \
246  shared(potential_label) schedule(static)
247 #endif
248  for (uint32_t i_ver = 0; i_ver < comp_size; i_ver++) {
249  if (vertex_attribute_map(
250  this->components[ind_com][i_ver])
251  .weight == 0) {
252  continue;
253  }
254  if (potential_label[i_ver]) {
255  total_weight[0] +=
256  vertex_attribute_map(
257  this->components[ind_com][i_ver])
258  .weight;
259  for (uint32_t i_dim = 0; i_dim < this->dim;
260  i_dim++) {
261  kernels[0][i_dim] +=
262  vertex_attribute_map(
263  this->components[ind_com]
264  [i_ver])
265  .observation[i_dim] *
266  vertex_attribute_map(
267  this->components[ind_com]
268  [i_ver])
269  .weight;
270  }
271  } else {
272  total_weight[1] +=
273  vertex_attribute_map(
274  this->components[ind_com][i_ver])
275  .weight;
276  for (uint32_t i_dim = 0; i_dim < this->dim;
277  i_dim++) {
278  kernels[1][i_dim] +=
279  vertex_attribute_map(
280  this->components[ind_com]
281  [i_ver])
282  .observation[i_dim] *
283  vertex_attribute_map(
284  this->components[ind_com]
285  [i_ver])
286  .weight;
287  }
288  }
289  }
290  if ((total_weight[0] == 0) || (total_weight[1] == 0)) {
291  // std::cout << "kmeans error : " << comp_size <<
292  // std::endl;
293  break;
294  }
295  for (uint32_t i_dim = 0; i_dim < this->dim; i_dim++) {
296  kernels[0][i_dim] = kernels[0][i_dim] / total_weight[0];
297  kernels[1][i_dim] = kernels[1][i_dim] / total_weight[1];
298  }
299  }
300  //----compute the associated energy ------
301  current_energy = 0;
302 #ifdef OPENMP
303 #pragma omp parallel for if (nb_comp < omp_get_num_threads()) \
304  shared(potential_label) schedule(static)
305 #endif
306  for (uint32_t i_ver = 0; i_ver < comp_size; i_ver++) {
307  for (uint32_t i_dim = 0; i_dim < this->dim; i_dim++) {
308  if (potential_label[i_ver]) {
309  current_energy +=
310  pow(vertex_attribute_map(
311  this->components[ind_com]
312  [i_ver])
313  .observation[i_dim] -
314  kernels[0][i_dim],
315  2) *
316  vertex_attribute_map(
317  this->components[ind_com][i_ver])
318  .weight;
319  } else {
320  current_energy +=
321  pow(vertex_attribute_map(
322  this->components[ind_com]
323  [i_ver])
324  .observation[i_dim] -
325  kernels[1][i_dim],
326  2) *
327  vertex_attribute_map(
328  this->components[ind_com][i_ver])
329  .weight;
330  }
331  }
332  }
333  if (current_energy < best_energy) {
334  best_energy = current_energy;
335  for (uint32_t i_ver = 0; i_ver < comp_size; i_ver++) {
336  binary_label[vertex_index_map(
337  this->components[ind_com][i_ver])] =
338  potential_label[i_ver];
339  }
340  }
341  }
342  }
343  }
344 
345  //=============================================================================================
346  //============================= COMPUTE_CENTERS_L2
347  //==========================================
348  //=============================================================================================
349  inline void compute_centers(VectorOfCentroids<T>& centers,
350  const uint32_t& nb_comp,
351  const std::vector<bool>& binary_label) {
352  // compute for each component the values of h_1 and h_2
353 #ifdef OPENMP
354 #pragma omp parallel for if (nb_comp >= omp_get_num_threads()) schedule(dynamic)
355 #endif
356  for (uint32_t ind_com = 0; ind_com < nb_comp; ind_com++) {
357  if (this->saturated_components[ind_com]) {
358  continue;
359  }
360  compute_center(centers.centroids[ind_com], ind_com, binary_label);
361  }
362  }
363 
364  //=============================================================================================
365  //============================= COMPUTE_CENTERS_L2
366  //==========================================
367  //=============================================================================================
368  inline void compute_center(std::vector<std::vector<T>>& center,
369  const uint32_t& ind_com,
370  const std::vector<bool>& binary_label) {
371  // compute for each component the values of the centroids corresponding
372  // to the optimal binary partition
373  VertexAttributeMap<T> vertex_attribute_map =
374  boost::get(boost::vertex_bundle, this->main_graph);
375  VertexIndexMap<T> vertex_index_map =
376  boost::get(boost::vertex_index, this->main_graph);
377  T total_weight[2];
378  total_weight[0] = 0.;
379  total_weight[1] = 0.;
380  // #pragma omp parallel for if (this->parameter.parallel)
381  for (uint32_t i_ver = 0; i_ver < this->components[ind_com].size();
382  i_ver++) {
383  if (vertex_attribute_map(this->components[ind_com][i_ver]).weight ==
384  0) {
385  continue;
386  }
387  if (binary_label[vertex_index_map(
388  this->components[ind_com][i_ver])]) {
389  total_weight[0] +=
390  vertex_attribute_map(this->components[ind_com][i_ver])
391  .weight;
392  for (uint32_t i_dim = 0; i_dim < this->dim; i_dim++) {
393  center[0][i_dim] +=
394  vertex_attribute_map(
395  this->components[ind_com][i_ver])
396  .observation[i_dim] *
397  vertex_attribute_map(
398  this->components[ind_com][i_ver])
399  .weight;
400  }
401  } else {
402  total_weight[1] +=
403  vertex_attribute_map(this->components[ind_com][i_ver])
404  .weight;
405  for (uint32_t i_dim = 0; i_dim < this->dim; i_dim++) {
406  center[1][i_dim] +=
407  vertex_attribute_map(
408  this->components[ind_com][i_ver])
409  .observation[i_dim] *
410  vertex_attribute_map(
411  this->components[ind_com][i_ver])
412  .weight;
413  }
414  }
415  }
416  if ((total_weight[0] == 0) || (total_weight[1] == 0)) {
417  // the component is saturated
418  this->saturateComponent(ind_com);
419  for (uint32_t i_dim = 0; i_dim < this->dim; i_dim++) {
420  center[0][i_dim] =
421  vertex_attribute_map(this->components[ind_com][0])
422  .value[i_dim];
423  center[1][i_dim] =
424  vertex_attribute_map(this->components[ind_com][0])
425  .value[i_dim];
426  }
427  } else {
428  for (uint32_t i_dim = 0; i_dim < this->dim; i_dim++) {
429  center[0][i_dim] = center[0][i_dim] / total_weight[0];
430  center[1][i_dim] = center[1][i_dim] / total_weight[1];
431  }
432  }
433  }
434 
435  //=============================================================================================
436  //============================= SET_CAPACITIES
437  //==========================================
438  //=============================================================================================
439  inline void set_capacities(const VectorOfCentroids<T>& centers) {
440  VertexAttributeMap<T> vertex_attribute_map =
441  boost::get(boost::vertex_bundle, this->main_graph);
442  EdgeAttributeMap<T> edge_attribute_map =
443  boost::get(boost::edge_bundle, this->main_graph);
444  //----first compute the capacity in sink/node
445  // edges------------------------------------ #pragma omp parallel for if
446  //(this->parameter.parallel) schedule(dynamic)
447  uint32_t nb_comp = static_cast<uint32_t>(this->components.size());
448 #ifdef OPENMP
449 #pragma omp parallel for if (nb_comp >= omp_get_num_threads()) schedule(dynamic)
450 #endif
451  for (uint32_t ind_com = 0; ind_com < nb_comp; ind_com++) {
452  VertexDescriptor<T> desc_v;
453  EdgeDescriptor desc_source2v, desc_v2sink, desc_v2source;
454  T cost_B, cost_notB; // the cost of being in B or not B, local for
455  // each component
456  if (this->saturated_components[ind_com]) {
457  continue;
458  }
459  for (uint32_t i_ver = 0; i_ver < this->components[ind_com].size();
460  i_ver++) {
461  desc_v = this->components[ind_com][i_ver];
462  // because of the adjacency structure NEVER access edge
463  // (source,v) directly!
464  desc_v2source =
465  boost::edge(desc_v, this->source, this->main_graph)
466  .first;
467  desc_source2v =
468  edge_attribute_map(desc_v2source)
469  .edge_reverse; // use edge_reverse instead
470  desc_v2sink =
471  boost::edge(desc_v, this->sink, this->main_graph).first;
472  cost_B = 0;
473  cost_notB = 0;
474  if (vertex_attribute_map(desc_v).weight ==
475  0) { // no observation - no cut
476  edge_attribute_map(desc_source2v).capacity = 0;
477  edge_attribute_map(desc_v2sink).capacity = 0;
478  continue;
479  }
480  for (uint32_t i_dim = 0; i_dim < this->dim; i_dim++) {
481  cost_B += 0.5 * vertex_attribute_map(desc_v).weight *
482  (pow(centers.centroids[ind_com][0][i_dim], 2) -
483  2 * (centers.centroids[ind_com][0][i_dim] *
484  vertex_attribute_map(desc_v)
485  .observation[i_dim]));
486  cost_notB += 0.5 * vertex_attribute_map(desc_v).weight *
487  (pow(centers.centroids[ind_com][1][i_dim], 2) -
488  2 * (centers.centroids[ind_com][1][i_dim] *
489  vertex_attribute_map(desc_v)
490  .observation[i_dim]));
491  }
492  if (cost_B > cost_notB) {
493  edge_attribute_map(desc_source2v).capacity =
494  cost_B - cost_notB;
495  edge_attribute_map(desc_v2sink).capacity = 0.;
496  } else {
497  edge_attribute_map(desc_source2v).capacity = 0.;
498  edge_attribute_map(desc_v2sink).capacity =
499  cost_notB - cost_B;
500  }
501  }
502  }
503  //----then set the vertex to vertex edges
504  //---------------------------------------------
505  EdgeIterator<T> i_edg, i_edg_end;
506  for (boost::tie(i_edg, i_edg_end) = boost::edges(this->main_graph);
507  i_edg != i_edg_end; ++i_edg) {
508  if (!edge_attribute_map(*i_edg).realEdge) {
509  continue;
510  }
511  if (!edge_attribute_map(*i_edg).isActive) {
512  edge_attribute_map(*i_edg).capacity =
513  edge_attribute_map(*i_edg).weight *
514  this->parameter.reg_strenth;
515  } else {
516  edge_attribute_map(*i_edg).capacity = 0;
517  }
518  }
519  }
520 
521  //=============================================================================================
522  //================================= COMPUTE_VALUE
523  //=========================================
524  //=============================================================================================
525  std::pair<std::vector<T>, T> compute_value(
526  const uint32_t& ind_com) override {
527  VertexAttributeMap<T> vertex_attribute_map =
528  boost::get(boost::vertex_bundle, this->main_graph);
529  T total_weight = 0;
530  std::vector<T> compValue(this->dim);
531  std::fill((compValue.begin()), (compValue.end()), 0);
532 #ifdef OPENMP
533 #pragma omp parallel for if (this->parameter.parallel) schedule(static)
534 #endif
535  for (uint32_t ind_ver = 0; ind_ver < this->components[ind_com].size();
536  ++ind_ver) {
537  total_weight +=
538  vertex_attribute_map(this->components[ind_com][ind_ver])
539  .weight;
540  for (uint32_t i_dim = 0; i_dim < this->dim; i_dim++) {
541  compValue[i_dim] +=
542  vertex_attribute_map(this->components[ind_com][ind_ver])
543  .observation[i_dim] *
544  vertex_attribute_map(this->components[ind_com][ind_ver])
545  .weight;
546  }
547  vertex_attribute_map(this->components[ind_com][ind_ver])
548  .in_component = ind_com;
549  }
550  for (uint32_t i_dim = 0; i_dim < this->dim; i_dim++) {
551  compValue[i_dim] = compValue[i_dim] / total_weight;
552  }
553  for (uint32_t ind_ver = 0; ind_ver < this->components[ind_com].size();
554  ++ind_ver) {
555  for (uint32_t i_dim = 0; i_dim < this->dim; i_dim++) {
556  vertex_attribute_map(this->components[ind_com][ind_ver])
557  .value[i_dim] = compValue[i_dim];
558  }
559  }
560  return std::pair<std::vector<T>, T>(compValue, total_weight);
561  }
562 
563  //=============================================================================================
564  //================================= COMPUTE_MERGE_GAIN
565  //=========================================
566  //=============================================================================================
567  std::pair<std::vector<T>, T> compute_merge_gain(
568  const VertexDescriptor<T>& comp1,
569  const VertexDescriptor<T>& comp2) override {
570  VertexAttributeMap<T> reduced_vertex_attribute_map =
571  boost::get(boost::vertex_bundle, this->reduced_graph);
572  std::vector<T> merge_value(this->dim);
573  T gain = 0;
574  // compute the value obtained by mergeing the two connected components
575  for (uint32_t i_dim = 0; i_dim < this->dim; i_dim++) {
576  merge_value[i_dim] =
577  (reduced_vertex_attribute_map(comp1).weight *
578  reduced_vertex_attribute_map(comp1).value[i_dim] +
579  reduced_vertex_attribute_map(comp2).weight *
580  reduced_vertex_attribute_map(comp2).value[i_dim]) /
581  (reduced_vertex_attribute_map(comp1).weight +
582  reduced_vertex_attribute_map(comp2).weight);
583  gain += 0.5 *
584  (pow(merge_value[i_dim], 2) *
585  (reduced_vertex_attribute_map(comp1).weight +
586  reduced_vertex_attribute_map(comp2).weight) -
587  pow(reduced_vertex_attribute_map(comp1).value[i_dim], 2) *
588  reduced_vertex_attribute_map(comp1).weight -
589  pow(reduced_vertex_attribute_map(comp2).value[i_dim], 2) *
590  reduced_vertex_attribute_map(comp2).weight);
591  }
592  return std::pair<std::vector<T>, T>(merge_value, gain);
593  }
594 };
595 } // namespace CP
long vertex_index
std::vector< std::vector< std::vector< T > > > centroids
Definition: Common.h:109
Definition: API.h:123
boost::vec_adj_list_vertex_property_map< Graph< T >, Graph< T > *, VertexAttribute< T >, VertexAttribute< T > &, boost::vertex_bundle_t > VertexAttributeMap
Definition: Graph.h:92
typename boost::graph_traits< Graph< T > >::edge_iterator EdgeIterator
Definition: Graph.h:84
boost::graph_traits< boost::adjacency_list< boost::vecS, boost::vecS, boost::directedS > >::edge_descriptor EdgeDescriptor
Definition: Graph.h:22
typename boost::graph_traits< CP::Graph< T > >::vertex_descriptor VertexDescriptor
Definition: Graph.h:75
typename boost::property_map< Graph< T >, boost::vertex_index_t >::type VertexIndexMap
Definition: Graph.h:103
boost::adj_list_edge_property_map< boost::directed_tag, EdgeAttribute< T >, EdgeAttribute< T > &, uint64_t, CP::EdgeAttribute< T >, boost::edge_bundle_t > EdgeAttributeMap
Definition: Graph.h:100
Matrix< T > random_sample(Matrix< T > &srcMatrix, size_t size, bool remove=false)
Definition: sampling.h:40
void compute_center(std::vector< std::vector< T >> &center, const uint32_t &ind_com, const std::vector< bool > &binary_label)
size_t split() override
Definition: CutPursuit_L2.h:61
void compute_centers(VectorOfCentroids< T > &centers, const uint32_t &nb_comp, const std::vector< bool > &binary_label)
void init_labels(std::vector< bool > &binary_label)
std::pair< std::vector< T >, T > compute_value(const uint32_t &ind_com) override
void set_capacities(const VectorOfCentroids< T > &centers)
std::pair< std::vector< T >, T > compute_merge_gain(const VertexDescriptor< T > &comp1, const VertexDescriptor< T > &comp2) override
std::pair< T, T > compute_energy() override
Definition: CutPursuit_L2.h:19
CPparameter< T > parameter
Definition: CutPursuit.h:65
Graph< T > main_graph
Definition: CutPursuit.h:45
std::vector< std::vector< VertexDescriptor< T > > > components
Definition: CutPursuit.h:49
VertexDescriptor< T > sink
Definition: CutPursuit.h:58
VertexDescriptor< T > source
Definition: CutPursuit.h:57
size_t activate_edges(bool allows_saturation=true)
Definition: CutPursuit.h:298
uint32_t dim
Definition: CutPursuit.h:59
uint32_t nVertex
Definition: CutPursuit.h:60
std::vector< bool > saturated_components
Definition: CutPursuit.h:53
Graph< T > reduced_graph
Definition: CutPursuit.h:46
void saturateComponent(const uint32_t &ind_com)
Definition: CutPursuit.h:835