36 #include <type_traits>
44 #include <vq3Graph.hpp>
50 using std::runtime_error::runtime_error;
56 template<
typename INCREMENTABLE,
typename NB_TYPE>
66 accum() : nb(0), value() {}
72 template<
typename NB_AVG_TYPE = NB_TYPE>
73 auto average()
const {
return value/
static_cast<NB_AVG_TYPE
>(nb);}
77 value = INCREMENTABLE();
116 template<
typename GRAPH,
typename VALUE_OF_REF_VERTEX>
117 auto make_vertex_table(GRAPH& g,
const VALUE_OF_REF_VERTEX& value_of) {
118 std::map<
typename GRAPH::ref_vertex,
typename std::result_of<VALUE_OF_REF_VERTEX (
typename GRAPH::ref_vertex)>::type> res;
119 g.foreach_vertex([&res, &value_of](
const typename GRAPH::ref_vertex& ref_v) {res[ref_v] = value_of(ref_v);});
128 template<
typename GRAPH,
typename OUTPUT_IT>
129 void collect_vertices(GRAPH& g,
const OUTPUT_IT& outit) {
131 g.foreach_vertex([&out](
const typename GRAPH::ref_vertex& ref_v) {*(out++) = ref_v;});
139 template<
typename GRAPH,
typename OUTPUT_IT>
140 void collect_edges(GRAPH& g,
const OUTPUT_IT& outit) {
142 g.foreach_edge([&out](
const typename GRAPH::ref_edge& ref_e) {
143 auto extr = ref_e->extremities();
144 if(invalid_extremities(extr))
153 template<
typename PROCESS,
typename =
void>
155 void operator()(
const PROCESS& d)
const {}
161 template<
typename PROCESS>
163 void operator()(
const PROCESS& d)
const {d.vq3_closest_init();}
174 template<
typename GRAPH,
typename SAMPLE,
typename DISTANCE>
175 typename GRAPH::ref_vertex closest(GRAPH& g,
const SAMPLE& sample,
const DISTANCE& distance,
double& closest_distance_value) {
176 typename GRAPH::ref_vertex res =
nullptr;
177 double dist = std::numeric_limits<double>::max();
179 g.foreach_vertex([&dist, &res, &sample, &distance](
const typename GRAPH::ref_vertex& ref_v) {
180 if(
double d = distance((*ref_v)(), sample); d < dist) {
186 closest_distance_value = dist;
197 template<
typename GRAPH,
typename SAMPLE,
typename DISTANCE>
198 typename GRAPH::ref_vertex closest(GRAPH& g,
const SAMPLE& sample,
const DISTANCE& distance) {
200 return closest(g, sample, distance, d);
211 template<
typename GRAPH,
typename SAMPLE,
typename DISTANCE>
212 typename std::pair<typename GRAPH::ref_vertex, typename GRAPH::ref_vertex> two_closest(GRAPH& g,
const SAMPLE& sample,
const DISTANCE& distance, std::pair<double, double>& closest_distance_values) {
213 std::pair<typename GRAPH::ref_vertex, typename GRAPH::ref_vertex> res = {
nullptr,
nullptr};
214 double dist1 = std::numeric_limits<double>::max();
215 double dist2 = std::numeric_limits<double>::max();
216 execute_vq3_closest_init_if_available<DISTANCE>()(distance);
217 g.foreach_vertex([&dist1, &dist2, &res, &sample, &distance](
const typename GRAPH::ref_vertex& ref_v) {
218 double d = distance((*ref_v)(), sample);
221 res.second = res.first;
230 closest_distance_values = {dist1, dist2};
242 template<
typename GRAPH,
typename SAMPLE,
typename DISTANCE>
243 typename std::pair<typename GRAPH::ref_vertex, typename GRAPH::ref_vertex> two_closest(GRAPH& g,
const SAMPLE& sample,
const DISTANCE& distance) {
244 std::pair<double, double> dists;
245 return two_closest(g, sample, distance, dists);
256 template<
typename GRAPH,
typename SAMPLE,
typename DISTANCE>
257 typename GRAPH::ref_edge closest_edge(GRAPH& g,
const SAMPLE& sample,
const DISTANCE& distance,
double& closest_distance_value) {
258 typename GRAPH::ref_edge res =
nullptr;
259 double dist = std::numeric_limits<double>::max();
260 execute_vq3_closest_init_if_available<DISTANCE>()(distance);
261 g.foreach_edge([&dist, &res, &sample, &distance](
const typename GRAPH::ref_edge& ref_e) {
262 auto extr = ref_e->extremities();
263 if(invalid_extremities(extr))
265 else if(
double d = distance((*(extr.first))(), (*(extr.second))(), sample); d < dist) {
270 closest_distance_value = dist;
281 template<
typename GRAPH,
typename SAMPLE,
typename DISTANCE>
282 typename GRAPH::ref_edge closest_edge(GRAPH& g,
const SAMPLE& sample,
const DISTANCE& distance) {
284 return closest_edge(g, sample, distance, dist);
297 template<
typename GRAPH,
typename VERTEX_VALUE_OF,
typename EDGE_VALUE_OF>
298 auto make_grid(GRAPH& g,
unsigned int width,
unsigned int height,
299 const VERTEX_VALUE_OF& v_of,
const EDGE_VALUE_OF& e_of,
300 bool loop_w =
false,
bool loop_h =
false) {
301 std::vector<std::vector<typename GRAPH::ref_vertex>> lines;
302 std::vector<typename GRAPH::ref_vertex> line(width);
303 auto lout = std::back_inserter(lines);
306 unsigned int width_ = width - 1;
307 unsigned int height_ = height - 1;
309 for(h = 0; h < height; ++h) {
310 for(w = 0; w < width; ++w)
311 line[w] = (g += v_of(w, h));
315 for(h = 0; h < height_; ++h) {
316 for(w = 0; w < width_; ++w) {
317 g.connect(lines[h][w], lines[h][w + 1], e_of(w, h, w + 1, h));
318 g.connect(lines[h][w], lines[h + 1][w], e_of(w, h, w, h + 1));
320 g.connect(lines[h][w], lines[h + 1][w], e_of(w, h, w, h + 1));
322 for(w = 0; w < width_; ++w)
323 g.connect(lines[h][w], lines[h][w + 1], e_of(w, h, w + 1, h));
325 if(loop_w && width > 1)
326 for(h = 0; h < height; ++h)
327 g.connect(lines[h][0], lines[h][width_], e_of(0, h, width_, h));
329 if(loop_h && height > 1)
330 for(w = 0; w < width; ++w)
331 g.connect(lines[0][w], lines[height_][w], e_of(w, 0, w, height_));
347 template<
typename GRAPH,
typename VERTEX_VALUE_OF>
348 auto make_grid(GRAPH& g,
unsigned int width,
unsigned int height,
349 const VERTEX_VALUE_OF& v_of,
350 bool loop_w =
false,
bool loop_h =
false) {
351 std::vector<std::vector<typename GRAPH::ref_vertex>> lines;
352 std::vector<typename GRAPH::ref_vertex> line(width);
353 auto lout = std::back_inserter(lines);
356 unsigned int width_ = width - 1;
357 unsigned int height_ = height - 1;
359 for(h = 0; h < height; ++h) {
360 for(w = 0; w < width; ++w)
361 line[w] = (g += v_of(w, h));
365 for(h = 0; h < height_; ++h) {
366 for(w = 0; w < width_; ++w) {
367 g.connect(lines[h][w], lines[h][w + 1]);
368 g.connect(lines[h][w], lines[h + 1][w]);
370 g.connect(lines[h][w], lines[h + 1][w]);
372 for(w = 0; w < width_; ++w)
373 g.connect(lines[h][w], lines[h][w + 1]);
375 if(loop_w && width > 1)
376 for(h = 0; h < height; ++h)
377 g.connect(lines[h][0], lines[h][width_]);
379 if(loop_h && height > 1)
380 for(w = 0; w < width; ++w)
381 g.connect(lines[0][w], lines[height_][w]);
389 template<
typename GRAPH>
390 void clear_vertex_tags(GRAPH& g,
bool value) {
391 g.foreach_vertex([value](
const typename GRAPH::ref_vertex& ref_v) {(*ref_v)().vq3_tag = value;});
397 template<
typename GRAPH>
398 void clear_edge_tags(GRAPH& g,
bool value) {
399 g.foreach_edge([value](
const typename GRAPH::ref_edge& ref_e) {
400 auto extr = ref_e->extremities();
401 if(invalid_extremities(extr))
404 (*ref_e)().vq3_tag = value;
411 template<
typename GRAPH>
412 void clear_all_tags(GRAPH& g,
bool value) {
413 clear_vertex_tags(g, value);
414 clear_edge_tags(g, value);
420 template<
typename GRAPH>
421 void clear_vertex_counters(GRAPH& g, std::size_t value) {
422 g.foreach_vertex([value](
const typename GRAPH::ref_vertex& ref_v) {(*ref_v)().vq3_counter = value;});
428 template<
typename GRAPH>
429 void clear_edge_counters(GRAPH& g, std::size_t value) {
430 g.foreach_edge([value](
const typename GRAPH::ref_edge& ref_e) {
431 auto extr = ref_e->extremities();
432 if(invalid_extremities(extr))
435 (*ref_e)().vq3_counter = value;
442 template<
typename GRAPH>
443 void clear_all_counters(GRAPH& g, std::size_t value) {
444 clear_vertex_counters(g, value);
445 clear_edge_counters(g, value);
452 template<
typename GRAPH>
453 void clear_vertex_labels(GRAPH& g,
unsigned int value) {
454 g.foreach_vertex([value](
const typename GRAPH::ref_vertex& ref_v) {(*ref_v)().vq3_label = value;});
460 template<
typename GRAPH>
461 void clear_edge_labels(GRAPH& g,
unsigned int value) {
462 g.foreach_edge([value](
const typename GRAPH::ref_edge& ref_e) {
463 auto extr = ref_e->extremities();
464 if(invalid_extremities(extr))
467 (*ref_e)().vq3_label = value;
474 template<
typename GRAPH>
475 void clear_all_labels(GRAPH& g,
unsigned int value) {
476 clear_vertex_labels(g, value);
477 clear_edge_labels(g, value);
483 template<
typename GRAPH>
484 void clear_vertex_efficiencies(GRAPH& g,
bool value) {
485 g.foreach_vertex([value](
const typename GRAPH::ref_vertex& ref_v) {(*ref_v)().vq3_efficient = value;});
491 template<
typename GRAPH>
492 void clear_edge_efficiencies(GRAPH& g,
bool value) {
493 g.foreach_edge([value](
const typename GRAPH::ref_edge& ref_e) {
494 auto extr = ref_e->extremities();
495 if(invalid_extremities(extr))
498 (*ref_e)().vq3_efficient = value;
505 template<
typename GRAPH>
506 void clear_all_efficiencies(GRAPH& g,
bool value) {
507 clear_vertex_efficiencies(g, value);
508 clear_edge_efficiencies(g, value);
515 template<
typename IT>
516 auto split(
const IT& begin,
const IT& end,
unsigned int nb) {
517 std::vector< std::pair<IT, IT> > pairs;
519 auto out = std::back_inserter(pairs);
520 auto coef = std::distance(begin, end)/double(nb);
524 for(
unsigned int i = 1; i <= nb; ++i) {
527 q = (
unsigned int)(i*coef+.5);
528 std::advance(it, q-p);
530 *(out++) = {first, last};
539 template<
typename REF_VERTEX,
typename EDGE_FUN>
540 void foreach_efficient_edge(
const REF_VERTEX& ref_v,
const EDGE_FUN& fun) {
541 ref_v->foreach_edge([fun](
const typename REF_VERTEX::element_type::ref_edge_type& ref_e) {
542 if((*ref_e)().vq3_efficient)
548 namespace savitzky_golay {
553 template<
typename VALUE,
unsigned int ORDER,
unsigned int WINDOW_SIZE>
557 std::deque<VALUE> window;
558 mutable std::array<std::optional<VALUE>, ORDER+1> value;
572 window.emplace_back(v);
573 if(window.size() > WINDOW_SIZE)
575 for(
auto& v : value) v.reset();
581 template<
unsigned int O>
582 const std::optional<VALUE>&
get()
const {
583 static_assert(O <= ORDER,
"vq3::utils::savitzky_golay::get<O> : O is too high.");
588 namespace constant_timestep {
590 template<
unsigned int ORDER,
unsigned int WINDOW_SIZE,
unsigned int DEGREE>
595 static_assert(ORDER < 0,
"The parameters passed to vq3::utils::savitzky_golay::constant_timestep::estimator<...> leads to an unimplemented case (sg_norm fails).");
598 template<
typename VALUE,
unsigned int ORDER,
unsigned int WINDOW_SIZE,
unsigned int DEGREE>
603 static_assert(ORDER < 0,
"The parameters passed to vq3::utils::savitzky_golay::constant_timestep::estimator<...> leads to an unimplemented case (sg_compute fails).");
613 template<>
struct sg_norm<0, 9, 2> {
double value;
sg_norm(
double) {value = 1/231.0;}};
616 template<
typename ITER>
618 value = (*(iter++)) * -21;
619 value += (*(iter++)) * 14;
620 value += (*(iter++)) * 39;
621 value += (*(iter++)) * 54;
622 value += (*(iter++)) * 59;
623 value += (*(iter++)) * 54;
624 value += (*(iter++)) * 39;
625 value += (*(iter++)) * 14;
626 value += (*(iter++)) * -21;
630 template<>
struct sg_norm<1, 9, 2> {
double value;
sg_norm(
double step) {value = 1/(60*step);}};
633 template<
typename ITER>
635 value = (*(iter++)) * -4;
636 value += (*(iter++)) * -3;
637 value += (*(iter++)) * -2;
638 value += (*(iter++)) * -1;
640 value += (*(iter++)) * 1;
641 value += (*(iter++)) * 2;
642 value += (*(iter++)) * 3;
643 value += (*(iter++)) * 4;
647 template<>
struct sg_norm<2, 9, 2> {
double value;
sg_norm(
double step) {value = 1/(462*step*step);}};
650 template<
typename ITER>
652 value = (*(iter++)) * 28;
653 value += (*(iter++)) * 7;
654 value += (*(iter++)) * -8;
655 value += (*(iter++)) * -17;
656 value += (*(iter++)) * -20;
657 value += (*(iter++)) * -17;
658 value += (*(iter++)) * -8;
659 value += (*(iter++)) * 7;
660 value += (*(iter++)) * 28;
669 template<>
struct sg_norm<0, 15, 2> {
double value;
sg_norm(
double) {value = 1/1105.0;}};
670 template<
typename VALUE>
struct sg_compute<VALUE, 0, 15, 2> {
672 template<
typename ITER>
674 value = (*(iter++)) * -78;
675 value += (*(iter++)) * -13;
676 value += (*(iter++)) * 42;
677 value += (*(iter++)) * 87;
678 value += (*(iter++)) * 122;
679 value += (*(iter++)) * 147;
680 value += (*(iter++)) * 162;
681 value += (*(iter++)) * 167;
682 value += (*(iter++)) * 162;
683 value += (*(iter++)) * 147;
684 value += (*(iter++)) * 122;
685 value += (*(iter++)) * 87;
686 value += (*(iter++)) * 42;
687 value += (*(iter++)) * -13;
688 value += (*(iter++)) * -78;
692 template<>
struct sg_norm<1, 15, 2> {
double value;
sg_norm(
double step) {value = 1/(280*step);}};
693 template<
typename VALUE>
struct sg_compute<VALUE, 1, 15, 2> {
695 template<
typename ITER>
697 value = (*(iter++)) * -7;
698 value += (*(iter++)) * -6;
699 value += (*(iter++)) * -5;
700 value += (*(iter++)) * -4;
701 value += (*(iter++)) * -3;
702 value += (*(iter++)) * -2;
703 value += (*(iter++)) * -1;
705 value += (*(iter++)) * 1;
706 value += (*(iter++)) * 2;
707 value += (*(iter++)) * 3;
708 value += (*(iter++)) * 4;
709 value += (*(iter++)) * 5;
710 value += (*(iter++)) * 6;
711 value += (*(iter++)) * 7;
715 template<>
struct sg_norm<2, 15, 2> {
double value;
sg_norm(
double step) {value = 1/(6188*step*step);}};
716 template<
typename VALUE>
struct sg_compute<VALUE, 2, 15, 2> {
718 template<
typename ITER>
720 value = (*(iter++)) * 91;
721 value += (*(iter++)) * 52;
722 value += (*(iter++)) * 19;
723 value += (*(iter++)) * -8;
724 value += (*(iter++)) * -29;
725 value += (*(iter++)) * -44;
726 value += (*(iter++)) * -53;
727 value += (*(iter++)) * -56;
728 value += (*(iter++)) * -53;
729 value += (*(iter++)) * -44;
730 value += (*(iter++)) * -29;
731 value += (*(iter++)) * -8;
732 value += (*(iter++)) * 19;
733 value += (*(iter++)) * 52;
734 value += (*(iter++)) * 91;
742 template<>
struct sg_norm<0, 21, 2> {
double value;
sg_norm(
double) {value = 1/3059.0;}};
743 template<
typename VALUE>
struct sg_compute<VALUE, 0, 21, 2> {
745 template<
typename ITER>
747 value = (*(iter++)) * -171;
748 value += (*(iter++)) * -76;
749 value += (*(iter++)) * 9;
750 value += (*(iter++)) * 84;
751 value += (*(iter++)) * 149;
752 value += (*(iter++)) * 204;
753 value += (*(iter++)) * 249;
754 value += (*(iter++)) * 284;
755 value += (*(iter++)) * 309;
756 value += (*(iter++)) * 324;
757 value += (*(iter++)) * 329;
758 value += (*(iter++)) * 324;
759 value += (*(iter++)) * 309;
760 value += (*(iter++)) * 284;
761 value += (*(iter++)) * 249;
762 value += (*(iter++)) * 204;
763 value += (*(iter++)) * 149;
764 value += (*(iter++)) * 84;
765 value += (*(iter++)) * 9;
766 value += (*(iter++)) * -76;
767 value += (*(iter++)) * -171;
771 template<>
struct sg_norm<1, 21, 2> {
double value;
sg_norm(
double step) {value = 1/(770*step);}};
772 template<
typename VALUE>
struct sg_compute<VALUE, 1, 21, 2> {
774 template<
typename ITER>
776 value = (*(iter++)) * -11;
777 value += (*(iter++)) * -10;
778 value += (*(iter++)) * -9;
779 value += (*(iter++)) * -7;
780 value += (*(iter++)) * -6;
781 value += (*(iter++)) * -5;
782 value += (*(iter++)) * -4;
783 value += (*(iter++)) * -3;
784 value += (*(iter++)) * -2;
785 value += (*(iter++)) * -1;
787 value += (*(iter++)) * 1;
788 value += (*(iter++)) * 2;
789 value += (*(iter++)) * 3;
790 value += (*(iter++)) * 4;
791 value += (*(iter++)) * 5;
792 value += (*(iter++)) * 6;
793 value += (*(iter++)) * 7;
794 value += (*(iter++)) * 9;
795 value += (*(iter++)) * 10;
796 value += (*(iter++)) * 11;
801 template<>
struct sg_norm<2, 21, 2> {
double value;
sg_norm(
double step) {value = 1/(33649*step*step);}};
802 template<
typename VALUE>
struct sg_compute<VALUE, 2, 21, 2> {
804 template<
typename ITER>
806 value = (*(iter++)) * 190;
807 value += (*(iter++)) * 133;
808 value += (*(iter++)) * 82;
809 value += (*(iter++)) * 37;
810 value += (*(iter++)) * -2;
811 value += (*(iter++)) * -35;
812 value += (*(iter++)) * -62;
813 value += (*(iter++)) * -83;
814 value += (*(iter++)) * -98;
815 value += (*(iter++)) * -107;
816 value += (*(iter++)) * -110;
817 value += (*(iter++)) * -107;
818 value += (*(iter++)) * -98;
819 value += (*(iter++)) * -83;
820 value += (*(iter++)) * -62;
821 value += (*(iter++)) * -35;
822 value += (*(iter++)) * -2;
823 value += (*(iter++)) * 37;
824 value += (*(iter++)) * 82;
825 value += (*(iter++)) * 133;
826 value += (*(iter++)) * 190;
835 template<
typename VALUE>
struct sg_compute<VALUE, 0, 21, 3> {
837 template<
typename ITER>
843 template<>
struct sg_norm<1, 21, 3> {
double value;
sg_norm(
double step) {value = 1/(3634092*step);}};
844 template<
typename VALUE>
struct sg_compute<VALUE, 1, 21, 3> {
846 template<
typename ITER>
848 value = (*(iter++)) * 84075;
849 value += (*(iter++)) * 10032;
850 value += (*(iter++)) * -43284;
851 value += (*(iter++)) * -78176;
852 value += (*(iter++)) * -96947;
853 value += (*(iter++)) * -101900;
854 value += (*(iter++)) * -95338;
855 value += (*(iter++)) * -79654;
856 value += (*(iter++)) * -56881;
857 value += (*(iter++)) * -29592;
859 value += (*(iter++)) * 29592;
860 value += (*(iter++)) * 56881;
861 value += (*(iter++)) * 79654;
862 value += (*(iter++)) * 95338;
863 value += (*(iter++)) * 101900;
864 value += (*(iter++)) * 96947;
865 value += (*(iter++)) * 78176;
866 value += (*(iter++)) * 43284;
867 value += (*(iter++)) * -10032;
868 value += (*(iter++)) * -84075;
873 template<
typename VALUE>
struct sg_compute<VALUE, 2, 21, 3> {
875 template<
typename ITER>
887 template<
typename VALUE,
unsigned int ORDER,
unsigned int WINDOW_SIZE,
unsigned int DEGREE>
890 std::array<double, ORDER+1> hcoef;
892 template<
unsigned int O>
893 void __set_timestep(
double step) {
894 if constexpr (O == 0)
898 __set_timestep<O-1>(step);
910 __set_timestep<ORDER>(step);
916 template<
unsigned int O>
917 const std::optional<VALUE>&
get()
const {
918 static_assert(O <= ORDER,
"vq3::utils::savitzky_golay::get<O> : O is too high.");
919 auto& v = this->value[O];
920 if(!v && this->window.size() == WINDOW_SIZE)