26 #include <gudhi/Debug_utils.h> 27 #include <gudhi/graph_simplicial_complex.h> 29 #include <gudhi/Simplex_tree.h> 30 #include <gudhi/Rips_complex.h> 31 #include <gudhi/Points_off_io.h> 33 #include <gudhi/Persistent_cohomology.h> 34 #include <gudhi/Bottleneck.h> 36 #include <boost/config.hpp> 37 #include <boost/graph/graph_traits.hpp> 38 #include <boost/graph/adjacency_list.hpp> 39 #include <boost/graph/connected_components.hpp> 40 #include <boost/graph/dijkstra_shortest_paths.hpp> 41 #include <boost/graph/subgraph.hpp> 42 #include <boost/graph/graph_utility.hpp> 57 namespace cover_complex {
62 using Persistence_diagram = std::vector<std::pair<double, double> >;
63 using Graph = boost::subgraph<
64 boost::adjacency_list<boost::setS, boost::vecS, boost::undirectedS, boost::no_property,
65 boost::property<boost::edge_index_t, int, boost::property<boost::edge_weight_t, double> > > >;
66 using Vertex_t = boost::graph_traits<Graph>::vertex_descriptor;
67 using Index_map = boost::property_map<Graph, boost::vertex_index_t>::type;
68 using Weight_map = boost::property_map<Graph, boost::edge_weight_t>::type;
90 template <
typename Po
int>
96 std::vector<Point> point_cloud;
97 std::vector<std::vector<double> > distances;
102 std::map<int, double> func;
103 std::map<int, double>
105 bool functional_cover =
false;
107 Graph one_skeleton_OFF;
109 std::vector<Vertex_t> vertices;
111 std::vector<std::vector<int> > simplices;
112 std::vector<int> voronoi_subsamples;
114 Persistence_diagram PD;
115 std::vector<double> distribution;
117 std::map<int, std::vector<int> >
119 std::map<int, std::vector<int> >
121 std::map<int, double> cover_std;
125 std::map<int, std::pair<int, double> >
128 int resolution_int = -1;
129 double resolution_double = -1;
131 double rate_constant = 10;
132 double rate_power = 0.001;
135 std::map<int, int> name2id, name2idinv;
137 std::string cover_name;
138 std::string point_cloud_name;
139 std::string color_name;
143 Less(std::map<int, double> func) { Fct = func; }
144 std::map<int, double> Fct;
145 bool operator()(
int a,
int b) {
146 if (Fct[a] == Fct[b])
149 return Fct[a] < Fct[b];
154 void remove_edges(Graph& G) {
155 boost::graph_traits<Graph>::edge_iterator ei, ei_end;
156 for (boost::tie(ei, ei_end) = boost::edges(G); ei != ei_end; ++ei) boost::remove_edge(*ei, G);
160 double GetUniform() {
161 thread_local std::default_random_engine re;
162 thread_local std::uniform_real_distribution<double> Dist(0, 1);
167 void SampleWithoutReplacement(
int populationSize,
int sampleSize, std::vector<int>& samples) {
171 while (m < sampleSize) {
173 if ((populationSize - t) * u >= sampleSize - m) {
212 rate_constant = constant;
233 point_cloud_name = off_file_name;
234 std::ifstream input(off_file_name);
238 while (comment ==
'#') {
239 std::getline(input, line);
240 if (!line.empty() && !all_of(line.begin(), line.end(), (int (*)(int))isspace))
241 comment = line[line.find_first_not_of(
' ')];
243 if (strcmp((
char*)line.c_str(),
"nOFF") == 0) {
245 while (comment ==
'#') {
246 std::getline(input, line);
247 if (!line.empty() && !all_of(line.begin(), line.end(), (int (*)(int))isspace))
248 comment = line[line.find_first_not_of(
' ')];
250 std::stringstream stream(line);
251 stream >> data_dimension;
257 int numedges, numfaces, i, dim;
258 while (comment ==
'#') {
259 std::getline(input, line);
260 if (!line.empty() && !all_of(line.begin(), line.end(), (int (*)(int))isspace))
261 comment = line[line.find_first_not_of(
' ')];
263 std::stringstream stream(line);
270 std::getline(input, line);
271 if (!line.empty() && line[line.find_first_not_of(
' ')] !=
'#' &&
272 !all_of(line.begin(), line.end(), (int (*)(int))isspace)) {
273 std::stringstream iss(line);
274 std::vector<double> point;
275 point.assign(std::istream_iterator<double>(iss), std::istream_iterator<double>());
276 point_cloud.emplace_back(point.begin(), point.begin() + data_dimension);
277 boost::add_vertex(one_skeleton_OFF);
278 vertices.push_back(boost::add_vertex(one_skeleton));
284 while (i < numfaces) {
285 std::getline(input, line);
286 if (!line.empty() && line[line.find_first_not_of(
' ')] !=
'#' &&
287 !all_of(line.begin(), line.end(), (int (*)(int))isspace)) {
288 std::vector<int> simplex;
289 std::stringstream iss(line);
290 simplex.assign(std::istream_iterator<int>(iss), std::istream_iterator<int>());
292 for (
int j = 1; j <= dim; j++)
293 for (
int k = j + 1; k <= dim; k++)
294 boost::add_edge(vertices[simplex[j]], vertices[simplex[k]], one_skeleton_OFF);
299 return input.is_open();
315 remove_edges(one_skeleton);
317 std::ifstream input(graph_file_name);
320 while (std::getline(input, line)) {
321 std::stringstream stream(line);
323 while (stream >> neighb) boost::add_edge(vertices[source], vertices[neighb], one_skeleton);
332 remove_edges(one_skeleton);
333 if (num_edges(one_skeleton_OFF))
334 one_skeleton = one_skeleton_OFF;
336 std::cout <<
"No triangulation read in OFF file!" << std::endl;
346 template <
typename Distance>
348 remove_edges(one_skeleton);
349 if (distances.size() == 0) compute_pairwise_distances(distance);
350 for (
int i = 0; i < n; i++) {
351 for (
int j = i + 1; j < n; j++) {
352 if (distances[i][j] <= threshold) {
353 boost::add_edge(vertices[i], vertices[j], one_skeleton);
354 boost::put(boost::edge_weight, one_skeleton, boost::edge(vertices[i], vertices[j], one_skeleton).first,
362 void set_graph_weights() {
363 Index_map index = boost::get(boost::vertex_index, one_skeleton);
364 Weight_map weight = boost::get(boost::edge_weight, one_skeleton);
365 boost::graph_traits<Graph>::edge_iterator ei, ei_end;
366 for (boost::tie(ei, ei_end) = boost::edges(one_skeleton); ei != ei_end; ++ei)
367 boost::put(weight, *ei,
368 distances[index[boost::source(*ei, one_skeleton)]][index[boost::target(*ei, one_skeleton)]]);
374 template <
typename Distance>
375 void compute_pairwise_distances(Distance ref_distance) {
377 std::vector<double> zeros(n);
378 for (
int i = 0; i < n; i++) distances.push_back(zeros);
379 std::string distance = point_cloud_name +
"_dist";
380 std::ifstream input(distance, std::ios::out | std::ios::binary);
383 if (verbose) std::cout <<
"Reading distances..." << std::endl;
384 for (
int i = 0; i < n; i++) {
385 for (
int j = i; j < n; j++) {
386 input.read((
char*)&d, 8);
393 if (verbose) std::cout <<
"Computing distances..." << std::endl;
395 std::ofstream output(distance, std::ios::out | std::ios::binary);
396 for (
int i = 0; i < n; i++) {
397 int state = (int)floor(100 * (i * 1.0 + 1) / n) % 10;
398 if (state == 0 && verbose) std::cout <<
"\r" << state <<
"%" << std::flush;
399 for (
int j = i; j < n; j++) {
400 double dis = ref_distance(point_cloud[i], point_cloud[j]);
401 distances[i][j] = dis;
402 distances[j][i] = dis;
403 output.write((
char*)&dis, 8);
407 if (verbose) std::cout << std::endl;
421 template <
typename Distance>
423 int m = floor(n / std::exp((1 + rate_power) * std::log(std::log(n) / std::log(rate_constant))));
424 m = std::min(m, n - 1);
425 std::vector<int> samples(m);
428 if (verbose) std::cout << n <<
" points in R^" << data_dimension << std::endl;
429 if (verbose) std::cout <<
"Subsampling " << m <<
" points" << std::endl;
431 if (distances.size() == 0) compute_pairwise_distances(distance);
434 for (
int i = 0; i < N; i++) {
435 SampleWithoutReplacement(n, m, samples);
436 double hausdorff_dist = 0;
437 for (
int j = 0; j < n; j++) {
438 double mj = distances[j][samples[0]];
439 for (
int k = 1; k < m; k++) mj = std::min(mj, distances[j][samples[k]]);
440 hausdorff_dist = std::max(hausdorff_dist, mj);
442 delta += hausdorff_dist / N;
445 if (verbose) std::cout <<
"delta = " << delta << std::endl;
462 std::ifstream input(func_file_name);
465 while (std::getline(input, line)) {
466 std::stringstream stream(line);
471 functional_cover =
true;
472 cover_name = func_file_name;
482 for (
int i = 0; i < n; i++) func.emplace(i, point_cloud[i][k]);
483 functional_cover =
true;
484 cover_name =
"coordinate " + std::to_string(k);
493 template <
class InputRange>
495 for (
int i = 0; i < n; i++) func.emplace(i,
function[i]);
496 functional_cover =
true;
512 if (!functional_cover) {
513 std::cout <<
"Cover needs to come from the preimages of a function." << std::endl;
516 if (type !=
"Nerve" && type !=
"GIC") {
517 std::cout <<
"Type of complex needs to be specified." << std::endl;
522 Index_map index = boost::get(boost::vertex_index, one_skeleton);
525 boost::graph_traits<Graph>::edge_iterator ei, ei_end;
526 for (boost::tie(ei, ei_end) = boost::edges(one_skeleton); ei != ei_end; ++ei)
527 reso = std::max(reso, std::abs(func[index[boost::source(*ei, one_skeleton)]] -
528 func[index[boost::target(*ei, one_skeleton)]]));
529 if (verbose) std::cout <<
"resolution = " << reso << std::endl;
530 resolution_double = reso;
533 if (type ==
"Nerve") {
534 boost::graph_traits<Graph>::edge_iterator ei, ei_end;
535 for (boost::tie(ei, ei_end) = boost::edges(one_skeleton); ei != ei_end; ++ei)
536 reso = std::max(reso, std::abs(func[index[boost::source(*ei, one_skeleton)]] -
537 func[index[boost::target(*ei, one_skeleton)]]) /
539 if (verbose) std::cout <<
"resolution = " << reso << std::endl;
540 resolution_double = reso;
571 if (resolution_double == -1 && resolution_int == -1) {
572 std::cout <<
"Number and/or length of intervals not specified" << std::endl;
576 std::cout <<
"Gain not specified" << std::endl;
581 double minf = std::numeric_limits<float>::max();
582 double maxf = std::numeric_limits<float>::lowest();
583 for (
int i = 0; i < n; i++) {
584 minf = std::min(minf, func[i]);
585 maxf = std::max(maxf, func[i]);
587 if (verbose) std::cout <<
"Min function value = " << minf <<
" and Max function value = " << maxf << std::endl;
590 std::vector<std::pair<double, double> > intervals;
593 if (resolution_double == -1) {
594 double incr = (maxf - minf) / resolution_int;
596 double alpha = (incr * gain) / (2 - 2 * gain);
597 double y = minf + incr + alpha;
598 std::pair<double, double> interm(x, y);
599 intervals.push_back(interm);
600 for (
int i = 1; i < resolution_int - 1; i++) {
601 x = minf + i * incr - alpha;
602 y = minf + (i + 1) * incr + alpha;
603 std::pair<double, double> inter(x, y);
604 intervals.push_back(inter);
606 x = minf + (resolution_int - 1) * incr - alpha;
608 std::pair<double, double> interM(x, y);
609 intervals.push_back(interM);
610 res = intervals.size();
612 for (
int i = 0; i < res; i++)
613 std::cout <<
"Interval " << i <<
" = [" << intervals[i].first <<
", " << intervals[i].second <<
"]" 617 if (resolution_int == -1) {
619 double y = x + resolution_double;
620 while (y <= maxf && maxf - (y - gain * resolution_double) >= resolution_double) {
621 std::pair<double, double> inter(x, y);
622 intervals.push_back(inter);
623 x = y - gain * resolution_double;
624 y = x + resolution_double;
626 std::pair<double, double> interM(x, maxf);
627 intervals.push_back(interM);
628 res = intervals.size();
630 for (
int i = 0; i < res; i++)
631 std::cout <<
"Interval " << i <<
" = [" << intervals[i].first <<
", " << intervals[i].second <<
"]" 636 double y = x + resolution_double;
638 while (count < resolution_int && y <= maxf && maxf - (y - gain * resolution_double) >= resolution_double) {
639 std::pair<double, double> inter(x, y);
640 intervals.push_back(inter);
642 x = y - gain * resolution_double;
643 y = x + resolution_double;
645 res = intervals.size();
647 for (
int i = 0; i < res; i++)
648 std::cout <<
"Interval " << i <<
" = [" << intervals[i].first <<
", " << intervals[i].second <<
"]" 655 std::vector<int> points(n);
656 for (
int i = 0; i < n; i++) points[i] = i;
657 std::sort(points.begin(), points.end(), Less(this->func));
661 Index_map index = boost::get(boost::vertex_index, one_skeleton);
662 std::map<int, std::vector<int> > preimages;
663 std::map<int, double> funcstd;
665 if (verbose) std::cout <<
"Computing preimages..." << std::endl;
666 for (
int i = 0; i < res; i++) {
668 std::pair<double, double> inter1 = intervals[i];
674 std::pair<double, double> inter3 = intervals[i - 1];
675 while (func[points[tmp]] < inter3.second && tmp != n) {
676 preimages[i].push_back(points[tmp]);
684 std::pair<double, double> inter2 = intervals[i + 1];
685 while (func[points[tmp]] < inter2.first && tmp != n) {
686 preimages[i].push_back(points[tmp]);
691 while (func[points[tmp]] < inter1.second && tmp != n) {
692 preimages[i].push_back(points[tmp]);
697 std::pair<double, double> inter3 = intervals[i - 1];
698 while (func[points[tmp]] < inter3.second && tmp != n) {
699 preimages[i].push_back(points[tmp]);
703 preimages[i].push_back(points[tmp]);
710 funcstd[i] = 0.5 * (u + v);
713 if (verbose) std::cout <<
"Computing connected components..." << std::endl;
715 for (
int i = 0; i < res; i++) {
717 Graph G = one_skeleton.create_subgraph();
718 int num = preimages[i].size();
719 std::vector<int> component(num);
720 for (
int j = 0; j < num; j++) boost::add_vertex(index[vertices[preimages[i][j]]], G);
721 boost::connected_components(G, &component[0]);
725 for (
int j = 0; j < num; j++) {
727 if (component[j] > max) max = component[j];
730 int identifier = (std::pow(i + component[j], 2) + 3 * i + component[j]) / 2;
733 cover[preimages[i][j]].push_back(identifier);
734 cover_back[identifier].push_back(preimages[i][j]);
735 cover_fct[identifier] = i;
736 cover_std[identifier] = funcstd[i];
737 cover_color[identifier].second += func_color[preimages[i][j]];
738 cover_color[identifier].first += 1;
745 maximal_dim =
id - 1;
746 for (std::map<
int, std::pair<int, double> >::iterator iit = cover_color.begin(); iit != cover_color.end(); iit++)
747 iit->second.second /= iit->second.first;
760 std::vector<int> cov_elts, cov_number;
761 std::ifstream input(cover_file_name);
763 while (std::getline(input, line)) {
765 std::stringstream stream(line);
766 while (stream >> cov) {
767 cov_elts.push_back(cov);
768 cov_number.push_back(cov);
769 cover_fct[cov] = cov;
770 cover_color[cov].second += func_color[i];
771 cover_color[cov].first++;
772 cover_back[cov].push_back(i);
778 std::sort(cov_number.begin(), cov_number.end());
779 std::vector<int>::iterator it = std::unique(cov_number.begin(), cov_number.end());
780 cov_number.resize(std::distance(cov_number.begin(), it));
782 maximal_dim = cov_number.size() - 1;
783 for (
int i = 0; i <= maximal_dim; i++) cover_color[i].second /= cover_color[i].first;
784 cover_name = cover_file_name;
794 template <
typename Distance>
796 voronoi_subsamples.resize(m);
797 SampleWithoutReplacement(n, m, voronoi_subsamples);
798 if (distances.size() == 0) compute_pairwise_distances(distance);
800 Weight_map weight = boost::get(boost::edge_weight, one_skeleton);
801 Index_map index = boost::get(boost::vertex_index, one_skeleton);
802 std::vector<double> mindist(n);
803 for (
int j = 0; j < n; j++) mindist[j] = std::numeric_limits<double>::max();
807 for (
int i = 0; i < m; i++) {
808 if (verbose) std::cout <<
"Computing geodesic distances to seed " << i <<
"..." << std::endl;
809 int seed = voronoi_subsamples[i];
810 std::vector<double> dmap(n);
811 boost::dijkstra_shortest_paths(
812 one_skeleton, vertices[seed],
813 boost::weight_map(weight).distance_map(boost::make_iterator_property_map(dmap.begin(), index)));
815 for (
int j = 0; j < n; j++)
816 if (mindist[j] > dmap[j]) {
817 mindist[j] = dmap[j];
818 if (cover[j].size() == 0)
819 cover[j].push_back(i);
825 for (
int i = 0; i < n; i++) {
826 cover_back[cover[i][0]].push_back(i);
827 cover_color[cover[i][0]].second += func_color[i];
828 cover_color[cover[i][0]].first++;
830 for (
int i = 0; i < m; i++) cover_color[i].second /= cover_color[i].first;
832 cover_name =
"Voronoi";
842 const std::vector<int>&
subpopulation(
int c) {
return cover_back[name2idinv[c]]; }
857 std::ifstream input(color_file_name);
860 while (std::getline(input, line)) {
861 std::stringstream stream(line);
863 func_color.emplace(i, f);
866 color_name = color_file_name;
876 for (
int i = 0; i < n; i++) func_color[i] = point_cloud[i][k];
877 color_name =
"coordinate ";
878 color_name.append(std::to_string(k));
888 for (
unsigned int i = 0; i < color.size(); i++) func_color[i] = color[i];
897 std::string mapp = point_cloud_name +
"_sc.dot";
898 std::ofstream graphic(mapp);
900 double maxv = std::numeric_limits<double>::lowest();
901 double minv = std::numeric_limits<double>::max();
902 for (std::map<
int, std::pair<int, double> >::iterator iit = cover_color.begin(); iit != cover_color.end(); iit++) {
903 maxv = std::max(maxv, iit->second.second);
904 minv = std::min(minv, iit->second.second);
908 std::vector<int> nodes;
911 graphic <<
"graph GIC {" << std::endl;
913 for (std::map<
int, std::pair<int, double> >::iterator iit = cover_color.begin(); iit != cover_color.end(); iit++) {
914 if (iit->second.first > mask) {
915 nodes.push_back(iit->first);
916 name2id[iit->first] = id;
917 name2idinv[id] = iit->first;
919 graphic << name2id[iit->first] <<
"[shape=circle fontcolor=black color=black label=\"" << name2id[iit->first]
920 <<
":" << iit->second.first <<
"\" style=filled fillcolor=\"" 921 << (1 - (maxv - iit->second.second) / (maxv - minv)) * 0.6 <<
", 1, 1\"]" << std::endl;
926 int num_simplices = simplices.size();
927 for (
int i = 0; i < num_simplices; i++)
928 if (simplices[i].size() == 2) {
929 if (cover_color[simplices[i][0]].first > mask && cover_color[simplices[i][1]].first > mask) {
930 graphic <<
" " << name2id[simplices[i][0]] <<
" -- " << name2id[simplices[i][1]] <<
" [weight=15];" 937 std::cout << mapp <<
" file generated. It can be visualized with e.g. neato." << std::endl;
945 int num_simplices = simplices.size();
947 std::string mapp = point_cloud_name +
"_sc.txt";
948 std::ofstream graphic(mapp);
950 for (
int i = 0; i < num_simplices; i++)
951 if (simplices[i].size() == 2)
952 if (cover_color[simplices[i][0]].first > mask && cover_color[simplices[i][1]].first > mask) num_edges++;
954 graphic << point_cloud_name << std::endl;
955 graphic << cover_name << std::endl;
956 graphic << color_name << std::endl;
957 graphic << resolution_double <<
" " << gain << std::endl;
958 graphic << cover_color.size() <<
" " << num_edges << std::endl;
961 for (std::map<
int, std::pair<int, double> >::iterator iit = cover_color.begin(); iit != cover_color.end(); iit++) {
962 graphic <<
id <<
" " << iit->second.second <<
" " << iit->second.first << std::endl;
963 name2id[iit->first] = id;
964 name2idinv[id] = iit->first;
968 for (
int i = 0; i < num_simplices; i++)
969 if (simplices[i].size() == 2)
970 if (cover_color[simplices[i][0]].first > mask && cover_color[simplices[i][1]].first > mask)
971 graphic << name2id[simplices[i][0]] <<
" " << name2id[simplices[i][1]] << std::endl;
974 <<
" generated. It can be visualized with e.g. python KeplerMapperVisuFromTxtFile.py and firefox." 984 assert(cover_name ==
"Voronoi");
986 int m = voronoi_subsamples.size();
989 std::vector<std::vector<int> > edges, faces;
990 int numsimplices = simplices.size();
992 std::string mapp = point_cloud_name +
"_sc.off";
993 std::ofstream graphic(mapp);
995 graphic <<
"OFF" << std::endl;
996 for (
int i = 0; i < numsimplices; i++) {
997 if (simplices[i].size() == 2) {
999 edges.push_back(simplices[i]);
1001 if (simplices[i].size() == 3) {
1003 faces.push_back(simplices[i]);
1006 graphic << m <<
" " << numedges + numfaces << std::endl;
1007 for (
int i = 0; i < m; i++) {
1008 if (data_dimension <= 3) {
1009 for (
int j = 0; j < data_dimension; j++) graphic << point_cloud[voronoi_subsamples[i]][j] <<
" ";
1010 for (
int j = data_dimension; j < 3; j++) graphic << 0 <<
" ";
1011 graphic << std::endl;
1013 for (
int j = 0; j < 3; j++) graphic << point_cloud[voronoi_subsamples[i]][j] <<
" ";
1016 for (
int i = 0; i < numedges; i++) graphic << 2 <<
" " << edges[i][0] <<
" " << edges[i][1] << std::endl;
1017 for (
int i = 0; i < numfaces; i++)
1018 graphic << 3 <<
" " << faces[i][0] <<
" " << faces[i][1] <<
" " << faces[i][2] << std::endl;
1020 std::cout << mapp <<
" generated. It can be visualized with e.g. geomview." << std::endl;
1035 double maxf = std::numeric_limits<double>::lowest();
1036 double minf = std::numeric_limits<double>::max();
1037 for (std::map<int, double>::iterator it = cover_std.begin(); it != cover_std.end(); it++) {
1038 maxf = std::max(maxf, it->second);
1039 minf = std::min(minf, it->second);
1042 for (
auto const& simplex : simplices) {
1044 std::vector<int> splx = simplex;
1051 double filta = std::numeric_limits<double>::lowest();
1052 double filts = filta;
1053 bool ascending =
true;
1059 filta = std::max(-2 + (cover_std[vertex] - minf) / (maxf - minf), filta);
1060 filts = std::max(2 - (cover_std[vertex] - minf) / (maxf - minf), filts);
1078 for (
int i = 0; i < max_dim; i++) {
1080 int num_bars = bars.size();
1081 if(verbose) std::cout << num_bars <<
" interval(s) in dimension " << i <<
":" << std::endl;
1082 for (
int j = 0; j < num_bars; j++) {
1083 double birth = bars[j].first;
1084 double death = bars[j].second;
1085 if (i == 0 && std::isinf(death))
continue;
1087 birth = minf + (birth + 2) * (maxf - minf);
1089 birth = minf + (2 - birth) * (maxf - minf);
1091 death = minf + (death + 2) * (maxf - minf);
1093 death = minf + (2 - death) * (maxf - minf);
1094 PD.push_back(std::pair<double, double>(birth, death));
1095 if (verbose) std::cout <<
" [" << birth <<
", " << death <<
"]" << std::endl;
1106 template <
typename SimplicialComplex>
1108 if (distribution.size() >= N) {
1109 std::cout <<
"Already done!" << std::endl;
1111 for (
int i = 0; i < N - distribution.size(); i++) {
1114 std::vector<int> boot(this->n);
1115 for (
int j = 0; j < this->n; j++) {
1116 double u = GetUniform();
1117 int id = std::floor(u * (this->n));
1119 Cboot.point_cloud[j] = this->point_cloud[id];
1120 Cboot.func.emplace(j, this->func[
id]);
1122 for (
int j = 0; j < n; j++) {
1123 std::vector<double> dist(n);
1124 for (
int k = 0; k < n; k++) dist[k] = distances[boot[j]][boot[k]];
1125 Cboot.distances.push_back(dist);
1138 std::sort(distribution.begin(), distribution.end());
1149 int N = distribution.size();
1150 return distribution[std::floor(alpha * N)];
1160 int N = distribution.size();
1161 for (
int i = 0; i < N; i++)
1162 if (distribution[i] > d)
return i * 1.0 / N;
1171 double distancemin = -std::numeric_limits<double>::lowest();
1173 for (
int i = 0; i < N; i++) distancemin = std::min(distancemin, 0.5 * (PD[i].second - PD[i].first));
1187 template <
typename SimplicialComplex>
1189 unsigned int dimension = 0;
1190 for (
auto const& simplex : simplices) {
1191 int numvert = simplex.size();
1192 double filt = std::numeric_limits<double>::lowest();
1193 for (
int i = 0; i < numvert; i++) filt = std::max(cover_color[simplex[i]].second, filt);
1194 complex.insert_simplex_and_subfaces(simplex, filt);
1195 if (dimension < simplex.size() - 1) dimension = simplex.size() - 1;
1203 if (type !=
"Nerve" && type !=
"GIC") {
1204 std::cout <<
"Type of complex needs to be specified." << std::endl;
1208 if (type ==
"Nerve") {
1209 for(
auto& simplex : cover)
1210 simplices.push_back(simplex.second);
1211 std::sort(simplices.begin(), simplices.end());
1212 std::vector<std::vector<int> >::iterator it = std::unique(simplices.begin(), simplices.end());
1213 simplices.resize(std::distance(simplices.begin(), it));
1216 if (type ==
"GIC") {
1217 Index_map index = boost::get(boost::vertex_index, one_skeleton);
1219 if (functional_cover) {
1224 throw std::invalid_argument(
1225 "the output of this function is correct ONLY if the cover is minimal, i.e. the gain is less than 0.5.");
1228 boost::graph_traits<Graph>::edge_iterator ei, ei_end;
1229 for (boost::tie(ei, ei_end) = boost::edges(one_skeleton); ei != ei_end; ++ei) {
1230 int nums = cover[index[boost::source(*ei, one_skeleton)]].size();
1231 for (
int i = 0; i < nums; i++) {
1232 int vs = cover[index[boost::source(*ei, one_skeleton)]][i];
1233 int numt = cover[index[boost::target(*ei, one_skeleton)]].size();
1234 for (
int j = 0; j < numt; j++) {
1235 int vt = cover[index[boost::target(*ei, one_skeleton)]][j];
1236 if (cover_fct[vs] == cover_fct[vt] + 1 || cover_fct[vt] == cover_fct[vs] + 1) {
1237 std::vector<int> edge(2);
1238 edge[0] = std::min(vs, vt);
1239 edge[1] = std::max(vs, vt);
1240 simplices.push_back(edge);
1247 std::sort(simplices.begin(), simplices.end());
1248 std::vector<std::vector<int> >::iterator it = std::unique(simplices.begin(), simplices.end());
1249 simplices.resize(std::distance(simplices.begin(), it));
1254 boost::graph_traits<Graph>::edge_iterator ei, ei_end;
1255 for (boost::tie(ei, ei_end) = boost::edges(one_skeleton); ei != ei_end; ++ei)
1256 if (!(cover[index[boost::target(*ei, one_skeleton)]].size() == 1 &&
1257 cover[index[boost::target(*ei, one_skeleton)]] == cover[index[boost::source(*ei, one_skeleton)]])) {
1258 std::vector<int> edge(2);
1259 edge[0] = index[boost::source(*ei, one_skeleton)];
1260 edge[1] = index[boost::target(*ei, one_skeleton)];
1273 std::vector<int> simplx;
1275 unsigned int sz = cover[vertex].size();
1276 for (
unsigned int i = 0; i < sz; i++) {
1277 simplx.push_back(cover[vertex][i]);
1280 std::sort(simplx.begin(), simplx.end());
1281 std::vector<int>::iterator it = std::unique(simplx.begin(), simplx.end());
1282 simplx.resize(std::distance(simplx.begin(), it));
1283 simplices.push_back(simplx);
1286 std::sort(simplices.begin(), simplices.end());
1287 std::vector<std::vector<int> >::iterator it = std::unique(simplices.begin(), simplices.end());
1288 simplices.resize(std::distance(simplices.begin(), it));
void init_coefficients(int charac)
Initializes the coefficient field.
Definition: Persistent_cohomology.h:168
void set_color_from_vector(std::vector< double > color)
Computes the function used to color the nodes of the simplicial complex from a vector stored in memor...
Definition: GIC.h:887
void compute_distribution(int N=100)
Computes bootstrapped distances distribution.
Definition: GIC.h:1107
void plot_DOT()
Creates a .dot file called SC.dot for neato (part of the graphviz package) once the simplicial comple...
Definition: GIC.h:896
bool read_point_cloud(const std::string &off_file_name)
Reads and stores the input point cloud.
Definition: GIC.h:232
void expansion(int max_dim)
Expands the Simplex_tree containing only its one skeleton until dimension max_dim.
Definition: Simplex_tree.h:1033
void set_mask(int nodemask)
Sets the mask, which is a threshold integer such that nodes in the complex that contain a number of d...
Definition: GIC.h:224
void set_function_from_range(InputRange const &function)
Creates the function f from a vector stored in memory.
Definition: GIC.h:494
void set_graph_from_file(const std::string &graph_file_name)
Creates a graph G from a file containing the edges.
Definition: GIC.h:314
Computes the persistent cohomology of a filtered complex.
Definition: Persistent_cohomology.h:64
const std::vector< int > & subpopulation(int c)
Returns the data subset corresponding to a specific node of the created complex.
Definition: GIC.h:842
Simplex Tree data structure for representing simplicial complexes.
Definition: Simplex_tree.h:72
std::pair< Simplex_handle, bool > insert_simplex_and_subfaces(const InputVertexRange &Nsimplex, Filtration_value filtration=0)
Insert a N-simplex and all his subfaces, from a N-simplex represented by a range of Vertex_handles...
Definition: Simplex_tree.h:683
double compute_distance_from_confidence_level(double alpha)
Computes the bottleneck distance threshold corresponding to a specific confidence level...
Definition: GIC.h:1148
void set_type(const std::string &t)
Specifies whether the type of the output simplicial complex.
Definition: GIC.h:193
void find_simplices()
Computes the simplices of the simplicial complex.
Definition: GIC.h:1202
void write_info()
Creates a .txt file called SC.txt describing the 1-skeleton, which can then be plotted with e...
Definition: GIC.h:944
Compute the Euclidean distance between two Points given by a range of coordinates. The points are assumed to have the same dimension.
Definition: distance_functions.h:43
void set_function_from_coordinate(int k)
Creates the function f from the k-th coordinate of the point cloud P.
Definition: GIC.h:481
Definition: SimplicialComplexForAlpha.h:26
Rips complex data structure.
Definition: Rips_complex.h:57
void set_color_from_coordinate(int k=0)
Computes the function used to color the nodes of the simplicial complex from the k-th coordinate...
Definition: GIC.h:875
void create_complex(SimplicialComplex &complex)
Creates the simplicial complex.
Definition: GIC.h:1188
void set_graph_from_OFF()
Creates a graph G from the triangulation given by the input .OFF file.
Definition: GIC.h:331
void set_function_from_file(const std::string &func_file_name)
Creates the function f from a file containing the function values.
Definition: GIC.h:460
void set_subsampling(double constant, double power)
Sets the constants used to subsample the data set. These constants are explained in ...
Definition: GIC.h:211
void set_cover_from_Voronoi(Distance distance, int m=100)
Creates the cover C from the Voronoï cells of a subsampling of the point cloud.
Definition: GIC.h:795
void set_verbose(bool verb=false)
Specifies whether the program should display information or not.
Definition: GIC.h:201
std::vector< std::pair< Filtration_value, Filtration_value > > intervals_in_dimension(int dimension)
Returns persistence intervals for a given dimension.
Definition: Persistent_cohomology.h:703
double compute_p_value()
Computes the p-value, i.e. the opposite of the confidence level of the largest bottleneck distance pr...
Definition: GIC.h:1170
void initialize_filtration()
Initializes the filtrations, i.e. sort the simplices according to their order in the filtration and i...
Definition: Simplex_tree.h:796
Simplex_handle find(const InputVertexRange &s)
Given a range of Vertex_handles, returns the Simplex_handle of the simplex in the simplicial complex ...
Definition: Simplex_tree.h:517
Value type for a filtration function on a cell complex.
Definition: FiltrationValue.h:32
Complex_simplex_range complex_simplex_range()
Returns a range over the simplices of the simplicial complex.
Definition: Simplex_tree.h:214
void assign_filtration(Simplex_handle sh, Filtration_value fv)
Sets the filtration value of a simplex. In debug mode, if sh is a null_simplex.
Definition: Simplex_tree.h:421
Simplex_vertex_range simplex_vertex_range(Simplex_handle sh)
Returns a range over the vertices of a simplex.
Definition: Simplex_tree.h:261
Global distance functions.
void set_graph_from_rips(double threshold, Distance distance)
Creates a graph G from a Rips complex.
Definition: GIC.h:347
bool has_children(SimplexHandle sh) const
Returns true if the node in the simplex tree pointed by sh has children.
Definition: Simplex_tree.h:504
void plot_OFF()
Creates a .off file called SC.off for 3D visualization, which contains the 2-skeleton of the GIC...
Definition: GIC.h:983
double bottleneck_distance(const Persistence_diagram1 &diag1, const Persistence_diagram2 &diag2, double e=(std::numeric_limits< double >::min)())
Function to compute the Bottleneck distance between two persistence diagrams.
Definition: Bottleneck.h:103
int dimension(Simplex_handle sh)
Returns the dimension of a simplex.
Definition: Simplex_tree.h:476
double set_graph_from_automatic_rips(Distance distance, int N=100)
Creates a graph G from a Rips complex whose threshold value is automatically tuned with subsampling—...
Definition: GIC.h:422
void set_color_from_file(const std::string &color_file_name)
Computes the function used to color the nodes of the simplicial complex from a file containing the fu...
Definition: GIC.h:855
double compute_confidence_level_from_distance(double d)
Computes the confidence level of a specific bottleneck distance threshold.
Definition: GIC.h:1159
void set_resolution_with_interval_number(int reso)
Sets a number of intervals from a value stored in memory.
Definition: GIC.h:558
void set_resolution_with_interval_length(double reso)
Sets a length of intervals from a value stored in memory.
Definition: GIC.h:552
void set_cover_from_file(const std::string &cover_file_name)
Creates the cover C from a file containing the cover elements of each point (the order has to be the ...
Definition: GIC.h:757
void set_cover_from_function()
Creates a cover C from the preimages of the function f.
Definition: GIC.h:570
Options::Filtration_value Filtration_value
Type for the value of the filtration function.
Definition: Simplex_tree.h:79
void compute_persistent_cohomology(Filtration_value min_interval_length=0)
Compute the persistent homology of the filtered simplicial complex.
Definition: Persistent_cohomology.h:184
Cover complex data structure.
Definition: GIC.h:91
void compute_PD()
Computes the extended persistence diagram of the complex.
Definition: GIC.h:1031
double set_automatic_resolution()
Computes the optimal length of intervals (i.e. the smallest interval length avoiding discretization a...
Definition: GIC.h:511
This file includes common file reader for GUDHI.
void set_gain(double g=0.3)
Sets a gain from a value stored in memory (default value 0.3).
Definition: GIC.h:564