Skeleton_blocker_link_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): David Salinas
6  *
7  * Copyright (C) 2014 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 SKELETON_BLOCKER_LINK_COMPLEX_H_
24 #define SKELETON_BLOCKER_LINK_COMPLEX_H_
25 
26 #include <gudhi/Skeleton_blocker_complex.h>
27 #include <gudhi/Debug_utils.h>
28 
29 namespace Gudhi {
30 
31 namespace skeleton_blocker {
32 
33 template<class ComplexType> class Skeleton_blocker_sub_complex;
34 
41 template<typename ComplexType>
43 ComplexType> {
44  template<typename T> friend class Skeleton_blocker_link_superior;
45  typedef typename ComplexType::Edge_handle Edge_handle;
46 
47  typedef typename ComplexType::boost_vertex_handle boost_vertex_handle;
48 
49  private:
50  bool only_superior_vertices_;
51 
52  public:
53  typedef typename ComplexType::Vertex_handle Vertex_handle;
54  typedef typename ComplexType::Root_vertex_handle Root_vertex_handle;
55 
56  typedef typename ComplexType::Simplex Simplex;
57  typedef typename ComplexType::Root_simplex_handle Root_simplex_handle;
58 
59  typedef typename ComplexType::Blocker_handle Blocker_handle;
60 
61  typedef typename ComplexType::Root_simplex_handle::Simplex_vertex_const_iterator Root_simplex_handle_iterator;
62 
63  explicit Skeleton_blocker_link_complex(bool only_superior_vertices = false)
64  : only_superior_vertices_(only_superior_vertices) { }
65 
71  Skeleton_blocker_link_complex(const ComplexType & parent_complex,
72  const Simplex& alpha_parent_adress,
73  bool only_superior_vertices = false,
74  bool only_vertices = false)
75  : only_superior_vertices_(only_superior_vertices) {
76  if (!alpha_parent_adress.empty())
77  build_link(parent_complex, alpha_parent_adress, only_vertices);
78  }
79 
84  Skeleton_blocker_link_complex(const ComplexType & parent_complex,
85  Vertex_handle a_parent_adress,
86  bool only_superior_vertices = false)
87  : only_superior_vertices_(only_superior_vertices) {
88  Simplex alpha_simplex(a_parent_adress);
89  build_link(parent_complex, alpha_simplex);
90  }
91 
96  Skeleton_blocker_link_complex(const ComplexType & parent_complex,
97  Edge_handle edge, bool only_superior_vertices =
98  false)
99  : only_superior_vertices_(only_superior_vertices) {
100  Simplex alpha_simplex(parent_complex.first_vertex(edge),
101  parent_complex.second_vertex(edge));
102  build_link(parent_complex, alpha_simplex);
103  }
104 
105  protected:
111  void compute_link_vertices(const ComplexType & parent_complex,
112  const Simplex& alpha_parent_adress,
113  bool only_superior_vertices,
114  bool is_alpha_blocker = false) {
115  if (alpha_parent_adress.dimension() == 0) {
116  // for a vertex we know exactly the number of vertices of the link (and the size of the corresponding vector)
117  // thus we call a specific function that will reserve a vector with appropriate size
118  this->compute_link_vertices(parent_complex,
119  alpha_parent_adress.first_vertex(),
120  only_superior_vertices_);
121  } else {
122  // we compute the intersection of neighbors of alpha and store it in link_vertices
123  Simplex link_vertices_parent;
124  parent_complex.add_neighbours(alpha_parent_adress, link_vertices_parent,
125  only_superior_vertices);
126  // For all vertex 'v' in this intersection, we go through all its adjacent blockers.
127  // If one blocker minus 'v' is included in alpha then the vertex is not in the link complex.
128  for (auto v_parent : link_vertices_parent) {
129  bool new_vertex = true;
130  for (auto beta : parent_complex.const_blocker_range(v_parent)) {
131  if (!is_alpha_blocker || *beta != alpha_parent_adress) {
132  new_vertex = !(alpha_parent_adress.contains_difference(*beta,
133  v_parent));
134  if (!new_vertex)
135  break;
136  }
137  }
138  if (new_vertex)
139  this->add_vertex(parent_complex.get_id(v_parent));
140  }
141  }
142  }
143 
149  void compute_link_vertices(const ComplexType & parent_complex,
150  Vertex_handle alpha_parent_adress,
151  bool only_superior_vertices) {
152  // for a vertex we know exactly the number of vertices of the link (and the size of the corresponding vector
153  this->skeleton.m_vertices.reserve(
154  parent_complex.degree(alpha_parent_adress));
155 
156  // For all vertex 'v' in this intersection, we go through all its adjacent blockers.
157  // If one blocker minus 'v' is included in alpha then the vertex is not in the link complex.
158  for (auto v_parent : parent_complex.vertex_range(alpha_parent_adress)) {
159  if (!only_superior_vertices
160  || v_parent.vertex > alpha_parent_adress.vertex)
161  this->add_vertex(parent_complex.get_id(v_parent));
162  }
163  }
164 
165  void compute_link_edges(const ComplexType & parent_complex,
166  const Simplex& alpha_parent_adress,
167  bool is_alpha_blocker = false) {
168  if (this->num_vertices() <= 1)
169  return;
170 
171  for (auto x_link = this->vertex_range().begin();
172  x_link != this->vertex_range().end(); ++x_link) {
173  for (auto y_link = x_link; ++y_link != this->vertex_range().end();) {
174  Vertex_handle x_parent = *parent_complex.get_address(
175  this->get_id(*x_link));
176  Vertex_handle y_parent = *parent_complex.get_address(
177  this->get_id(*y_link));
178  if (parent_complex.contains_edge(x_parent, y_parent)) {
179  // we check that there is no blocker subset of alpha passing trough x and y
180  bool new_edge = true;
181  for (auto blocker_parent : parent_complex.const_blocker_range(
182  x_parent)) {
183  if (!is_alpha_blocker || *blocker_parent != alpha_parent_adress) {
184  if (blocker_parent->contains(y_parent)) {
185  new_edge = !(alpha_parent_adress.contains_difference(
186  *blocker_parent, x_parent, y_parent));
187  if (!new_edge)
188  break;
189  }
190  }
191  }
192  if (new_edge)
193  this->add_edge_without_blockers(*x_link, *y_link);
194  }
195  }
196  }
197  }
198 
204  boost::optional<Vertex_handle> give_equivalent_vertex(const ComplexType & other_complex,
205  Vertex_handle address) const {
206  Root_vertex_handle id((*this)[address].get_id());
207  return other_complex.get_address(id);
208  }
209 
210  /*
211  * compute the blockers of the link if is_alpha_blocker is false.
212  * Otherwise, alpha is a blocker, and the link is computed in the complex where
213  * the blocker is anticollapsed.
214  */
215  void compute_link_blockers(const ComplexType & parent_complex,
216  const Simplex& alpha_parent,
217  bool is_alpha_blocker = false) {
218  for (auto x_link : this->vertex_range()) {
219  Vertex_handle x_parent = *this->give_equivalent_vertex(parent_complex,
220  x_link);
221 
222  for (auto blocker_parent : parent_complex.const_blocker_range(x_parent)) {
223  if (!is_alpha_blocker || *blocker_parent != alpha_parent) {
224  Simplex sigma_parent(*blocker_parent);
225 
226  sigma_parent.difference(alpha_parent);
227 
228  if (sigma_parent.dimension() >= 2
229  && sigma_parent.first_vertex() == x_parent) {
230  Root_simplex_handle sigma_id(parent_complex.get_id(sigma_parent));
231  auto sigma_link = this->get_simplex_address(sigma_id);
232  // ie if the vertices of sigma are vertices of the link
233  if (sigma_link) {
234  bool is_new_blocker = true;
235  for (auto a : alpha_parent) {
236  for (auto eta_parent : parent_complex.const_blocker_range(a)) {
237  if (!is_alpha_blocker || *eta_parent != alpha_parent) {
238  Simplex eta_minus_alpha(*eta_parent);
239  eta_minus_alpha.difference(alpha_parent);
240  if (eta_minus_alpha != sigma_parent
241  && sigma_parent.contains_difference(*eta_parent,
242  alpha_parent)) {
243  is_new_blocker = false;
244  break;
245  }
246  }
247  }
248  if (!is_new_blocker)
249  break;
250  }
251  if (is_new_blocker)
252  this->add_blocker(new Simplex(*sigma_link));
253  }
254  }
255  }
256  }
257  }
258  }
259 
260  public:
266  void build_link(const ComplexType & parent_complex,
267  const Simplex& alpha_parent_adress,
268  bool is_alpha_blocker = false,
269  bool only_vertices = false) {
270  assert(is_alpha_blocker || parent_complex.contains(alpha_parent_adress));
271  compute_link_vertices(parent_complex, alpha_parent_adress, only_superior_vertices_);
272  if (!only_vertices) {
273  compute_link_edges(parent_complex, alpha_parent_adress, is_alpha_blocker);
274  compute_link_blockers(parent_complex, alpha_parent_adress, is_alpha_blocker);
275  }
276  }
277 
283  friend void build_link_of_blocker(const ComplexType & parent_complex,
284  Simplex& blocker,
286  assert(blocker.dimension() >= 2);
287  assert(parent_complex.contains_blocker(blocker));
288  result.clear();
289  result.build_link(parent_complex, blocker, true);
290  }
291 };
292 
293 } // namespace skeleton_blocker
294 
295 namespace skbl = skeleton_blocker;
296 
297 } // namespace Gudhi
298 
299 #endif // SKELETON_BLOCKER_LINK_COMPLEX_H_
Simplicial subcomplex of a complex represented by a skeleton/blockers pair.
Definition: Skeleton_blocker_link_superior.h:32
Abstract simplex used in Skeleton blockers data-structure.
Definition: Skeleton_blocker_simplex.h:50
void add_blocker(const Root_simplex_handle &blocker_root)
Definition: Skeleton_blocker_sub_complex.h:124
Definition: SimplicialComplexForAlpha.h:26
Root_vertex_handle get_id(Vertex_handle local) const
Definition: Skeleton_blocker_complex.h:455
void add_edge_without_blockers(Root_vertex_handle v1_root, Root_vertex_handle v2_root)
Definition: Skeleton_blocker_sub_complex.h:112
boost::optional< Simplex > get_simplex_address(const Root_simplex_handle &s) const
Compute the local vertices of &#39;s&#39; in the current complex If one of them is not present in the complex...
Definition: Skeleton_blocker_complex.h:931
Vertex_handle add_vertex()
Adds a vertex to the simplicial complex and returns its Vertex_handle.
Definition: Skeleton_blocker_complex.h:384
Complex_vertex_range vertex_range() const
Returns a Complex_vertex_range over all vertices of the complex.
Definition: Skeleton_blocker_complex.h:1296
void clear()
Definition: Skeleton_blocker_sub_complex.h:168
GUDHI  Version 2.2.0  - C++ library for Topological Data Analysis (TDA) and Higher Dimensional Geometry Understanding.  - Copyright : GPL v3 Generated on Thu Jun 14 2018 15:00:55 for GUDHI by Doxygen 1.8.13