Skeleton_blocker_simplifiable_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_SIMPLIFIABLE_COMPLEX_H_
24 #define SKELETON_BLOCKER_SIMPLIFIABLE_COMPLEX_H_
25 
26 #include <gudhi/Skeleton_blocker/Skeleton_blocker_sub_complex.h>
27 
28 #include <list>
29 #include <vector>
30 #include <set>
31 
32 namespace Gudhi {
33 
34 namespace skeleton_blocker {
35 
44 template<typename SkeletonBlockerDS>
46  assert(this->contains_blocker(*sigma));
48  build_link_of_blocker(*this, *sigma, link_blocker_sigma);
49  return link_blocker_sigma.is_contractible() == CONTRACTIBLE;
50 }
51 
56 template<typename SkeletonBlockerDS>
58  std::list<Vertex_handle> vertex_to_check;
59  for (auto v : this->vertex_range())
60  vertex_to_check.push_front(v);
61 
62  while (!vertex_to_check.empty()) {
63  Vertex_handle v = vertex_to_check.front();
64  vertex_to_check.pop_front();
65 
66  bool blocker_popable_found = true;
67  while (blocker_popable_found) {
68  blocker_popable_found = false;
69  for (auto block : this->blocker_range(v)) {
70  if (this->is_popable_blocker(block)) {
71  for (Vertex_handle nv : *block)
72  if (nv != v) vertex_to_check.push_back(nv);
73  this->delete_blocker(block);
74  blocker_popable_found = true;
75  break;
76  }
77  }
78  }
79  }
80 }
81 
85 template<typename SkeletonBlockerDS>
87  bool blocker_popable_found = true;
88  while (blocker_popable_found) {
89  blocker_popable_found = false;
90  for (auto block : this->blocker_range(v)) {
91  if (is_popable_blocker(block)) {
92  this->delete_blocker(block);
93  blocker_popable_found = true;
94  }
95  }
96  }
97 }
98 
104 template<typename SkeletonBlockerDS>
106  std::list<Vertex_handle> vertex_to_check;
107  vertex_to_check.push_front(v);
108 
109  while (!vertex_to_check.empty()) {
110  Vertex_handle v = vertex_to_check.front();
111  vertex_to_check.pop_front();
112 
113  bool blocker_popable_found = true;
114  while (blocker_popable_found) {
115  blocker_popable_found = false;
116  for (auto block : this->blocker_range(v)) {
117  if (this->is_popable_blocker(block)) {
118  for (Vertex_handle nv : *block)
119  if (nv != v) vertex_to_check.push_back(nv);
120  this->delete_blocker(block);
121  blocker_popable_found = true;
122  break;
123  }
124  }
125  }
126  }
127 }
128 
132 template<typename SkeletonBlockerDS>
134  // we remove the blockers that are not consistent anymore
135  update_blockers_after_remove_star_of_vertex_or_edge(Simplex(v));
136  while (this->degree(v) > 0) {
137  Vertex_handle w(* (adjacent_vertices(v.vertex, this->skeleton).first));
138  this->remove_edge(v, w);
139  }
140  this->remove_vertex(v);
141 }
142 
148 template<typename SkeletonBlockerDS>
150  std::list <Blocker_handle> blockers_to_update;
151  if (simplex_to_be_removed.empty()) return;
152 
153  auto v0 = simplex_to_be_removed.first_vertex();
154  for (auto blocker : this->blocker_range(v0)) {
155  if (blocker->contains(simplex_to_be_removed))
156  blockers_to_update.push_back(blocker);
157  }
158 
159  for (auto blocker_to_update : blockers_to_update) {
160  Simplex sub_blocker_to_be_added;
161  bool sub_blocker_need_to_be_added =
162  (blocker_to_update->dimension() - simplex_to_be_removed.dimension()) >= 2;
163  if (sub_blocker_need_to_be_added) {
164  sub_blocker_to_be_added = *blocker_to_update;
165  sub_blocker_to_be_added.difference(simplex_to_be_removed);
166  }
167  this->delete_blocker(blocker_to_update);
168  if (sub_blocker_need_to_be_added)
169  this->add_blocker(sub_blocker_to_be_added);
170  }
171 }
172 
177 template<typename SkeletonBlockerDS>
179  update_blockers_after_remove_star_of_vertex_or_edge(Simplex(a, b));
180  // we remove the edge
181  this->remove_edge(a, b);
182 }
183 
187 template<typename SkeletonBlockerDS>
189  return remove_star(this->first_vertex(e), this->second_vertex(e));
190 }
191 
195 template<typename SkeletonBlockerDS>
197  assert(this->contains(sigma));
198  if (sigma.dimension() == 0) {
199  remove_star(sigma.first_vertex());
200  } else if (sigma.dimension() == 1) {
201  remove_star(sigma.first_vertex(), sigma.last_vertex());
202  } else {
203  remove_blocker_containing_simplex(sigma);
204  this->add_blocker(sigma);
205  }
206 }
207 
208 template<typename SkeletonBlockerDS>
210  // to add a simplex s, all blockers included in s are first removed
211  // and then all simplex in the coboundary of s are added as blockers
212  assert(!this->contains(sigma));
213  assert(sigma.dimension() > 1);
214  if (!contains_vertices(sigma)) {
215  std::cerr << "add_simplex: Some vertices were not present in the complex, adding them" << std::endl;
216  size_t num_vertices_to_add = sigma.last_vertex() - this->num_vertices() + 1;
217  for (size_t i = 0; i < num_vertices_to_add; ++i)
218  this->add_vertex();
219  }
220  assert(contains_vertices(sigma));
221  if (!contains_edges(sigma))
222  add_edge(sigma);
223  remove_blocker_include_in_simplex(sigma);
224  add_blockers_after_simplex_insertion(sigma);
225 }
226 
227 template<typename SkeletonBlockerDS>
229  if (sigma.dimension() < 1) return;
230 
231  for (auto s : coboundary_range(sigma)) {
232  this->add_blocker(s);
233  }
234 }
235 
239 template<typename SkeletonBlockerDS>
241  std::vector <Blocker_handle> blockers_to_remove;
242  for (auto blocker : this->blocker_range(sigma.first_vertex())) {
243  if (blocker->contains(sigma))
244  blockers_to_remove.push_back(blocker);
245  }
246  for (auto blocker_to_update : blockers_to_remove)
247  this->delete_blocker(blocker_to_update);
248 }
249 
253 template<typename SkeletonBlockerDS>
255  // TODO(DS): write efficiently by using only superior blockers
256  // eg for all s, check blockers whose vertices are all greater than s
257  std::set <Blocker_handle> blockers_to_remove;
258  for (auto s : sigma) {
259  for (auto blocker : this->blocker_range(s)) {
260  if (sigma.contains(*blocker))
261  blockers_to_remove.insert(blocker);
262  }
263  }
264  for (auto blocker_to_update : blockers_to_remove) {
265  auto s = *blocker_to_update;
266  this->delete_blocker(blocker_to_update);
267  // now if there is a vertex v in the link of s
268  // and v is not included in sigma then v.s is a blocker
269  // (all faces of v.s are there since v belongs to the link of s)
270  for (const auto& b : coboundary_range(s))
271  if (!sigma.contains(b))
272  this->add_blocker(b);
273  }
274 }
275 
281 template<typename SkeletonBlockerDS>
283  std::vector<Simplex> & buffer) const {
284  for (auto const & blocker : this->const_blocker_range(a)) {
285  Simplex beta = (*blocker);
286  beta.remove_vertex(a);
287  buffer.push_back(beta);
288  }
289 
290  Simplex n;
291  this->add_neighbours(b, n);
292  this->remove_neighbours(a, n);
293  n.remove_vertex(a);
294 
295 
296  for (Vertex_handle y : n) {
297  Simplex beta;
298  beta.add_vertex(y);
299  buffer.push_back(beta);
300  }
301 }
302 
311 template<typename SkeletonBlockerDS>
312 void
314  this->add_edge_without_blockers(a, x);
315  if (this->visitor) this->visitor->on_swaped_edge(a, b, x);
316  this->remove_edge(b, x);
317 }
318 
319 template<typename SkeletonBlockerDS>
320 void
322  std::list <Blocker_handle> blockers_to_delete;
323  for (auto blocker : this->blocker_range(v)) {
324  blockers_to_delete.push_back(blocker);
325  }
326  while (!blockers_to_delete.empty()) {
327  this->remove_blocker(blockers_to_delete.back());
328  blockers_to_delete.pop_back();
329  }
330 }
331 
335 template<typename SkeletonBlockerDS>
336 void
338  std::list<Blocker_handle> blocker_to_delete;
339  for (auto blocker : this->blocker_range(a))
340  if (blocker->contains(b)) blocker_to_delete.push_back(blocker);
341  while (!blocker_to_delete.empty()) {
342  this->delete_blocker(blocker_to_delete.back());
343  blocker_to_delete.pop_back();
344  }
345 }
346 
352 template<typename SkeletonBlockerDS>
353 void
355  assert(this->contains_vertex(a));
356  assert(this->contains_vertex(b));
357 
358  if (this->contains_edge(a, b))
359  this->add_edge_without_blockers(a, b);
360 
361  // if some blockers passes through 'ab', we need to remove them.
362  if (!link_condition(a, b))
363  delete_blockers_around_edge(a, b);
364 
365  std::set<Simplex> blockers_to_add;
366 
367  get_blockers_to_be_added_after_contraction(a, b, blockers_to_add);
368 
369  delete_blockers_around_vertices(a, b);
370 
371  update_edges_after_contraction(a, b);
372 
373  this->remove_vertex(b);
374 
375  notify_changed_edges(a);
376 
377  for (auto block : blockers_to_add)
378  this->add_blocker(block);
379 
380  assert(this->contains_vertex(a));
381  assert(!this->contains_vertex(b));
382 }
383 
384 template<typename SkeletonBlockerDS>
386  Vertex_handle b,
387  std::set<Simplex>& blockers_to_add) {
388  blockers_to_add.clear();
389 
391 
392  LinkComplexType link_a(*this, a);
393  LinkComplexType link_b(*this, b);
394 
395  std::vector<Simplex> vector_alpha, vector_beta;
396 
397  tip_blockers(a, b, vector_alpha);
398  tip_blockers(b, a, vector_beta);
399 
400  for (auto alpha = vector_alpha.begin(); alpha != vector_alpha.end(); ++alpha) {
401  for (auto beta = vector_beta.begin(); beta != vector_beta.end(); ++beta) {
402  Simplex sigma = *alpha;
403  sigma.union_vertices(*beta);
404  Root_simplex_handle sigma_id = this->get_id(sigma);
405  if (this->contains(sigma) &&
406  proper_faces_in_union<Skeleton_blocker_complex < SkeletonBlockerDS >> (sigma_id, link_a, link_b)) {
407  // Blocker_handle blocker = new Simplex(sigma);
408  sigma.add_vertex(a);
409  blockers_to_add.insert(sigma);
410  }
411  }
412  }
413 }
414 
418 template<typename SkeletonBlockerDS>
419 void
421  std::vector<Blocker_handle> blocker_to_delete;
422  for (auto bl : this->blocker_range(a))
423  blocker_to_delete.push_back(bl);
424  for (auto bl : this->blocker_range(b))
425  blocker_to_delete.push_back(bl);
426  while (!blocker_to_delete.empty()) {
427  this->delete_blocker(blocker_to_delete.back());
428  blocker_to_delete.pop_back();
429  }
430 }
431 
432 template<typename SkeletonBlockerDS>
433 void
435  // We update the set of edges
436  this->remove_edge(a, b);
437 
438  // For all edges {b,x} incident to b,
439  // we remove {b,x} and add {a,x} if not already there.
440  while (this->degree(b) > 0) {
441  Vertex_handle x(*(adjacent_vertices(b.vertex, this->skeleton).first));
442  if (!this->contains_edge(a, x))
443  // we 'replace' the edge 'bx' by the edge 'ax'
444  this->swap_edge(a, b, x);
445  else
446  this->remove_edge(b, x);
447  }
448 }
449 
450 template<typename SkeletonBlockerDS>
451 void
453  // We notify the visitor that all edges incident to 'a' had changed
454  boost_adjacency_iterator v, v_end;
455 
456  for (tie(v, v_end) = adjacent_vertices(a.vertex, this->skeleton); v != v_end; ++v)
457  if (this->visitor) this->visitor->on_changed_edge(a, Vertex_handle(*v));
458 }
459 
460 
461 } // namespace skeleton_blocker
462 
463 namespace skbl = skeleton_blocker;
464 
465 } // namespace Gudhi
466 
467 #endif // SKELETON_BLOCKER_SIMPLIFIABLE_COMPLEX_H_
T last_vertex() const
Definition: Skeleton_blocker_simplex.h:232
Abstract simplex used in Skeleton blockers data-structure.
Definition: Skeleton_blocker_simplex.h:50
void add_vertex(T v)
Definition: Skeleton_blocker_simplex.h:122
virtual void clear()
Definition: Skeleton_blocker_complex.h:323
int dimension() const
Definition: Skeleton_blocker_simplex.h:209
SkeletonBlockerGeometricDS ::Vertex_handle Vertex_handle
The type of an handle to a vertex of the complex.
Definition: Skeleton_blocker_complex.h:89
void difference(const Skeleton_blocker_simplex &a)
Definition: Skeleton_blocker_simplex.h:151
void remove_vertex(T v)
Definition: Skeleton_blocker_simplex.h:129
void contract_edge(Edge_handle edge)
Definition: Skeleton_blocker_complex.h:1258
void remove_star(Vertex_handle v)
Definition: Skeleton_blocker_simplifiable_complex.h:133
Definition: SimplicialComplexForAlpha.h:26
void remove_all_popable_blockers(Vertex_handle v)
Removes all the popable blockers of the complex passing through v and delete them. Also remove popable blockers in the neighborhood if they became popable.
Definition: Skeleton_blocker_simplifiable_complex.h:105
void add_simplex(const Simplex &sigma)
add a simplex and all its faces.
Definition: Skeleton_blocker_simplifiable_complex.h:209
void union_vertices(const Skeleton_blocker_simplex &a)
Definition: Skeleton_blocker_simplex.h:167
boost::graph_traits< Graph >::edge_descriptor Edge_handle
Handle to an edge of the complex.
Definition: Skeleton_blocker_complex.h:126
bool is_popable_blocker(Blocker_handle sigma) const
Definition: Skeleton_blocker_simplifiable_complex.h:45
virtual contractible_status is_contractible() const
Test if the complex is reducible using a strategy defined in the class (by default it tests if the co...
Definition: Skeleton_blocker_complex.h:1176
Abstract Simplicial Complex represented with a skeleton/blockers pair.
Definition: Skeleton_blocker_complex.h:63
void remove_popable_blockers()
Definition: Skeleton_blocker_simplifiable_complex.h:57
T first_vertex() const
Definition: Skeleton_blocker_simplex.h:222
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