21 #include <boost/graph/boykov_kolmogorov_max_flow.hpp>
48 std::vector<std::vector<VertexDescriptor<T>>>
50 std::vector<VertexDescriptor<T>>
54 std::vector<std::vector<EdgeDescriptor>>
68 this->main_graph =
Graph<T>(nbVertex);
70 this->
components = std::vector<std::vector<VertexDescriptor<T>>>(1);
71 this->
root_vertex = std::vector<VertexDescriptor<T>>(1, 0);
79 this->parameter.
cutoff = 0;
94 std::pair<std::vector<T>, std::vector<T>>
run() {
97 if (this->parameter.
verbose > 0) {
98 std::cout <<
"Graph " << boost::num_vertices(this->main_graph)
99 <<
" vertices and " << boost::num_edges(this->main_graph)
100 <<
" edges and observation of dimension " << this->dim
105 T old_energy = energy_zero;
107 std::vector<T> energy_out(this->parameter.
max_ite_main),
112 for (uint32_t ite_main = 1; ite_main <= this->parameter.
max_ite_main;
122 energy_out.push_back((energy.first + energy.second));
124 if (this->parameter.
verbose > 1) {
125 printf(
"Iteration %3i - %4i components - ", ite_main,
127 printf(
"Saturation %5.1f %% - ",
128 (100.0 * saturation) / this->nVertex);
131 printf(
"Quadratic Energy %4.3f %% - ",
132 100 * (energy.first + energy.second) /
137 printf(
"Linear Energy %10.1f - ",
138 energy.first + energy.second);
142 printf(
"KL Energy %4.3f %% - ",
143 100 * (energy.first + energy.second) /
148 printf(
"Quadratic Energy %4.3f %% - ",
149 100 * (energy.first + energy.second) /
157 if (saturation == this->nVertex) {
158 if (this->parameter.
verbose > 1) {
159 std::cout <<
"All components are saturated" <<
std::endl;
163 if ((old_energy - energy.first - energy.second) / (old_energy) <
164 this->parameter.stopping_ratio) {
166 if (this->parameter.
verbose > 1) {
167 std::cout <<
"Stopping criterion reached" <<
std::endl;
173 if (this->parameter.
verbose > 1) {
174 std::cout <<
"Max number of iteration reached" <<
std::endl;
178 old_energy = energy.first + energy.second;
180 if (this->parameter.
cutoff > 0) {
183 return std::pair<std::vector<T>, std::vector<T>>(energy_out, time_out);
206 return std::pair<T, T>(0, 0);
214 const uint32_t& ind_com) {
216 return std::pair<std::vector<T>, T>(std::vector<T>(0), 0);
227 return std::pair<std::vector<T>, T>(std::vector<T>(0), 0);
244 boost::get(boost::edge_bundle, this->main_graph);
246 std::vector<VertexDescriptor<T>>(0);
247 this->
root_vertex[0] = *boost::vertices(this->main_graph).first;
249 static_cast<uint32_t
>(boost::num_vertices(this->main_graph));
250 this->nEdge =
static_cast<uint32_t
>(boost::num_edges(this->main_graph));
253 for (boost::tie(ite_ver, ite_ver_end) =
254 boost::vertices(this->main_graph);
255 ite_ver != ite_ver_end; ++ite_ver) {
258 this->lastIterator = ite_ver;
262 this->source = boost::add_vertex(this->main_graph);
263 this->sink = boost::add_vertex(this->main_graph);
265 static_cast<uint32_t
>(boost::num_edges(this->main_graph));
266 ite_ver = boost::vertices(this->main_graph).first;
267 for (uint32_t ind_ver = 0; ind_ver < this->
nVertex; ind_ver++) {
271 addDoubledge<T>(this->main_graph, this->source,
272 boost::vertex(ind_ver, this->main_graph), 0.,
273 eIndex, edge_attribute_map,
false);
275 addDoubledge<T>(this->main_graph,
276 boost::vertex(ind_ver, this->main_graph),
277 this->sink, 0., eIndex, edge_attribute_map,
false);
288 for (uint32_t ind_com = 0; ind_com < this->
components.size();
304 boost::get(boost::vertex_bundle, this->main_graph);
306 boost::get(boost::edge_bundle, this->main_graph);
308 size_t saturation = 0;
309 uint32_t nb_comp =
static_cast<uint32_t
>(this->
components.size());
313 for (uint32_t ind_com = 0; ind_com < nb_comp; ind_com++) {
317 saturation += this->
components[ind_com].size();
320 std::vector<T> totalWeight(2, 0);
321 for (uint32_t ind_ver = 0;
322 ind_ver < this->
components[ind_com].size(); ind_ver++) {
323 bool isSink = (vertex_attribute_map(
326 vertex_attribute_map(this->sink).color);
329 vertex_attribute_map(
334 vertex_attribute_map(
339 if (allows_saturation &&
340 ((totalWeight[0] == 0) || (totalWeight[1] == 0))) {
343 saturation += this->
components[ind_com].size();
348 uint32_t color_v1, color_v2, color_combination;
349 for (boost::tie(ite_edg, ite_edg_end) = boost::edges(this->main_graph);
350 ite_edg != ite_edg_end; ++ite_edg) {
351 if (!edge_attribute_map(*ite_edg).realEdge) {
354 color_v1 = vertex_attribute_map(
355 boost::source(*ite_edg, this->main_graph))
357 color_v2 = vertex_attribute_map(
358 boost::target(*ite_edg, this->main_graph))
365 color_combination = color_v1 + color_v2;
366 if ((color_combination == 0) || (color_combination == 2) ||
367 (color_combination == 2) ||
368 (color_combination ==
373 edge_attribute_map(*ite_edg).isActive =
true;
374 edge_attribute_map(*ite_edg).capacity = 0;
375 vertex_attribute_map(boost::source(*ite_edg, this->main_graph))
377 vertex_attribute_map(boost::target(*ite_edg, this->main_graph))
414 boost::get(boost::vertex_bundle, this->main_graph);
418 std::vector<bool> edges_seen(this->nEdge,
false);
419 std::vector<bool> vertices_seen(this->nVertex + 2,
false);
420 vertices_seen[vertex_index_map(this->source)] =
true;
421 vertices_seen[vertex_index_map(this->sink)] =
true;
425 for (uint32_t ind_com = 0; ind_com < this->
root_vertex.size();
433 for (uint32_t ind_ver = 0;
434 ind_ver < this->
components[ind_com].size(); ++ind_ver) {
435 vertices_seen[vertex_index_map(
441 vertices_seen, edges_seen);
446 for (ite_ver = boost::vertices(this->main_graph).first;
448 if (vertices_seen[vertex_index_map(*ite_ver)]) {
453 size_t current_component_size =
454 this->
components[vertex_attribute_map(root).in_component]
457 root, current_component_size, vertices_seen, edges_seen));
470 const size_t& size_comp,
471 std::vector<bool>& vertices_seen,
472 std::vector<bool>& edges_seen) {
477 boost::get(boost::edge_bundle, this->main_graph);
482 std::vector<VertexDescriptor<T>>
487 vertices_added.reserve(size_comp);
490 std::vector<VertexDescriptor<T>> vertices_to_add;
491 vertices_to_add.reserve(size_comp);
495 vertices_to_add.push_back(root);
496 while (vertices_to_add.size() >
498 vertex_current = vertices_to_add.back();
500 vertices_to_add.pop_back();
502 if (vertices_seen[vertex_index_map(
507 vertices_added.push_back(vertex_current);
509 vertices_seen[vertex_index_map(vertex_current)] =
512 typename boost::graph_traits<Graph<T>>::out_edge_iterator ite_edg,
514 for (boost::tie(ite_edg, ite_edg_end) =
515 boost::out_edges(vertex_current, this->main_graph);
516 ite_edg != ite_edg_end;
518 edge_current = *ite_edg;
519 if (edge_attribute_map(*ite_edg).isActive ||
520 (edges_seen[edge_index_map(
526 edge_reverse = edge_attribute_map(edge_current).edge_reverse;
527 edges_seen[edge_index_map(edge_current)] =
true;
528 edges_seen[edge_index_map(edge_reverse)] =
true;
529 vertices_to_add.push_back(
530 boost::target(edge_current, this->main_graph));
533 vertices_added.shrink_to_fit();
534 return vertices_added;
546 boost::get(boost::edge_bundle, this->main_graph);
548 boost::get(boost::vertex_bundle, this->main_graph);
551 boost::get(boost::vertex_bundle, this->reduced_graph);
554 #pragma omp parallel for schedule(dynamic)
556 for (uint32_t ind_com = 0; ind_com < this->
components.size();
558 std::pair<std::vector<T>, T> component_values_and_weight =
563 boost::vertex(ind_com, this->reduced_graph);
564 component_attribute_map[reduced_vertex] =
566 component_attribute_map(reduced_vertex).weight =
567 component_values_and_weight.second;
568 for (uint32_t i_dim = 0; i_dim < this->
dim; i_dim++) {
569 component_attribute_map(reduced_vertex).value[i_dim] =
570 component_values_and_weight.first[i_dim];
575 boost::get(boost::edge_bundle, this->reduced_graph);
578 uint32_t ind_border_edge = 0, comp1, comp2, component_source,
581 bool reducedEdgeExists;
582 typename boost::graph_traits<Graph<T>>::edge_iterator ite_edg,
584 for (boost::tie(ite_edg, ite_edg_end) = boost::edges(this->main_graph);
585 ite_edg != ite_edg_end; ++ite_edg) {
586 if (!edge_attribute_map(*ite_edg)
591 edge_current = *ite_edg;
594 comp1 = vertex_attribute_map(
595 boost::source(edge_current, this->main_graph))
597 comp2 = vertex_attribute_map(
598 boost::target(edge_current, this->main_graph))
600 if (comp1 == comp2) {
606 component_source =
std::min(comp1, comp2);
607 component_target =
std::max(comp1, comp2);
610 boost::vertex(component_source, this->reduced_graph);
612 boost::vertex(component_target, this->reduced_graph);
615 boost::tie(border_edge_current, reducedEdgeExists) = boost::edge(
616 source_component, target_component, this->reduced_graph);
617 if (!reducedEdgeExists) {
621 border_edge_current =
622 boost::add_edge(source_component, target_component,
625 border_edge_attribute_map(border_edge_current).index =
627 border_edge_attribute_map(border_edge_current).weight = 0;
631 this->
borders.push_back(std::vector<EdgeDescriptor>(0));
635 border_edge_attribute_map(border_edge_current).weight +=
636 0.5 * edge_attribute_map(edge_current).weight;
637 this->
borders[border_edge_attribute_map(border_edge_current).index]
638 .push_back(edge_current);
654 boost::get(boost::vertex_bundle, this->main_graph);
656 boost::get(boost::vertex_bundle, this->reduced_graph);
658 boost::get(boost::edge_bundle, this->reduced_graph);
660 boost::get(boost::edge_bundle, this->main_graph);
665 typename boost::graph_traits<Graph<T>>::edge_iterator ite_border,
667 typename std::vector<EdgeDescriptor>::iterator ite_border_edge;
669 uint32_t ind_source_component, ind_target_component,
670 border_edge_currentIndex;
676 std::priority_queue<ComponentsFusion<T>,
677 std::vector<ComponentsFusion<T>>,
682 for (boost::tie(ite_border, ite_border_end) =
683 boost::edges(this->reduced_graph);
684 ite_border != ite_border_end; ++ite_border) {
687 border_edge_current = *ite_border;
688 border_edge_currentIndex =
689 border_edge_attribute_map(border_edge_current).index;
692 boost::source(border_edge_current, this->reduced_graph);
694 boost::target(border_edge_current, this->reduced_graph);
696 component_attribute_map(source_component).weight >=
698 component_attribute_map(target_component).weight >=
702 ind_source_component =
static_cast<uint32_t
>(
703 component_index_map(source_component));
704 ind_target_component =
static_cast<uint32_t
>(
705 component_index_map(target_component));
709 std::pair<std::vector<T>, T> merge_gain =
712 gain = merge_gain.second +
713 border_edge_attribute_map(border_edge_current).weight *
718 ind_source_component, ind_target_component,
719 border_edge_currentIndex, gain);
724 merge_queue.push(mergeing_information);
728 uint32_t n_merged = 0;
732 std::vector<bool> is_merged(this->
components.size(),
false);
734 std::vector<bool> to_destroy(this->
components.size(),
false);
735 while (merge_queue.size() >
745 if (is_merged.at(mergeing_information.
comp1) ||
746 (is_merged.at(mergeing_information.
comp2))) {
756 this->components[mergeing_information.
comp2].end());
760 component_attribute_map(mergeing_information.
comp1).weight +=
761 component_attribute_map(mergeing_information.
comp2).weight;
763 component_attribute_map(mergeing_information.
comp1).value =
766 for (ite_border_edge =
770 this->borders.at(mergeing_information.
border_index).end();
772 edge_attribute_map(*ite_border_edge).isActive =
false;
774 is_merged.at(mergeing_information.
comp1) =
true;
775 is_merged.at(mergeing_information.
comp2) =
true;
776 to_destroy.at(mergeing_information.
comp2) =
true;
780 std::vector<std::vector<VertexDescriptor<T>>> new_components;
781 std::vector<VertexDescriptor<T>> new_root_vertex;
782 std::vector<bool> new_saturated_components;
783 uint32_t ind_new_component = 0;
784 for (uint32_t ind_com = 0; ind_com < this->
components.size();
786 if (to_destroy.at(ind_com)) {
789 new_components.push_back(this->
components.at(ind_com));
790 new_root_vertex.push_back(this->
root_vertex.at(ind_com));
791 new_saturated_components.push_back(
795 for (uint32_t ind_ver = 0;
796 ind_ver < this->
components[ind_com].size(); ++ind_ver) {
797 vertex_attribute_map(this->
components[ind_com][ind_ver]).value =
798 component_attribute_map(
799 boost::vertex(ind_com, this->reduced_graph))
801 vertex_attribute_map(this->
components[ind_com][ind_ver])
802 .in_component = ind_new_component;
823 n_merged =
merge(
true);
825 if (n_merged == 0 || i > 50) {
840 boost::get(boost::edge_bundle, this->main_graph);
842 for (uint32_t i_ver = 0; i_ver < this->
components[ind_com].size();
848 boost::edge(desc_v, this->source, this->main_graph).first;
850 edge_attribute_map(edg_ver2source)
853 boost::edge(desc_v, this->sink, this->main_graph).first;
855 edge_attribute_map(edg_source2ver).capacity = 0.;
856 edge_attribute_map(edg_sink2ver).capacity = 0.;
boost::vec_adj_list_vertex_property_map< Graph< T >, Graph< T > *, VertexAttribute< T >, VertexAttribute< T > &, boost::vertex_bundle_t > VertexAttributeMap
typename boost::graph_traits< Graph< T > >::edge_iterator EdgeIterator
typename boost::graph_traits< Graph< T > >::vertex_iterator VertexIterator
boost::graph_traits< boost::adjacency_list< boost::vecS, boost::vecS, boost::directedS > >::edge_descriptor EdgeDescriptor
typename boost::property_map< Graph< T >, uint32_t EdgeAttribute< T >::* >::type EdgeIndexMap
typename boost::graph_traits< CP::Graph< T > >::vertex_descriptor VertexDescriptor
typename boost::adjacency_list< boost::vecS, boost::vecS, boost::directedS, VertexAttribute< T >, EdgeAttribute< T > > Graph
typename boost::property_map< Graph< T >, boost::vertex_index_t >::type VertexIndexMap
boost::adj_list_edge_property_map< boost::directed_tag, EdgeAttribute< T >, EdgeAttribute< T > &, uint64_t, CP::EdgeAttribute< T >, boost::edge_bundle_t > EdgeAttributeMap
QTextStream & endl(QTextStream &stream)
uint32_t kmeans_resampling
void compute_connected_components()
CPparameter< T > parameter
std::vector< VertexDescriptor< T > > connected_comp_from_root(const VertexDescriptor< T > &root, const size_t &size_comp, std::vector< bool > &vertices_seen, std::vector< bool > &edges_seen)
CutPursuit(uint32_t nbVertex=1)
CP::VertexIterator< T > lastIterator
std::vector< std::vector< VertexDescriptor< T > > > components
VertexDescriptor< T > sink
VertexDescriptor< T > source
size_t activate_edges(bool allows_saturation=true)
std::vector< std::vector< EdgeDescriptor > > borders
void compute_reduced_graph()
virtual std::pair< std::vector< T >, T > compute_value(const uint32_t &ind_com)
virtual std::pair< std::vector< T >, T > compute_merge_gain(const VertexDescriptor< T > &comp1, const VertexDescriptor< T > &comp2)
std::vector< bool > saturated_components
void compute_reduced_value()
std::pair< std::vector< T >, std::vector< T > > run()
std::vector< VertexDescriptor< T > > root_vertex
void saturateComponent(const uint32_t &ind_com)
uint32_t merge(bool is_cutoff)
virtual std::pair< T, T > compute_energy()
std::vector< T > merged_value