Sparse_rips_complex.h
1 /* This file is part of the Gudhi Library. The Gudhi library
2  * (Geometric Understanding in Higher Dimensions) is a generic C++
3  * library for computational topology.
4  *
5  * Author(s): Marc Glisse
6  *
7  * Copyright (C) 2018 Inria
8  *
9  * This program is free software: you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation, either version 3 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program. If not, see <http://www.gnu.org/licenses/>.
21  */
22 
23 #ifndef SPARSE_RIPS_COMPLEX_H_
24 #define SPARSE_RIPS_COMPLEX_H_
25 
26 #include <gudhi/Debug_utils.h>
27 #include <gudhi/graph_simplicial_complex.h>
28 #include <gudhi/choose_n_farthest_points.h>
29 
30 #include <boost/graph/adjacency_list.hpp>
31 #include <boost/range/metafunctions.hpp>
32 
33 #include <vector>
34 
35 namespace Gudhi {
36 
37 namespace rips_complex {
38 
39 // The whole interface is copied on Rips_complex. A redesign should be discussed with all complex creation classes in
40 // mind.
41 
54 template <typename Filtration_value>
56  private:
57  // TODO(MG): use a different graph where we know we can safely insert in parallel.
58  typedef typename boost::adjacency_list<boost::vecS, boost::vecS, boost::undirectedS,
59  boost::property<vertex_filtration_t, Filtration_value>,
60  boost::property<edge_filtration_t, Filtration_value>>
61  Graph;
62 
63  typedef int Vertex_handle;
64 
65  public:
73  template <typename RandomAccessPointRange, typename Distance>
74  Sparse_rips_complex(const RandomAccessPointRange& points, Distance distance, double epsilon) {
75  GUDHI_CHECK(epsilon > 0, "epsilon must be positive");
76  std::vector<Vertex_handle> sorted_points;
77  std::vector<Filtration_value> params;
78  auto dist_fun = [&](Vertex_handle i, Vertex_handle j) { return distance(points[i], points[j]); };
79  Ker<decltype(dist_fun)> kernel(dist_fun);
80  subsampling::choose_n_farthest_points(kernel, boost::irange<Vertex_handle>(0, boost::size(points)), -1, -1,
81  std::back_inserter(sorted_points), std::back_inserter(params));
82  compute_sparse_graph(sorted_points, params, dist_fun, epsilon);
83  }
84 
93  template <typename DistanceMatrix>
94  Sparse_rips_complex(const DistanceMatrix& distance_matrix, double epsilon)
95  : Sparse_rips_complex(boost::irange<Vertex_handle>(0, boost::size(distance_matrix)),
96  [&](Vertex_handle i, Vertex_handle j) { return distance_matrix[j][i]; }, epsilon) {}
97 
108  template <typename SimplicialComplexForRips>
109  void create_complex(SimplicialComplexForRips& complex, int dim_max) {
110  GUDHI_CHECK(complex.num_vertices() == 0,
111  std::invalid_argument("Sparse_rips_complex::create_complex - simplicial complex is not empty"));
112 
113  complex.insert_graph(graph_);
114  complex.expansion(dim_max);
115  }
116 
117  private:
118  // choose_n_farthest_points wants the distance function in this form...
119  template <class Distance>
120  struct Ker {
121  typedef std::size_t Point_d; // index into point range
122  Ker(Distance& d) : dist(d) {}
123  // Despite the name, this is not squared...
124  typedef Distance Squared_distance_d;
125  Squared_distance_d& squared_distance_d_object() const { return dist; }
126  Distance& dist;
127  };
128 
129  // PointRange must be random access.
130  template <typename PointRange, typename ParamRange, typename Distance>
131  void compute_sparse_graph(const PointRange& points, const ParamRange& params, Distance& dist, double epsilon) {
132  const int n = boost::size(points);
133  graph_.~Graph();
134  new (&graph_) Graph(n);
135  // for(auto v : vertices(g)) // doesn't work :-(
136  typename boost::graph_traits<Graph>::vertex_iterator v_i, v_e;
137  for (std::tie(v_i, v_e) = vertices(graph_); v_i != v_e; ++v_i) {
138  auto v = *v_i;
139  // This whole loop might not be necessary, leave it until someone investigates if it is safe to remove.
140  put(vertex_filtration_t(), graph_, v, 0);
141  }
142 
143  // TODO(MG):
144  // - make it parallel
145  // - only test near-enough neighbors
146  for (int i = 0; i < n; ++i)
147  for (int j = i + 1; j < n; ++j) {
148  auto&& pi = points[i];
149  auto&& pj = points[j];
150  auto d = dist(pi, pj);
151  auto li = params[i];
152  auto lj = params[j];
153  GUDHI_CHECK(lj <= li, "Bad furthest point sorting");
154  Filtration_value alpha;
155 
156  // The paper has d/2 and d-lj/e to match the Cech, but we use doubles to match the Rips
157  if (d * epsilon <= 2 * lj)
158  alpha = d;
159  else if (d * epsilon <= li + lj && (epsilon >= 1 || d * epsilon <= lj * (1 + 1 / (1 - epsilon))))
160  alpha = (d - lj / epsilon) * 2;
161  else
162  continue;
163 
164  add_edge(pi, pj, alpha, graph_);
165  }
166  }
167 
168  Graph graph_;
169 };
170 
171 } // namespace rips_complex
172 
173 } // namespace Gudhi
174 
175 #endif // SPARSE_RIPS_COMPLEX_H_
void choose_n_farthest_points(Kernel const &k, Point_range const &input_pts, std::size_t final_size, std::size_t starting_point, PointOutputIterator output_it, DistanceOutputIterator dist_it={})
Subsample by a greedy strategy of iteratively adding the farthest point from the current chosen point...
Definition: choose_n_farthest_points.h:78
void expansion(int max_dim)
Expands the simplicial complex containing only its one skeleton until a given maximal dimension as ex...
void insert_graph(const OneSkeletonGraph &skel_graph)
Inserts a given Gudhi::rips_complex::Rips_complex::OneSkeletonGraph in the simplicial complex...
The concept SimplicialComplexForRips describes the requirements for a type to implement a simplicial ...
Definition: SimplicialComplexForRips.h:33
Definition: SimplicialComplexForAlpha.h:26
Value type for a filtration function on a cell complex.
Definition: FiltrationValue.h:32
std::size_t num_vertices()
Returns the number of vertices in the simplicial complex.
Sparse_rips_complex(const RandomAccessPointRange &points, Distance distance, double epsilon)
Sparse_rips_complex constructor from a list of points.
Definition: Sparse_rips_complex.h:74
Sparse_rips_complex(const DistanceMatrix &distance_matrix, double epsilon)
Sparse_rips_complex constructor from a distance matrix.
Definition: Sparse_rips_complex.h:94
Sparse Rips complex data structure.
Definition: Sparse_rips_complex.h:55
void create_complex(SimplicialComplexForRips &complex, int dim_max)
Fills the simplicial complex with the sparse Rips graph and expands it with all the cliques...
Definition: Sparse_rips_complex.h:109
GUDHI  Version 2.3.0  - C++ library for Topological Data Analysis (TDA) and Higher Dimensional Geometry Understanding.  - Copyright : GPL v3 Generated on Tue Sep 4 2018 14:33:00 for GUDHI by Doxygen 1.8.13