40 #include <vq3Topology.hpp>
41 #include <vq3Utils.hpp>
50 template<
typename SAMPLE_TYPE,
typename VERTEX_VALUE_TYPE,
typename PROTOTYPE_TYPE>
53 using sample_type = SAMPLE_TYPE;
54 using vertex_value_type = VERTEX_VALUE_TYPE;
55 using prototype_type = PROTOTYPE_TYPE;
65 void notify_closest(
const prototype_type& prototype,
const sample_type& sample,
double closest_distance);
104 template<
typename EPOCH_DATA_ITER>
105 auto distortion(
const EPOCH_DATA_ITER& begin,
const EPOCH_DATA_ITER& end) {
107 throw std::runtime_error(
"vq3::epoch::distortion : empty collection");
109 auto res = it->vq3_bmu_accum;
110 for(++it; it != end; ++it)
111 res += it->vq3_bmu_accum;
120 template<
typename SAMPLE_TYPE,
typename VERTEX_VALUE_TYPE,
typename PROTOTYPE_TYPE>
122 using sample_type = SAMPLE_TYPE;
123 using vertex_value_type = VERTEX_VALUE_TYPE;
124 using prototype_type = PROTOTYPE_TYPE;
128 void notify_closest (
const prototype_type&,
const sample_type&,
double) {}
131 void notify_wtm_update (
const sample_type&,
double) {}
134 void notify_wta_update (
const sample_type&) {}
137 void set_prototype(prototype_type& prototype) {}
140 void set_content(vertex_value_type& vertex_value) {}
143 none& operator+=(
const none& other) {
return *
this;}
150 template<
typename MOTHER>
152 using sample_type =
typename MOTHER::sample_type;
153 using vertex_value_type =
typename MOTHER::vertex_value_type;
154 using prototype_type =
typename MOTHER::prototype_type;
160 void notify_closest(
const prototype_type& prototype,
const sample_type& sample,
double dist) {
161 this->MOTHER::notify_closest(prototype, sample, dist);
165 void notify_wtm_update(
const sample_type& sample,
double coef) {
166 this->MOTHER::notify_wtm_update(sample, coef);
170 void notify_wta_update(
const sample_type& sample) {
171 this->MOTHER::notify_wta_update(sample);
176 void set_prototype(prototype_type& prototype) {
177 this->MOTHER::set_prototype(prototype);
178 if(this->vq3_wta_accum.nb != 0)
179 prototype = this->vq3_wta_accum.template average<double>();
183 void set_content(vertex_value_type& vertex_value) {
184 this->MOTHER::set_content(vertex_value);
188 wta<MOTHER>& operator+=(
const wta<MOTHER>& arg) {
189 this->MOTHER::operator+=(arg);
199 template<
typename MOTHER>
201 using sample_type =
typename MOTHER::sample_type;
202 using vertex_value_type =
typename MOTHER::vertex_value_type;
203 using prototype_type =
typename MOTHER::prototype_type;
210 void notify_closest(
const prototype_type& prototype,
const sample_type& sample,
double dist) {
211 this->MOTHER::notify_closest(prototype, sample, dist);
216 void notify_wtm_update(
const sample_type& sample,
double coef) {
217 this->MOTHER::notify_wtm_update(sample, coef);
223 void notify_wta_update(
const sample_type& sample) {
224 this->MOTHER::notify_wta_update(sample);
228 void set_prototype(prototype_type& prototype) {
229 this->MOTHER::set_prototype(prototype);
235 void set_content(vertex_value_type& vertex_value) {
236 this->MOTHER::set_content(vertex_value);
240 wtm<MOTHER>& operator+=(
const wtm<MOTHER>& arg) {
241 this->MOTHER::operator+=(arg);
250 template<
typename prototype_type,
typename sample_type>
252 double operator()(
const prototype_type&,
const sample_type&,
double d) {
return d;}
258 template<
typename prototype_type,
typename sample_type>
260 double operator()(
const prototype_type&,
const sample_type&,
double d) {
return std::sqrt(d);}
266 template<
typename prototype_type,
typename sample_type>
268 double operator()(
const prototype_type&,
const sample_type&,
double d) {
return 1.0;}
276 template<
typename MOTHER,
typename FCT_ACCUM>
278 using sample_type =
typename MOTHER::sample_type;
279 using vertex_value_type =
typename MOTHER::vertex_value_type;
280 using prototype_type =
typename MOTHER::prototype_type;
286 void notify_closest(
const prototype_type& prototype,
const sample_type& sample,
double dist) {
287 this->MOTHER::notify_closest(prototype, sample, dist);
292 void notify_wtm_update(
const sample_type& sample,
double coef) {
293 this->MOTHER::notify_wtm_update(sample, coef);
297 void notify_wta_update(
const sample_type& sample) {
298 this->MOTHER::notify_wta_update(sample);
302 void set_prototype(prototype_type& prototype) {
303 this->MOTHER::set_prototype(prototype);
307 void set_content(vertex_value_type& vertex_value) {
308 this->MOTHER::set_content(vertex_value);
312 bmu<MOTHER, FCT_ACCUM>& operator+=(
const bmu<MOTHER, FCT_ACCUM>& arg) {
313 this->MOTHER::operator+=(arg);
324 template<
typename MOTHER>
327 using sample_type =
typename MOTHER::sample_type;
328 using vertex_value_type =
typename MOTHER::vertex_value_type;
329 using prototype_type =
typename MOTHER::prototype_type;
336 void notify_closest(
const prototype_type& prototype,
const sample_type& sample,
double dist) {
337 this->MOTHER::notify_closest(prototype, sample, dist);
341 void notify_wtm_update(
const sample_type& sample,
double coef) {
342 this->MOTHER::notify_wtm_update(sample, coef);
346 void notify_wta_update(
const sample_type& sample) {
347 this->MOTHER::notify_wta_update(sample);
351 void set_prototype(prototype_type& prototype) {
353 this->MOTHER::set_prototype(prototype);
358 void set_content(vertex_value_type& vertex_value) {
359 this->MOTHER::set_content(vertex_value);
363 delta<MOTHER>& operator+=(
const delta<MOTHER>& arg) {
364 this->MOTHER::operator+=(arg);
378 template<
typename MOTHER>
380 using sample_type =
typename MOTHER::sample_type;
381 using vertex_value_type =
typename MOTHER::vertex_value_type;
382 using prototype_type =
typename MOTHER::prototype_type;
388 void notify_closest(
const prototype_type& prototype,
const sample_type& sample,
double dist) {
389 this->MOTHER::notify_closest(prototype, sample, dist);
394 void notify_wtm_update(
const sample_type& sample,
double coef) {
395 this->MOTHER::notify_wtm_update(sample, coef);
399 void notify_wta_update(
const sample_type& sample) {
400 this->MOTHER::notify_wta_update(sample);
404 void set_prototype(prototype_type& prototype) {
405 this->MOTHER::set_prototype(prototype);
409 void set_content(vertex_value_type& vertex_value) {
410 this->MOTHER::set_content(vertex_value);
415 bmu_mean_std<MOTHER>& operator+=(
const bmu_mean_std<MOTHER>& arg) {
416 this->MOTHER::operator+=(arg);
425 template<
typename GRAPH,
bool WITH_COUNTS>
429 using graph_type = GRAPH;
430 using ref_vertex =
typename graph_type::ref_vertex;
431 using ref_edge =
typename graph_type::ref_edge;
432 using edge =
typename graph_type::edge_value_type;
437 ref_vertex first, second;
438 mutable std::size_t chl_count = 0;
441 refpair(
const refpair&) =
default;
442 refpair& operator=(
const refpair&) =
default;
443 refpair(refpair&&) =
default;
444 refpair& operator=(refpair&&) =
default;
446 refpair(
const std::pair<ref_vertex, ref_vertex>& p)
447 : first(p.first), second(p.second) {
449 std::swap(first, second);
452 bool operator<(
const refpair& other)
const {
453 return (first < other.first) || ((first == other.first) && (second < other.second));
458 std::set<ref_edge> survivors;
459 std::set<refpair> newedges;
461 data(
const data&) =
default;
462 data& operator=(
const data&) =
default;
463 data(data&&) =
default;
464 data& operator=(data&&) =
default;
467 static auto std_set_union(
typename std::vector<refpair>::iterator first1,
typename std::vector<refpair>::iterator last1,
468 typename std::set<refpair>::iterator first2,
typename std::set<refpair>::iterator last2,
469 std::back_insert_iterator<std::vector<refpair>> d_first,
470 std::vector<refpair>& dest_container) {
471 if constexpr (WITH_COUNTS) {
473 for (; first1 != last1; ++d_first) {
475 return std::copy(first1, last1, d_first);
476 if (*first2 < *first1) {
477 *d_first = *first2++;
481 if (!(*first1 < *first2)) {
483 dest_container.rbegin()->chl_count += first2->chl_count;
489 return std::copy(first2, last2, d_first);
510 template<
typename ITERATOR,
typename SAMPLE_OF,
typename DISTANCE>
512 const ITERATOR& samples_begin,
const ITERATOR& samples_end,
const SAMPLE_OF& sample_of,
513 const DISTANCE& distance,
514 const edge& value_for_new_edges) {
515 if constexpr (WITH_COUNTS) g.foreach_edge([](
auto ref_e) {(*ref_e)().vq3_counter = 0;});
517 auto nb_vertices = g.nb_vertices();
520 if(nb_vertices == 2) {
521 std::array<ref_vertex, 2> vertices;
522 vq3::utils::collect_vertices(g,vertices.begin());
523 auto ref_e = g.get_edge(vertices[0], vertices[1]);
524 if(ref_e ==
nullptr) {
525 ref_e = g.connect(vertices[0], vertices[1], value_for_new_edges);
526 if constexpr (WITH_COUNTS) ++((*ref_e)().vq3_counter);
532 auto iters = utils::split(samples_begin, samples_end, nb_threads);
533 std::vector<std::future<data> > futures;
534 auto out = std::back_inserter(futures);
539 for(
auto& begin_end : iters)
540 *(out++) = std::async(std::launch::async,
541 [begin_end,
this, &sample_of, &distance]() {
543 for(
auto it = begin_end.first; it != begin_end.second; ++it) {
544 auto two = utils::two_closest(g, sample_of(*it), distance);
545 if(two.first && two.second) {
546 auto ref_e = g.get_edge(two.first, two.second);
547 if(ref_e ==
nullptr) {
548 auto [it, inserted ] = res.newedges.emplace(two);
549 if constexpr (WITH_COUNTS) ++(it->chl_count);
552 if constexpr (WITH_COUNTS) ++((*ref_e)().vq3_counter);
553 res.survivors.emplace(ref_e);
560 std::vector<ref_edge> survivors;
561 std::vector<refpair> newedges;
563 std::vector<ref_edge> s;
564 std::vector<refpair> n;
565 for(
auto& f : futures) {
569 auto outs = std::back_inserter(s);
570 std::set_union(survivors.begin(), survivors.end(),
571 d.survivors.begin(), d.survivors.end(),
575 auto outn = std::back_inserter(n);
576 if constexpr (WITH_COUNTS)
577 std_set_union(newedges.begin(), newedges.end(),
578 d.newedges.begin(), d.newedges.end(),
581 std::set_union(newedges.begin(), newedges.end(),
582 d.newedges.begin(), d.newedges.end(),
586 std::swap(s, survivors);
587 std::swap(n, newedges);
591 g.garbaging_unlock();
593 bool one_kill =
false;
596 utils::clear_edge_tags(g,
true);
597 for(
auto& ref_e : survivors) (*ref_e)().vq3_tag =
false;
598 g.foreach_edge([&one_kill](
const ref_edge& ref_e) {
599 if((*ref_e)().vq3_tag) {
606 for(
auto& p : newedges) {
607 auto ref_e = g.connect(p.first, p.second, value_for_new_edges);
608 if constexpr (WITH_COUNTS) (*ref_e)().vq3_counter = p.chl_count;
611 return newedges.size() != 0 || one_kill;
615 template<
typename GRAPH>
616 auto processor(GRAPH& g) {
return Processor<GRAPH, false>(g);}
618 template<
typename GRAPH>
619 auto processor_with_counts(GRAPH& g) {
return Processor<GRAPH, true>(g);}
625 template<
typename GRAPH>
629 using graph_type = GRAPH;
630 using ref_vertex =
typename graph_type::ref_vertex;
647 template<
typename ITERATOR,
typename SAMPLE_OF,
typename MATTERS>
649 const ITERATOR& samples_begin,
const ITERATOR& samples_end,
const SAMPLE_OF& sample_of,
650 const MATTERS& matters) {
652 auto iters = utils::split(samples_begin, samples_end, nb_threads);
653 std::vector<std::thread> threads;
658 for(
auto& [begin, end] : iters)
659 threads.emplace_back([begin, end,
this, &sample_of, &matters](){
660 for(
auto it = begin; it != end; ++it)
661 g.foreach_vertex([&sample_of, &matters, it](
auto ref_v) {
662 if(matters(ref_v, sample_of(*it))) (*ref_v)().vq3_counter++;
666 for(
auto& t : threads) t.join();
669 g.garbaging_unlock();
673 template<
typename GRAPH>
674 auto processor(GRAPH& g) {
return Processor<GRAPH>(g);}
680 template<
typename GRAPH>
684 using graph_type = GRAPH;
685 using ref_edge =
typename graph_type::ref_edge;
702 template<
typename ITERATOR,
typename SAMPLE_OF,
typename MATTERS>
704 const ITERATOR& samples_begin,
const ITERATOR& samples_end,
const SAMPLE_OF& sample_of,
705 const MATTERS& matters) {
707 auto iters = utils::split(samples_begin, samples_end, nb_threads);
708 std::vector<std::thread> threads;
713 for(
auto& [begin, end] : iters)
714 threads.emplace_back([begin, end,
this, &sample_of, &matters](){
715 for(
auto it = begin; it != end; ++it)
716 g.foreach_edge([&sample_of, &matters, it](
auto ref_e) {
717 auto extr_pair = ref_e->extremities();
718 if(vq3::invalid_extremities(extr_pair)) {
722 if(matters(ref_e, sample_of(*it))) (*ref_e)().vq3_counter++;
726 for(
auto& t : threads) t.join();
729 g.garbaging_unlock();
733 template<
typename GRAPH>
734 auto processor(GRAPH& g) {
return Processor<GRAPH>(g);}
745 template<
typename TABLE>
749 using topology_table_type = TABLE;
753 topology_table_type& table;
757 Processor(topology_table_type& table) : table(table) {}
768 template<
typename EPOCH_DATA,
typename ITERATOR,
typename SAMPLE_OF,
typename PROTOTYPE_OF_VERTEX_VALUE,
typename DISTANCE>
769 auto process(
unsigned int nb_threads,
const ITERATOR& samples_begin,
const ITERATOR& samples_end,
const SAMPLE_OF& sample_of,
const PROTOTYPE_OF_VERTEX_VALUE& prototype_of,
const DISTANCE& distance) {
770 auto iters = utils::split(samples_begin, samples_end, nb_threads);
771 std::vector<std::future<std::vector<EPOCH_DATA> > > futures;
772 auto out = std::back_inserter(futures);
775 table.g.garbaging_lock();
777 for(
auto& begin_end : iters)
778 *(out++) = std::async(std::launch::async,
779 [begin_end,
this, &sample_of, &distance, &prototype_of]() {
780 std::vector<EPOCH_DATA> data(table.size());
781 for(
auto it = begin_end.first; it != begin_end.second; ++it) {
783 const auto& sample = sample_of(*it);
784 auto closest = utils::closest(table.g, sample, distance, min_dist);
786 auto& d = data[table(closest)];
787 d.notify_closest(prototype_of((*closest)()), sample, min_dist);
788 d.notify_wta_update(sample);
794 auto fit = futures.begin();
795 if(futures.end() != fit) {
796 auto data0 = (fit++)->get();
797 auto b0 = data0.begin();
798 auto e0 = data0.end();
799 for(
unsigned int thread_id = 1; thread_id < nb_threads; ++thread_id) {
800 auto datai = (fit++)->get();
801 auto bi = datai.begin();
802 for(
auto b = b0; b != e0; ++b, ++bi)
807 table.g.garbaging_unlock();
809 unsigned int idx = 0;
810 for(
auto& d : data0) {
811 auto& value = (*(table(idx++)))();
812 d.set_prototype(prototype_of(value));
813 d.set_content(value);
820 table.g.garbaging_unlock();
821 return std::vector<EPOCH_DATA>();
826 template<
typename TABLE>
827 auto processor(TABLE& table) {
return Processor<TABLE>(table);}
832 template<
typename TABLE>
836 using topology_table_type = TABLE;
840 topology_table_type& table;
845 Processor(topology_table_type& table) : table(table) {}
856 template<
typename EPOCH_DATA,
typename ITERATOR,
typename SAMPLE_OF,
typename PROTOTYPE_OF_VERTEX_VALUE,
typename DISTANCE>
858 const typename topology_table_type::neighborhood_key_type& neighborhood_key,
859 const ITERATOR& samples_begin,
const ITERATOR& samples_end,
const SAMPLE_OF& sample_of,
const PROTOTYPE_OF_VERTEX_VALUE& prototype_of,
const DISTANCE& distance) {
860 auto iters = utils::split(samples_begin, samples_end, nb_threads);
861 std::vector<std::future<std::vector<EPOCH_DATA> > > futures;
862 auto out = std::back_inserter(futures);
865 table.g.garbaging_lock();
867 for(
auto& begin_end : iters)
868 *(out++) = std::async(std::launch::async,
869 [begin_end,
this, &sample_of, &distance, size = table.size(), &neighborhood_key, &prototype_of]() {
870 std::vector<EPOCH_DATA> data(size);
871 for(
auto it = begin_end.first; it != begin_end.second; ++it) {
873 const auto& sample = sample_of(*it);
874 auto closest = utils::closest(table.g, sample, distance, min_dist);
876 auto& neighborhood = table.neighborhood(closest, neighborhood_key);
877 data[neighborhood.begin()->index].notify_closest(prototype_of((*closest)()), sample, min_dist);
878 for(
auto& info : neighborhood) data[info.index].notify_wtm_update(sample, info.value);
884 auto fit = futures.begin();
885 if(fit != futures.end()) {
886 auto data0 = (fit++)->get();
887 auto b0 = data0.begin();
888 auto e0 = data0.end();
889 for(
unsigned int thread_id = 1; thread_id < nb_threads; ++thread_id) {
890 auto datai = (fit++)->get();
891 auto bi = datai.begin();
892 for(
auto b = b0; b != e0; ++b, ++bi)
897 table.g.garbaging_unlock();
899 unsigned int idx = 0;
900 for(
auto& d : data0) {
901 auto& value = (*(table(idx++)))();
902 d.set_prototype(prototype_of(value));
903 d.set_content(value);
909 table.g.garbaging_unlock();
910 return std::vector<EPOCH_DATA>();
915 template<
typename TABLE>
916 auto processor(TABLE& table) {
return Processor<TABLE>(table);}