GIC.h
1 /* This file is part of the Gudhi Library - https://gudhi.inria.fr/ - which is released under MIT.
2  * See file LICENSE or go to https://gudhi.inria.fr/licensing/ for full license details.
3  * Author: Mathieu Carriere
4  *
5  * Copyright (C) 2017 Inria
6  *
7  * Modification(s):
8  * - 2019/08 Vincent Rouvreau: Fix issue #10 for CGAL
9  * - YYYY/MM Author: Description of the modification
10  */
11 
12 #ifndef GIC_H_
13 #define GIC_H_
14 
15 #ifdef GUDHI_USE_TBB
16 #include <tbb/parallel_for.h>
17 #include <mutex>
18 #endif
19 
20 #include <gudhi/Debug_utils.h>
21 #include <gudhi/graph_simplicial_complex.h>
22 #include <gudhi/reader_utils.h>
23 #include <gudhi/Simplex_tree.h>
24 #include <gudhi/Rips_complex.h>
25 #include <gudhi/Points_off_io.h>
27 #include <gudhi/Persistent_cohomology.h>
28 #include <gudhi/Bottleneck.h>
29 
30 #include <boost/config.hpp>
31 #include <boost/graph/graph_traits.hpp>
32 #include <boost/graph/adjacency_list.hpp>
33 #include <boost/graph/connected_components.hpp>
34 #include <boost/graph/dijkstra_shortest_paths.hpp>
35 #include <boost/graph/subgraph.hpp>
36 #include <boost/graph/graph_utility.hpp>
37 
38 #include <CGAL/version.h> // for CGAL_VERSION_NR
39 
40 #include <iostream>
41 #include <vector>
42 #include <map>
43 #include <string>
44 #include <limits> // for numeric_limits
45 #include <utility> // for std::pair<>
46 #include <algorithm> // for (std::max)
47 #include <random>
48 #include <cassert>
49 #include <cmath>
50 
51 namespace Gudhi {
52 
53 namespace cover_complex {
54 
58 using Persistence_diagram = std::vector<std::pair<double, double> >;
59 using Graph = boost::subgraph<
60  boost::adjacency_list<boost::setS, boost::vecS, boost::undirectedS, boost::no_property,
61  boost::property<boost::edge_index_t, int, boost::property<boost::edge_weight_t, double> > > >;
62 using Vertex_t = boost::graph_traits<Graph>::vertex_descriptor;
63 using Index_map = boost::property_map<Graph, boost::vertex_index_t>::type;
64 using Weight_map = boost::property_map<Graph, boost::edge_weight_t>::type;
65 
86 template <typename Point>
88  private:
89  bool verbose = false; // whether to display information.
90  std::string type; // Nerve or GIC
91 
92  std::vector<Point> point_cloud; // input point cloud.
93  std::vector<std::vector<double> > distances; // all pairwise distances.
94  int maximal_dim; // maximal dimension of output simplicial complex.
95  int data_dimension; // dimension of input data.
96  int n; // number of points.
97 
98  std::vector<double> func; // function used to compute the output simplicial complex.
99  std::vector<double> func_color; // function used to compute the colors of the nodes of the output simplicial complex.
100  bool functional_cover = false; // whether we use a cover with preimages of a function or not.
101 
102  Graph one_skeleton_OFF; // one-skeleton given by the input OFF file (if it exists).
103  Graph one_skeleton; // one-skeleton used to compute the connected components.
104  std::vector<Vertex_t> vertices; // vertices of one_skeleton.
105 
106  std::vector<std::vector<int> > simplices; // simplices of output simplicial complex.
107  std::vector<int> voronoi_subsamples; // Voronoi germs (in case of Voronoi cover).
108 
109  Persistence_diagram PD;
110  std::vector<double> distribution;
111 
112  std::vector<std::vector<int> >
113  cover; // function associating to each data point the vector of cover elements to which it belongs.
114  std::map<int, std::vector<int> >
115  cover_back; // inverse of cover, in order to get the data points associated to a specific cover element.
116  std::map<int, double> cover_std; // standard function (induced by func) used to compute the extended persistence
117  // diagram of the output simplicial complex.
118  std::map<int, int>
119  cover_fct; // integer-valued function that allows to state if two elements of the cover are consecutive or not.
120  std::map<int, std::pair<int, double> >
121  cover_color; // size and coloring (induced by func_color) of the vertices of the output simplicial complex.
122 
123  int resolution_int = -1;
124  double resolution_double = -1;
125  double gain = -1;
126  double rate_constant = 10; // Constant in the subsampling.
127  double rate_power = 0.001; // Power in the subsampling.
128  int mask = 0; // Ignore nodes containing less than mask points.
129 
130  std::map<int, int> name2id, name2idinv;
131 
132  std::string cover_name;
133  std::string point_cloud_name;
134  std::string color_name;
135 
136  // Remove all edges of a graph.
137  void remove_edges(Graph& G) {
138  boost::graph_traits<Graph>::edge_iterator ei, ei_end;
139  for (boost::tie(ei, ei_end) = boost::edges(G); ei != ei_end; ++ei) boost::remove_edge(*ei, G);
140  }
141 
142  // Thread local is not available on XCode version < V.8
143  // If not available, random engine is a class member.
144 #ifndef GUDHI_CAN_USE_CXX11_THREAD_LOCAL
145  std::default_random_engine re;
146 #endif // GUDHI_CAN_USE_CXX11_THREAD_LOCAL
147 
148  // Find random number in [0,1].
149  double GetUniform() {
150  // Thread local is not available on XCode version < V.8
151  // If available, random engine is defined for each thread.
152 #ifdef GUDHI_CAN_USE_CXX11_THREAD_LOCAL
153  thread_local std::default_random_engine re;
154 #endif // GUDHI_CAN_USE_CXX11_THREAD_LOCAL
155  std::uniform_real_distribution<double> Dist(0, 1);
156  return Dist(re);
157  }
158 
159  // Subsample points.
160  void SampleWithoutReplacement(int populationSize, int sampleSize, std::vector<int>& samples) {
161  int t = 0;
162  int m = 0;
163  double u;
164  while (m < sampleSize) {
165  u = GetUniform();
166  if ((populationSize - t) * u >= sampleSize - m) {
167  t++;
168  } else {
169  samples[m] = t;
170  t++;
171  m++;
172  }
173  }
174  }
175 
176  // *******************************************************************************************************************
177  // Utils.
178  // *******************************************************************************************************************
179 
180  public:
186  void set_type(const std::string& t) { type = t; }
187 
188  public:
194  void set_verbose(bool verb = false) { verbose = verb; }
195 
196  public:
204  void set_subsampling(double constant, double power) {
205  rate_constant = constant;
206  rate_power = power;
207  }
208 
209  public:
217  void set_mask(int nodemask) { mask = nodemask; }
218 
219  public:
220 
221 
227  void set_point_cloud_from_range(const std::vector<std::vector<double> > & point_cloud) {
228  n = point_cloud.size(); data_dimension = point_cloud[0].size();
229  point_cloud_name = "matrix"; cover.resize(n);
230  for(int i = 0; i < n; i++){
231  boost::add_vertex(one_skeleton_OFF);
232  vertices.push_back(boost::add_vertex(one_skeleton));
233  }
234  this->point_cloud = point_cloud;
235  }
236 
242  bool read_point_cloud(const std::string& off_file_name) {
243  point_cloud_name = off_file_name;
244  std::ifstream input(off_file_name);
245  std::string line;
246 
247  char comment = '#';
248  while (comment == '#') {
249  std::getline(input, line);
250  if (!line.empty() && !all_of(line.begin(), line.end(), (int (*)(int))isspace))
251  comment = line[line.find_first_not_of(' ')];
252  }
253  if (strcmp((char*)line.c_str(), "nOFF") == 0) {
254  comment = '#';
255  while (comment == '#') {
256  std::getline(input, line);
257  if (!line.empty() && !all_of(line.begin(), line.end(), (int (*)(int))isspace))
258  comment = line[line.find_first_not_of(' ')];
259  }
260  std::stringstream stream(line);
261  stream >> data_dimension;
262  } else {
263  data_dimension = 3;
264  }
265 
266  comment = '#';
267  int numedges, numfaces, i, dim;
268  while (comment == '#') {
269  std::getline(input, line);
270  if (!line.empty() && !all_of(line.begin(), line.end(), (int (*)(int))isspace))
271  comment = line[line.find_first_not_of(' ')];
272  }
273  std::stringstream stream(line);
274  stream >> n;
275  stream >> numfaces;
276  stream >> numedges;
277 
278  i = 0;
279  while (i < n) {
280  std::getline(input, line);
281  if (!line.empty() && line[line.find_first_not_of(' ')] != '#' &&
282  !all_of(line.begin(), line.end(), (int (*)(int))isspace)) {
283  std::stringstream iss(line);
284  std::vector<double> point;
285  point.assign(std::istream_iterator<double>(iss), std::istream_iterator<double>());
286  point_cloud.emplace_back(point.begin(), point.begin() + data_dimension);
287  boost::add_vertex(one_skeleton_OFF);
288  vertices.push_back(boost::add_vertex(one_skeleton));
289  cover.emplace_back();
290  i++;
291  }
292  }
293 
294  i = 0;
295  while (i < numfaces) {
296  std::getline(input, line);
297  if (!line.empty() && line[line.find_first_not_of(' ')] != '#' &&
298  !all_of(line.begin(), line.end(), (int (*)(int))isspace)) {
299  std::vector<int> simplex;
300  std::stringstream iss(line);
301  simplex.assign(std::istream_iterator<int>(iss), std::istream_iterator<int>());
302  dim = simplex[0];
303  for (int j = 1; j <= dim; j++)
304  for (int k = j + 1; k <= dim; k++)
305  boost::add_edge(vertices[simplex[j]], vertices[simplex[k]], one_skeleton_OFF);
306  i++;
307  }
308  }
309 
310  return input.is_open();
311  }
312 
313  // *******************************************************************************************************************
314  // Graphs.
315  // *******************************************************************************************************************
316 
317  public: // Set graph from file.
325  void set_graph_from_file(const std::string& graph_file_name) {
326  remove_edges(one_skeleton);
327  int neighb;
328  std::ifstream input(graph_file_name);
329  std::string line;
330  int source;
331  while (std::getline(input, line)) {
332  std::stringstream stream(line);
333  stream >> source;
334  while (stream >> neighb) boost::add_edge(vertices[source], vertices[neighb], one_skeleton);
335  }
336  }
337 
338  public: // Set graph from OFF file.
343  remove_edges(one_skeleton);
344  if (num_edges(one_skeleton_OFF))
345  one_skeleton = one_skeleton_OFF;
346  else
347  std::cout << "No triangulation read in OFF file!" << std::endl;
348  }
349 
350  public: // Set graph from Rips complex.
357  template <typename Distance>
358  void set_graph_from_rips(double threshold, Distance distance) {
359  remove_edges(one_skeleton);
360  if (distances.size() == 0) compute_pairwise_distances(distance);
361  for (int i = 0; i < n; i++) {
362  for (int j = i + 1; j < n; j++) {
363  if (distances[i][j] <= threshold) {
364  boost::add_edge(vertices[i], vertices[j], one_skeleton);
365  boost::put(boost::edge_weight, one_skeleton, boost::edge(vertices[i], vertices[j], one_skeleton).first,
366  distances[i][j]);
367  }
368  }
369  }
370  }
371 
372  public:
373  void set_graph_weights() {
374  Index_map index = boost::get(boost::vertex_index, one_skeleton);
375  Weight_map weight = boost::get(boost::edge_weight, one_skeleton);
376  boost::graph_traits<Graph>::edge_iterator ei, ei_end;
377  for (boost::tie(ei, ei_end) = boost::edges(one_skeleton); ei != ei_end; ++ei)
378  boost::put(weight, *ei,
379  distances[index[boost::source(*ei, one_skeleton)]][index[boost::target(*ei, one_skeleton)]]);
380  }
381 
382  public:
388  void set_distances_from_range(const std::vector<std::vector<double> > & distance_matrix) {
389  n = distance_matrix.size(); data_dimension = 0; point_cloud_name = "matrix";
390  cover.resize(n); point_cloud.resize(n);
391  for(int i = 0; i < n; i++){
392  boost::add_vertex(one_skeleton_OFF);
393  vertices.push_back(boost::add_vertex(one_skeleton));
394  }
395  distances = distance_matrix;
396  }
397 
398  public: // Pairwise distances.
401  template <typename Distance>
402  void compute_pairwise_distances(Distance ref_distance) {
403  double d;
404  std::vector<double> zeros(n);
405  for (int i = 0; i < n; i++) distances.push_back(zeros);
406  std::string distance = point_cloud_name + "_dist";
407  std::ifstream input(distance, std::ios::out | std::ios::binary);
408 
409  if (input.good()) {
410  if (verbose) std::cout << "Reading distances..." << std::endl;
411  for (int i = 0; i < n; i++) {
412  for (int j = i; j < n; j++) {
413  input.read((char*)&d, 8);
414  distances[i][j] = d;
415  distances[j][i] = d;
416  }
417  }
418  input.close();
419  } else {
420  if (verbose) std::cout << "Computing distances..." << std::endl;
421  input.close();
422  std::ofstream output(distance, std::ios::out | std::ios::binary);
423  for (int i = 0; i < n; i++) {
424  int state = (int)floor(100 * (i * 1.0 + 1) / n) % 10;
425  if (state == 0 && verbose) std::cout << "\r" << state << "%" << std::flush;
426  for (int j = i; j < n; j++) {
427  double dis = ref_distance(point_cloud[i], point_cloud[j]);
428  distances[i][j] = dis;
429  distances[j][i] = dis;
430  output.write((char*)&dis, 8);
431  }
432  }
433  output.close();
434  if (verbose) std::cout << std::endl;
435  }
436  }
437 
438  public: // Automatic tuning of Rips complex.
448  template <typename Distance>
449  double set_graph_from_automatic_rips(Distance distance, int N = 100) {
450  int m = floor(n / std::exp((1 + rate_power) * std::log(std::log(n) / std::log(rate_constant))));
451  m = (std::min)(m, n - 1);
452  double delta = 0;
453 
454  if (verbose) std::cout << n << " points in R^" << data_dimension << std::endl;
455  if (verbose) std::cout << "Subsampling " << m << " points" << std::endl;
456 
457  if (distances.size() == 0) compute_pairwise_distances(distance);
458 
459  // This cannot be parallelized if thread_local is not defined
460  // thread_local is not defined for XCode < v.8
461  #if defined(GUDHI_USE_TBB) && defined(GUDHI_CAN_USE_CXX11_THREAD_LOCAL)
462  std::mutex deltamutex;
463  tbb::parallel_for(0, N, [&](int i){
464  std::vector<int> samples(m);
465  SampleWithoutReplacement(n, m, samples);
466  double hausdorff_dist = 0;
467  for (int j = 0; j < n; j++) {
468  double mj = distances[j][samples[0]];
469  for (int k = 1; k < m; k++) mj = (std::min)(mj, distances[j][samples[k]]);
470  hausdorff_dist = (std::max)(hausdorff_dist, mj);
471  }
472  deltamutex.lock();
473  delta += hausdorff_dist / N;
474  deltamutex.unlock();
475  });
476  #else
477  for (int i = 0; i < N; i++) {
478  std::vector<int> samples(m);
479  SampleWithoutReplacement(n, m, samples);
480  double hausdorff_dist = 0;
481  for (int j = 0; j < n; j++) {
482  double mj = distances[j][samples[0]];
483  for (int k = 1; k < m; k++) mj = (std::min)(mj, distances[j][samples[k]]);
484  hausdorff_dist = (std::max)(hausdorff_dist, mj);
485  }
486  delta += hausdorff_dist / N;
487  }
488  #endif
489 
490  if (verbose) std::cout << "delta = " << delta << std::endl;
491  set_graph_from_rips(delta, distance);
492  return delta;
493  }
494 
495  // *******************************************************************************************************************
496  // Functions.
497  // *******************************************************************************************************************
498 
499  public: // Set function from file.
505  void set_function_from_file(const std::string& func_file_name) {
506  int i = 0;
507  std::ifstream input(func_file_name);
508  std::string line;
509  double f;
510  while (std::getline(input, line)) {
511  std::stringstream stream(line);
512  stream >> f;
513  func.push_back(f);
514  i++;
515  }
516  functional_cover = true;
517  cover_name = func_file_name;
518  }
519 
520  public: // Set function from kth coordinate
527  if(point_cloud[0].size() > 0){
528  for (int i = 0; i < n; i++) func.push_back(point_cloud[i][k]);
529  functional_cover = true;
530  cover_name = "coordinate " + std::to_string(k);
531  }
532  else{
533  std::cout << "Only pairwise distances provided---cannot access " << k << "th coordinate; returning null vector instead" << std::endl;
534  for (int i = 0; i < n; i++) func.push_back(0.0);
535  functional_cover = true;
536  cover_name = "null";
537  }
538  }
539 
540  public: // Set function from vector.
546  template <class InputRange>
547  void set_function_from_range(InputRange const& function) {
548  for (int i = 0; i < n; i++) func.push_back(function[i]);
549  functional_cover = true;
550  }
551 
552  // *******************************************************************************************************************
553  // Covers.
554  // *******************************************************************************************************************
555 
556  public: // Automatic tuning of resolution.
565  if (!functional_cover) {
566  std::cout << "Cover needs to come from the preimages of a function." << std::endl;
567  return 0;
568  }
569  if (type != "Nerve" && type != "GIC") {
570  std::cout << "Type of complex needs to be specified." << std::endl;
571  return 0;
572  }
573 
574  double reso = 0;
575  Index_map index = boost::get(boost::vertex_index, one_skeleton);
576 
577  if (type == "GIC") {
578  boost::graph_traits<Graph>::edge_iterator ei, ei_end;
579  for (boost::tie(ei, ei_end) = boost::edges(one_skeleton); ei != ei_end; ++ei)
580  reso = (std::max)(reso, std::abs(func[index[boost::source(*ei, one_skeleton)]] -
581  func[index[boost::target(*ei, one_skeleton)]]));
582  if (verbose) std::cout << "resolution = " << reso << std::endl;
583  resolution_double = reso;
584  }
585 
586  if (type == "Nerve") {
587  boost::graph_traits<Graph>::edge_iterator ei, ei_end;
588  for (boost::tie(ei, ei_end) = boost::edges(one_skeleton); ei != ei_end; ++ei)
589  reso = (std::max)(reso, std::abs(func[index[boost::source(*ei, one_skeleton)]] -
590  func[index[boost::target(*ei, one_skeleton)]]) /
591  gain);
592  if (verbose) std::cout << "resolution = " << reso << std::endl;
593  resolution_double = reso;
594  }
595 
596  return reso;
597  }
598 
599  public:
605  void set_resolution_with_interval_length(double reso) { resolution_double = reso; }
611  void set_resolution_with_interval_number(int reso) { resolution_int = reso; }
617  void set_gain(double g = 0.3) { gain = g; }
618 
619  public: // Set cover with preimages of function.
624  if (resolution_double == -1 && resolution_int == -1) {
625  std::cout << "Number and/or length of intervals not specified" << std::endl;
626  return;
627  }
628  if (gain == -1) {
629  std::cout << "Gain not specified" << std::endl;
630  return;
631  }
632 
633  // Read function values and compute min and max
634  double minf = (std::numeric_limits<float>::max)();
635  double maxf = std::numeric_limits<float>::lowest();
636  for (int i = 0; i < n; i++) {
637  minf = (std::min)(minf, func[i]);
638  maxf = (std::max)(maxf, func[i]);
639  }
640  if (verbose) std::cout << "Min function value = " << minf << " and Max function value = " << maxf << std::endl;
641 
642  // Compute cover of im(f)
643  std::vector<std::pair<double, double> > intervals;
644  int res;
645 
646  if (resolution_double == -1) { // Case we use an integer for the number of intervals.
647  double incr = (maxf - minf) / resolution_int;
648  double x = minf;
649  double alpha = (incr * gain) / (2 - 2 * gain);
650  double y = minf + incr + alpha;
651  std::pair<double, double> interm(x, y);
652  intervals.push_back(interm);
653  for (int i = 1; i < resolution_int - 1; i++) {
654  x = minf + i * incr - alpha;
655  y = minf + (i + 1) * incr + alpha;
656  std::pair<double, double> inter(x, y);
657  intervals.push_back(inter);
658  }
659  x = minf + (resolution_int - 1) * incr - alpha;
660  y = maxf;
661  std::pair<double, double> interM(x, y);
662  intervals.push_back(interM);
663  res = intervals.size();
664  if (verbose) {
665  for (int i = 0; i < res; i++)
666  std::cout << "Interval " << i << " = [" << intervals[i].first << ", " << intervals[i].second << "]"
667  << std::endl;
668  }
669  } else {
670  if (resolution_int == -1) { // Case we use a double for the length of the intervals.
671  double x = minf;
672  double y = x + resolution_double;
673  while (y <= maxf && maxf - (y - gain * resolution_double) >= resolution_double) {
674  std::pair<double, double> inter(x, y);
675  intervals.push_back(inter);
676  x = y - gain * resolution_double;
677  y = x + resolution_double;
678  }
679  std::pair<double, double> interM(x, maxf);
680  intervals.push_back(interM);
681  res = intervals.size();
682  if (verbose) {
683  for (int i = 0; i < res; i++)
684  std::cout << "Interval " << i << " = [" << intervals[i].first << ", " << intervals[i].second << "]"
685  << std::endl;
686  }
687  } else { // Case we use an integer and a double for the length of the intervals.
688  double x = minf;
689  double y = x + resolution_double;
690  int count = 0;
691  while (count < resolution_int && y <= maxf && maxf - (y - gain * resolution_double) >= resolution_double) {
692  std::pair<double, double> inter(x, y);
693  intervals.push_back(inter);
694  count++;
695  x = y - gain * resolution_double;
696  y = x + resolution_double;
697  }
698  res = intervals.size();
699  if (verbose) {
700  for (int i = 0; i < res; i++)
701  std::cout << "Interval " << i << " = [" << intervals[i].first << ", " << intervals[i].second << "]"
702  << std::endl;
703  }
704  }
705  }
706 
707  // Sort points according to function values
708  std::vector<int> points(n);
709  for (int i = 0; i < n; i++) points[i] = i;
710  std::sort(points.begin(), points.end(), [this](int p1, int p2){return (this->func[p1] < this->func[p2]);});
711 
712  int id = 0;
713  int pos = 0;
714  Index_map index = boost::get(boost::vertex_index, one_skeleton); // int maxc = -1;
715  std::map<int, std::vector<int> > preimages;
716  std::map<int, double> funcstd;
717 
718  if (verbose) std::cout << "Computing preimages..." << std::endl;
719  for (int i = 0; i < res; i++) {
720  // Find points in the preimage
721  std::pair<double, double> inter1 = intervals[i];
722  int tmp = pos;
723  double u, v;
724 
725  if (i != res - 1) {
726  if (i != 0) {
727  std::pair<double, double> inter3 = intervals[i - 1];
728  while (func[points[tmp]] < inter3.second && tmp != n) {
729  preimages[i].push_back(points[tmp]);
730  tmp++;
731  }
732  u = inter3.second;
733  } else {
734  u = inter1.first;
735  }
736 
737  std::pair<double, double> inter2 = intervals[i + 1];
738  while (func[points[tmp]] < inter2.first && tmp != n) {
739  preimages[i].push_back(points[tmp]);
740  tmp++;
741  }
742  v = inter2.first;
743  pos = tmp;
744  while (func[points[tmp]] < inter1.second && tmp != n) {
745  preimages[i].push_back(points[tmp]);
746  tmp++;
747  }
748 
749  } else {
750  std::pair<double, double> inter3 = intervals[i - 1];
751  while (func[points[tmp]] < inter3.second && tmp != n) {
752  preimages[i].push_back(points[tmp]);
753  tmp++;
754  }
755  while (tmp != n) {
756  preimages[i].push_back(points[tmp]);
757  tmp++;
758  }
759  u = inter3.second;
760  v = inter1.second;
761  }
762 
763  funcstd[i] = 0.5 * (u + v);
764  }
765 
766  #ifdef GUDHI_USE_TBB
767  if (verbose) std::cout << "Computing connected components (parallelized)..." << std::endl;
768  std::mutex covermutex, idmutex;
769  tbb::parallel_for(0, res, [&](int i){
770  // Compute connected components
771  Graph G = one_skeleton.create_subgraph();
772  int num = preimages[i].size();
773  std::vector<int> component(num);
774  for (int j = 0; j < num; j++) boost::add_vertex(index[vertices[preimages[i][j]]], G);
775  boost::connected_components(G, &component[0]);
776  int max = 0;
777 
778  // For each point in preimage
779  for (int j = 0; j < num; j++) {
780  // Update number of components in preimage
781  if (component[j] > max) max = component[j];
782 
783  // Identify component with Cantor polynomial N^2 -> N
784  int identifier = ((i + component[j])*(i + component[j]) + 3 * i + component[j]) / 2;
785 
786  // Update covers
787  covermutex.lock();
788  cover[preimages[i][j]].push_back(identifier);
789  cover_back[identifier].push_back(preimages[i][j]);
790  cover_fct[identifier] = i;
791  cover_std[identifier] = funcstd[i];
792  cover_color[identifier].second += func_color[preimages[i][j]];
793  cover_color[identifier].first += 1;
794  covermutex.unlock();
795  }
796 
797  // Maximal dimension is total number of connected components
798  idmutex.lock();
799  id += max + 1;
800  idmutex.unlock();
801  });
802  #else
803  if (verbose) std::cout << "Computing connected components..." << std::endl;
804  for (int i = 0; i < res; i++) {
805  // Compute connected components
806  Graph G = one_skeleton.create_subgraph();
807  int num = preimages[i].size();
808  std::vector<int> component(num);
809  for (int j = 0; j < num; j++) boost::add_vertex(index[vertices[preimages[i][j]]], G);
810  boost::connected_components(G, &component[0]);
811  int max = 0;
812 
813  // For each point in preimage
814  for (int j = 0; j < num; j++) {
815  // Update number of components in preimage
816  if (component[j] > max) max = component[j];
817 
818  // Identify component with Cantor polynomial N^2 -> N
819  int identifier = (std::pow(i + component[j], 2) + 3 * i + component[j]) / 2;
820 
821  // Update covers
822  cover[preimages[i][j]].push_back(identifier);
823  cover_back[identifier].push_back(preimages[i][j]);
824  cover_fct[identifier] = i;
825  cover_std[identifier] = funcstd[i];
826  cover_color[identifier].second += func_color[preimages[i][j]];
827  cover_color[identifier].first += 1;
828  }
829 
830  // Maximal dimension is total number of connected components
831  id += max + 1;
832  }
833  #endif
834 
835  maximal_dim = id - 1;
836  for (std::map<int, std::pair<int, double> >::iterator iit = cover_color.begin(); iit != cover_color.end(); iit++)
837  iit->second.second /= iit->second.first;
838  }
839 
840  public: // Set cover from file.
847  void set_cover_from_file(const std::string& cover_file_name) {
848  int i = 0;
849  int cov;
850  std::vector<int> cov_elts, cov_number;
851  std::ifstream input(cover_file_name);
852  std::string line;
853  while (std::getline(input, line)) {
854  cov_elts.clear();
855  std::stringstream stream(line);
856  while (stream >> cov) {
857  cov_elts.push_back(cov);
858  cov_number.push_back(cov);
859  cover_fct[cov] = cov;
860  cover_color[cov].second += func_color[i];
861  cover_color[cov].first++;
862  cover_back[cov].push_back(i);
863  }
864  cover[i] = cov_elts;
865  i++;
866  }
867 
868  std::sort(cov_number.begin(), cov_number.end());
869  std::vector<int>::iterator it = std::unique(cov_number.begin(), cov_number.end());
870  cov_number.resize(std::distance(cov_number.begin(), it));
871 
872  maximal_dim = cov_number.size() - 1;
873  for (int i = 0; i <= maximal_dim; i++) cover_color[i].second /= cover_color[i].first;
874  cover_name = cover_file_name;
875  }
876 
877  public: // Set cover from Voronoi
884  template <typename Distance>
885  void set_cover_from_Voronoi(Distance distance, int m = 100) {
886  voronoi_subsamples.resize(m);
887  SampleWithoutReplacement(n, m, voronoi_subsamples);
888  if (distances.size() == 0) compute_pairwise_distances(distance);
889  set_graph_weights();
890  Weight_map weight = boost::get(boost::edge_weight, one_skeleton);
891  Index_map index = boost::get(boost::vertex_index, one_skeleton);
892  std::vector<double> mindist(n);
893  for (int j = 0; j < n; j++) mindist[j] = (std::numeric_limits<double>::max)();
894 
895  // Compute the geodesic distances to subsamples with Dijkstra
896  #ifdef GUDHI_USE_TBB
897  if (verbose) std::cout << "Computing geodesic distances (parallelized)..." << std::endl;
898  std::mutex coverMutex; std::mutex mindistMutex;
899  tbb::parallel_for(0, m, [&](int i){
900  int seed = voronoi_subsamples[i];
901  std::vector<double> dmap(n);
902  boost::dijkstra_shortest_paths(
903  one_skeleton, vertices[seed],
904  boost::weight_map(weight).distance_map(boost::make_iterator_property_map(dmap.begin(), index)));
905 
906  coverMutex.lock(); mindistMutex.lock();
907  for (int j = 0; j < n; j++)
908  if (mindist[j] > dmap[j]) {
909  mindist[j] = dmap[j];
910  if (cover[j].size() == 0)
911  cover[j].push_back(i);
912  else
913  cover[j][0] = i;
914  }
915  coverMutex.unlock(); mindistMutex.unlock();
916  });
917  #else
918  for (int i = 0; i < m; i++) {
919  if (verbose) std::cout << "Computing geodesic distances to seed " << i << "..." << std::endl;
920  int seed = voronoi_subsamples[i];
921  std::vector<double> dmap(n);
922  boost::dijkstra_shortest_paths(
923  one_skeleton, vertices[seed],
924  boost::weight_map(weight).distance_map(boost::make_iterator_property_map(dmap.begin(), index)));
925 
926  for (int j = 0; j < n; j++)
927  if (mindist[j] > dmap[j]) {
928  mindist[j] = dmap[j];
929  if (cover[j].size() == 0)
930  cover[j].push_back(i);
931  else
932  cover[j][0] = i;
933  }
934  }
935  #endif
936 
937  for (int i = 0; i < n; i++) {
938  cover_back[cover[i][0]].push_back(i);
939  cover_color[cover[i][0]].second += func_color[i];
940  cover_color[cover[i][0]].first++;
941  }
942  for (int i = 0; i < m; i++) cover_color[i].second /= cover_color[i].first;
943  maximal_dim = m - 1;
944  cover_name = "Voronoi";
945  }
946 
947  public: // return subset of data corresponding to a node
954  const std::vector<int>& subpopulation(int c) { return cover_back[name2idinv[c]]; }
955 
956  // *******************************************************************************************************************
957  // Visualization.
958  // *******************************************************************************************************************
959 
960  public: // Set color from file.
967  void set_color_from_file(const std::string& color_file_name) {
968  int i = 0;
969  std::ifstream input(color_file_name);
970  std::string line;
971  double f;
972  while (std::getline(input, line)) {
973  std::stringstream stream(line);
974  stream >> f;
975  func_color.push_back(f);
976  i++;
977  }
978  color_name = color_file_name;
979  }
980 
981  public: // Set color from kth coordinate
987  void set_color_from_coordinate(int k = 0) {
988  if(point_cloud[0].size() > 0){
989  for (int i = 0; i < n; i++) func_color.push_back(point_cloud[i][k]);
990  color_name = "coordinate ";
991  color_name.append(std::to_string(k));
992  }
993  else{
994  std::cout << "Only pairwise distances provided---cannot access " << k << "th coordinate; returning null vector instead" << std::endl;
995  for (int i = 0; i < n; i++) func.push_back(0.0);
996  functional_cover = true;
997  cover_name = "null";
998  }
999  }
1000 
1001  public: // Set color from vector.
1007  void set_color_from_range(std::vector<double> color) {
1008  for (unsigned int i = 0; i < color.size(); i++) func_color.push_back(color[i]);
1009  }
1010 
1011  public: // Create a .dot file that can be compiled with neato to produce a .pdf file.
1016  void plot_DOT() {
1017  std::string mapp = point_cloud_name + "_sc.dot";
1018  std::ofstream graphic(mapp);
1019 
1020  double maxv = std::numeric_limits<double>::lowest();
1021  double minv = (std::numeric_limits<double>::max)();
1022  for (std::map<int, std::pair<int, double> >::iterator iit = cover_color.begin(); iit != cover_color.end(); iit++) {
1023  maxv = (std::max)(maxv, iit->second.second);
1024  minv = (std::min)(minv, iit->second.second);
1025  }
1026 
1027  int k = 0;
1028  std::vector<int> nodes;
1029  nodes.clear();
1030 
1031  graphic << "graph GIC {" << std::endl;
1032  int id = 0;
1033  for (std::map<int, std::pair<int, double> >::iterator iit = cover_color.begin(); iit != cover_color.end(); iit++) {
1034  if (iit->second.first > mask) {
1035  nodes.push_back(iit->first);
1036  name2id[iit->first] = id;
1037  name2idinv[id] = iit->first;
1038  id++;
1039  graphic << name2id[iit->first] << "[shape=circle fontcolor=black color=black label=\"" << name2id[iit->first]
1040  << ":" << iit->second.first << "\" style=filled fillcolor=\""
1041  << (1 - (maxv - iit->second.second) / (maxv - minv)) * 0.6 << ", 1, 1\"]" << std::endl;
1042  k++;
1043  }
1044  }
1045  int ke = 0;
1046  int num_simplices = simplices.size();
1047  for (int i = 0; i < num_simplices; i++)
1048  if (simplices[i].size() == 2) {
1049  if (cover_color[simplices[i][0]].first > mask && cover_color[simplices[i][1]].first > mask) {
1050  graphic << " " << name2id[simplices[i][0]] << " -- " << name2id[simplices[i][1]] << " [weight=15];"
1051  << std::endl;
1052  ke++;
1053  }
1054  }
1055  graphic << "}";
1056  graphic.close();
1057  std::cout << mapp << " file generated. It can be visualized with e.g. neato." << std::endl;
1058  }
1059 
1060  public: // Create a .txt file that can be compiled with KeplerMapper.
1064  void write_info() {
1065  int num_simplices = simplices.size();
1066  int num_edges = 0;
1067  std::string mapp = point_cloud_name + "_sc.txt";
1068  std::ofstream graphic(mapp);
1069 
1070  for (int i = 0; i < num_simplices; i++)
1071  if (simplices[i].size() == 2)
1072  if (cover_color[simplices[i][0]].first > mask && cover_color[simplices[i][1]].first > mask) num_edges++;
1073 
1074  graphic << point_cloud_name << std::endl;
1075  graphic << cover_name << std::endl;
1076  graphic << color_name << std::endl;
1077  graphic << resolution_double << " " << gain << std::endl;
1078  graphic << cover_color.size() << " " << num_edges << std::endl;
1079 
1080  int id = 0;
1081  for (std::map<int, std::pair<int, double> >::iterator iit = cover_color.begin(); iit != cover_color.end(); iit++) {
1082  graphic << id << " " << iit->second.second << " " << iit->second.first << std::endl;
1083  name2id[iit->first] = id;
1084  name2idinv[id] = iit->first;
1085  id++;
1086  }
1087 
1088  for (int i = 0; i < num_simplices; i++)
1089  if (simplices[i].size() == 2)
1090  if (cover_color[simplices[i][0]].first > mask && cover_color[simplices[i][1]].first > mask)
1091  graphic << name2id[simplices[i][0]] << " " << name2id[simplices[i][1]] << std::endl;
1092  graphic.close();
1093  std::cout << mapp
1094  << " generated. It can be visualized with e.g. python KeplerMapperVisuFromTxtFile.py and firefox."
1095  << std::endl;
1096  }
1097 
1098  public: // Create a .off file that can be visualized (e.g. with Geomview).
1103  void plot_OFF() {
1104  assert(cover_name == "Voronoi");
1105 
1106  int m = voronoi_subsamples.size();
1107  int numedges = 0;
1108  int numfaces = 0;
1109  std::vector<std::vector<int> > edges, faces;
1110  int numsimplices = simplices.size();
1111 
1112  std::string mapp = point_cloud_name + "_sc.off";
1113  std::ofstream graphic(mapp);
1114 
1115  graphic << "OFF" << std::endl;
1116  for (int i = 0; i < numsimplices; i++) {
1117  if (simplices[i].size() == 2) {
1118  numedges++;
1119  edges.push_back(simplices[i]);
1120  }
1121  if (simplices[i].size() == 3) {
1122  numfaces++;
1123  faces.push_back(simplices[i]);
1124  }
1125  }
1126  graphic << m << " " << numedges + numfaces << std::endl;
1127  for (int i = 0; i < m; i++) {
1128  if (data_dimension <= 3) {
1129  for (int j = 0; j < data_dimension; j++) graphic << point_cloud[voronoi_subsamples[i]][j] << " ";
1130  for (int j = data_dimension; j < 3; j++) graphic << 0 << " ";
1131  graphic << std::endl;
1132  } else {
1133  for (int j = 0; j < 3; j++) graphic << point_cloud[voronoi_subsamples[i]][j] << " ";
1134  }
1135  }
1136  for (int i = 0; i < numedges; i++) graphic << 2 << " " << edges[i][0] << " " << edges[i][1] << std::endl;
1137  for (int i = 0; i < numfaces; i++)
1138  graphic << 3 << " " << faces[i][0] << " " << faces[i][1] << " " << faces[i][2] << std::endl;
1139  graphic.close();
1140  std::cout << mapp << " generated. It can be visualized with e.g. geomview." << std::endl;
1141  }
1142 
1143  // *******************************************************************************************************************
1144  // Extended Persistence Diagrams.
1145  // *******************************************************************************************************************
1146 
1147  public:
1151  Persistence_diagram compute_PD() {
1152  Simplex_tree st;
1153 
1154  // Compute max and min
1155  double maxf = std::numeric_limits<double>::lowest();
1156  double minf = (std::numeric_limits<double>::max)();
1157  for (std::map<int, double>::iterator it = cover_std.begin(); it != cover_std.end(); it++) {
1158  maxf = (std::max)(maxf, it->second);
1159  minf = (std::min)(minf, it->second);
1160  }
1161 
1162  // Build filtration
1163  for (auto const& simplex : simplices) {
1164  std::vector<int> splx = simplex;
1165  splx.push_back(-2);
1166  st.insert_simplex_and_subfaces(splx, -3);
1167  }
1168 
1169  for (std::map<int, double>::iterator it = cover_std.begin(); it != cover_std.end(); it++) {
1170  int vertex = it->first; float val = it->second;
1171  int vert[] = {vertex}; int edge[] = {vertex, -2};
1172  if(st.find(vert) != st.null_simplex()){
1173  st.assign_filtration(st.find(vert), -2 + (val - minf)/(maxf - minf));
1174  st.assign_filtration(st.find(edge), 2 - (val - minf)/(maxf - minf));
1175  }
1176  }
1178 
1179  // Compute PD
1182 
1183  // Output PD
1184  int max_dim = st.dimension();
1185  for (int i = 0; i < max_dim; i++) {
1186  std::vector<std::pair<double, double> > bars = pcoh.intervals_in_dimension(i);
1187  int num_bars = bars.size(); if(i == 0) num_bars -= 1;
1188  if(verbose) std::cout << num_bars << " interval(s) in dimension " << i << ":" << std::endl;
1189  for (int j = 0; j < num_bars; j++) {
1190  double birth = bars[j].first;
1191  double death = bars[j].second;
1192  if (i == 0 && std::isinf(death)) continue;
1193  if (birth < 0)
1194  birth = minf + (birth + 2) * (maxf - minf);
1195  else
1196  birth = minf + (2 - birth) * (maxf - minf);
1197  if (death < 0)
1198  death = minf + (death + 2) * (maxf - minf);
1199  else
1200  death = minf + (2 - death) * (maxf - minf);
1201  PD.push_back(std::pair<double, double>(birth, death));
1202  if (verbose) std::cout << " [" << birth << ", " << death << "]" << std::endl;
1203  }
1204  }
1205  return PD;
1206  }
1207 
1208  public:
1214  void compute_distribution(unsigned int N = 100) {
1215  unsigned int sz = distribution.size();
1216  if (sz >= N) {
1217  std::cout << "Already done!" << std::endl;
1218  } else {
1219  for (unsigned int i = 0; i < N - sz; i++) {
1220  if (verbose) std::cout << "Computing " << i << "th bootstrap, bottleneck distance = ";
1221 
1222  Cover_complex Cboot; Cboot.n = this->n; Cboot.data_dimension = this->data_dimension; Cboot.type = this->type; Cboot.functional_cover = true;
1223 
1224  std::vector<int> boot(this->n);
1225  for (int j = 0; j < this->n; j++) {
1226  double u = GetUniform();
1227  int id = std::floor(u * (this->n)); boot[j] = id;
1228  Cboot.point_cloud.push_back(this->point_cloud[id]); Cboot.cover.emplace_back(); Cboot.func.push_back(this->func[id]);
1229  boost::add_vertex(Cboot.one_skeleton_OFF); Cboot.vertices.push_back(boost::add_vertex(Cboot.one_skeleton));
1230  }
1231  Cboot.set_color_from_range(Cboot.func);
1232 
1233  for (int j = 0; j < n; j++) {
1234  std::vector<double> dist(n);
1235  for (int k = 0; k < n; k++) dist[k] = distances[boot[j]][boot[k]];
1236  Cboot.distances.push_back(dist);
1237  }
1238 
1240  Cboot.set_gain();
1241  Cboot.set_automatic_resolution();
1242  Cboot.set_cover_from_function();
1243  Cboot.find_simplices();
1244  Cboot.compute_PD();
1245  double db = Gudhi::persistence_diagram::bottleneck_distance(this->PD, Cboot.PD);
1246  if (verbose) std::cout << db << std::endl;
1247  distribution.push_back(db);
1248  }
1249 
1250  std::sort(distribution.begin(), distribution.end());
1251  }
1252  }
1253 
1254  public:
1261  unsigned int N = distribution.size();
1262  double d = distribution[std::floor(alpha * N)];
1263  if (verbose) std::cout << "Distance corresponding to confidence " << alpha << " is " << d << std::endl;
1264  return d;
1265  }
1266 
1267  public:
1274  unsigned int N = distribution.size();
1275  double level = 1;
1276  for (unsigned int i = 0; i < N; i++)
1277  if (distribution[i] >= d){ level = i * 1.0 / N; break; }
1278  if (verbose) std::cout << "Confidence level of distance " << d << " is " << level << std::endl;
1279  return level;
1280  }
1281 
1282  public:
1287  double compute_p_value() {
1288  double distancemin = (std::numeric_limits<double>::max)(); int N = PD.size();
1289  for (int i = 0; i < N; i++) distancemin = (std::min)(distancemin, 0.5 * std::abs(PD[i].second - PD[i].first));
1290  double p_value = 1 - compute_confidence_level_from_distance(distancemin);
1291  if (verbose) std::cout << "p value = " << p_value << std::endl;
1292  return p_value;
1293  }
1294 
1295  // *******************************************************************************************************************
1296  // Computation of simplices.
1297  // *******************************************************************************************************************
1298 
1299  public:
1305  template <typename SimplicialComplex>
1306  void create_complex(SimplicialComplex& complex) {
1307  unsigned int dimension = 0;
1308  for (auto const& simplex : simplices) {
1309  int numvert = simplex.size();
1310  double filt = std::numeric_limits<double>::lowest();
1311  for (int i = 0; i < numvert; i++) filt = (std::max)(cover_color[simplex[i]].second, filt);
1312  complex.insert_simplex_and_subfaces(simplex, filt);
1313  if (dimension < simplex.size() - 1) dimension = simplex.size() - 1;
1314  }
1315  }
1316 
1317  public:
1321  if (type != "Nerve" && type != "GIC") {
1322  std::cout << "Type of complex needs to be specified." << std::endl;
1323  return;
1324  }
1325 
1326  if (type == "Nerve") {
1327  for(int i = 0; i < n; i++) simplices.push_back(cover[i]);
1328  std::sort(simplices.begin(), simplices.end());
1329  std::vector<std::vector<int> >::iterator it = std::unique(simplices.begin(), simplices.end());
1330  simplices.resize(std::distance(simplices.begin(), it));
1331  }
1332 
1333  if (type == "GIC") {
1334  Index_map index = boost::get(boost::vertex_index, one_skeleton);
1335 
1336  if (functional_cover) {
1337  // Computes the simplices in the GIC by looking at all the edges of the graph and adding the
1338  // corresponding edges in the GIC if the images of the endpoints belong to consecutive intervals.
1339 
1340  if (gain >= 0.5)
1341  throw std::invalid_argument(
1342  "the output of this function is correct ONLY if the cover is minimal, i.e. the gain is less than 0.5.");
1343 
1344  // Loop on all edges.
1345  boost::graph_traits<Graph>::edge_iterator ei, ei_end;
1346  for (boost::tie(ei, ei_end) = boost::edges(one_skeleton); ei != ei_end; ++ei) {
1347  int nums = cover[index[boost::source(*ei, one_skeleton)]].size();
1348  for (int i = 0; i < nums; i++) {
1349  int vs = cover[index[boost::source(*ei, one_skeleton)]][i];
1350  int numt = cover[index[boost::target(*ei, one_skeleton)]].size();
1351  for (int j = 0; j < numt; j++) {
1352  int vt = cover[index[boost::target(*ei, one_skeleton)]][j];
1353  if (cover_fct[vs] == cover_fct[vt] + 1 || cover_fct[vt] == cover_fct[vs] + 1) {
1354  std::vector<int> edge(2);
1355  edge[0] = (std::min)(vs, vt);
1356  edge[1] = (std::max)(vs, vt);
1357  simplices.push_back(edge);
1358  goto afterLoop;
1359  }
1360  }
1361  }
1362  afterLoop:;
1363  }
1364  std::sort(simplices.begin(), simplices.end());
1365  std::vector<std::vector<int> >::iterator it = std::unique(simplices.begin(), simplices.end());
1366  simplices.resize(std::distance(simplices.begin(), it));
1367 
1368  } else {
1369  // Find edges to keep
1370  Simplex_tree st;
1371  boost::graph_traits<Graph>::edge_iterator ei, ei_end;
1372  for (boost::tie(ei, ei_end) = boost::edges(one_skeleton); ei != ei_end; ++ei)
1373  if (!(cover[index[boost::target(*ei, one_skeleton)]].size() == 1 &&
1374  cover[index[boost::target(*ei, one_skeleton)]] == cover[index[boost::source(*ei, one_skeleton)]])) {
1375  std::vector<int> edge(2);
1376  edge[0] = index[boost::source(*ei, one_skeleton)];
1377  edge[1] = index[boost::target(*ei, one_skeleton)];
1378  st.insert_simplex_and_subfaces(edge);
1379  }
1380 
1381  // st.insert_graph(one_skeleton);
1382 
1383  // Build the Simplex Tree corresponding to the graph
1384  st.expansion(maximal_dim);
1385 
1386  // Find simplices of GIC
1387  simplices.clear();
1388  for (auto simplex : st.complex_simplex_range()) {
1389  if (!st.has_children(simplex)) {
1390  std::vector<int> simplx;
1391  for (auto vertex : st.simplex_vertex_range(simplex)) {
1392  unsigned int sz = cover[vertex].size();
1393  for (unsigned int i = 0; i < sz; i++) {
1394  simplx.push_back(cover[vertex][i]);
1395  }
1396  }
1397  std::sort(simplx.begin(), simplx.end());
1398  std::vector<int>::iterator it = std::unique(simplx.begin(), simplx.end());
1399  simplx.resize(std::distance(simplx.begin(), it));
1400  simplices.push_back(simplx);
1401  }
1402  }
1403  std::sort(simplices.begin(), simplices.end());
1404  std::vector<std::vector<int> >::iterator it = std::unique(simplices.begin(), simplices.end());
1405  simplices.resize(std::distance(simplices.begin(), it));
1406  }
1407  }
1408  }
1409 };
1410 
1411 } // namespace cover_complex
1412 
1413 } // namespace Gudhi
1414 
1415 #endif // GIC_H_
void init_coefficients(int charac)
Initializes the coefficient field.
Definition: Persistent_cohomology.h:156
void plot_DOT()
Creates a .dot file called SC.dot for neato (part of the graphviz package) once the simplicial comple...
Definition: GIC.h:1016
bool read_point_cloud(const std::string &off_file_name)
Reads and stores the input point cloud from .(n)OFF file.
Definition: GIC.h:242
void expansion(int max_dim)
Expands the Simplex_tree containing only its one skeleton until dimension max_dim.
Definition: Simplex_tree.h:1102
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:217
void set_function_from_range(InputRange const &function)
Creates the function f from a vector stored in memory.
Definition: GIC.h:547
void set_graph_from_file(const std::string &graph_file_name)
Creates a graph G from a file containing the edges.
Definition: GIC.h:325
Computes the persistent cohomology of a filtered complex.
Definition: Persistent_cohomology.h:52
const std::vector< int > & subpopulation(int c)
Returns the data subset corresponding to a specific node of the created complex.
Definition: GIC.h:954
Simplex Tree data structure for representing simplicial complexes.
Definition: Simplex_tree.h:60
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:750
double compute_distance_from_confidence_level(double alpha)
Computes the bottleneck distance threshold corresponding to a specific confidence level...
Definition: GIC.h:1260
void set_type(const std::string &t)
Specifies whether the type of the output simplicial complex.
Definition: GIC.h:186
void find_simplices()
Computes the simplices of the simplicial complex.
Definition: GIC.h:1320
void write_info()
Creates a .txt file called SC.txt describing the 1-skeleton, which can then be plotted with e...
Definition: GIC.h:1064
static Simplex_handle null_simplex()
Returns a Simplex_handle different from all Simplex_handles associated to the simplices in the simpli...
Definition: Simplex_tree.h:498
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:34
void set_function_from_coordinate(int k)
Creates the function f from the k-th coordinate of the point cloud P.
Definition: GIC.h:526
Persistence_diagram compute_PD()
Computes the extended persistence diagram of the complex.
Definition: GIC.h:1151
Definition: SimplicialComplexForAlpha.h:14
Rips complex data structure.
Definition: Rips_complex.h:45
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:987
void create_complex(SimplicialComplex &complex)
Creates the simplicial complex.
Definition: GIC.h:1306
void set_graph_from_OFF()
Creates a graph G from the triangulation given by the input .OFF file.
Definition: GIC.h:342
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:505
void set_subsampling(double constant, double power)
Sets the constants used to subsample the data set. These constants are explained in ...
Definition: GIC.h:204
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:885
void set_color_from_range(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:1007
void set_verbose(bool verb=false)
Specifies whether the program should display information or not.
Definition: GIC.h:194
bool make_filtration_non_decreasing()
This function ensures that each simplex has a higher filtration value than its faces by increasing th...
Definition: Simplex_tree.h:1321
std::vector< std::pair< Filtration_value, Filtration_value > > intervals_in_dimension(int dimension)
Returns persistence intervals for a given dimension.
Definition: Persistent_cohomology.h:697
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:1287
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:584
Value type for a filtration function on a cell complex.
Definition: FiltrationValue.h:20
Complex_simplex_range complex_simplex_range()
Returns a range over the simplices of the simplicial complex.
Definition: Simplex_tree.h:202
void assign_filtration(Simplex_handle sh, Filtration_value fv)
Sets the filtration value of a simplex.
Definition: Simplex_tree.h:488
Simplex_vertex_range simplex_vertex_range(Simplex_handle sh)
Returns a range over the vertices of a simplex.
Definition: Simplex_tree.h:249
void set_distances_from_range(const std::vector< std::vector< double > > &distance_matrix)
Reads and stores the distance matrices from vector stored in memory.
Definition: GIC.h:388
Global distance functions.
void set_graph_from_rips(double threshold, Distance distance)
Creates a graph G from a Rips complex.
Definition: GIC.h:358
bool has_children(SimplexHandle sh) const
Returns true if the node in the simplex tree pointed by sh has children.
Definition: Simplex_tree.h:571
void compute_distribution(unsigned int N=100)
Computes bootstrapped distances distribution.
Definition: GIC.h:1214
void plot_OFF()
Creates a .off file called SC.off for 3D visualization, which contains the 2-skeleton of the GIC...
Definition: GIC.h:1103
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:112
int dimension(Simplex_handle sh)
Returns the dimension of a simplex.
Definition: Simplex_tree.h:543
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:449
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:967
double compute_confidence_level_from_distance(double d)
Computes the confidence level of a specific bottleneck distance threshold.
Definition: GIC.h:1273
void set_resolution_with_interval_number(int reso)
Sets a number of intervals from a value stored in memory.
Definition: GIC.h:611
void set_resolution_with_interval_length(double reso)
Sets a length of intervals from a value stored in memory.
Definition: GIC.h:605
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:847
void set_cover_from_function()
Creates a cover C from the preimages of the function f.
Definition: GIC.h:623
Options::Filtration_value Filtration_value
Type for the value of the filtration function.
Definition: Simplex_tree.h:67
void compute_persistent_cohomology(Filtration_value min_interval_length=0)
Compute the persistent homology of the filtered simplicial complex.
Definition: Persistent_cohomology.h:172
Cover complex data structure.
Definition: GIC.h:87
double set_automatic_resolution()
Computes the optimal length of intervals (i.e. the smallest interval length avoiding discretization a...
Definition: GIC.h:564
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:617
void set_point_cloud_from_range(const std::vector< std::vector< double > > &point_cloud)
Reads and stores the input point cloud from vector stored in memory.
Definition: GIC.h:227
GUDHI  Version 3.1.1  - C++ library for Topological Data Analysis (TDA) and Higher Dimensional Geometry Understanding.  - Copyright : MIT Generated on Fri Feb 7 2020 16:35:36 for GUDHI by Doxygen 1.8.13