Skeleton_blocker_simplifiable_complex.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(s): David Salinas
4  *
5  * Copyright (C) 2014 Inria
6  *
7  * Modification(s):
8  * - YYYY/MM Author: Description of the modification
9  */
10 
11 #ifndef SKELETON_BLOCKER_SIMPLIFIABLE_COMPLEX_H_
12 #define SKELETON_BLOCKER_SIMPLIFIABLE_COMPLEX_H_
13 
14 #include <gudhi/Skeleton_blocker/Skeleton_blocker_sub_complex.h>
15 
16 #include <list>
17 #include <vector>
18 #include <set>
19 
20 namespace Gudhi {
21 
22 namespace skeleton_blocker {
23 
32 template<typename SkeletonBlockerDS>
34  assert(this->contains_blocker(*sigma));
36  build_link_of_blocker(*this, *sigma, link_blocker_sigma);
37  return link_blocker_sigma.is_contractible() == CONTRACTIBLE;
38 }
39 
44 template<typename SkeletonBlockerDS>
46  std::list<Vertex_handle> vertex_to_check;
47  for (auto v : this->vertex_range())
48  vertex_to_check.push_front(v);
49 
50  while (!vertex_to_check.empty()) {
51  Vertex_handle v = vertex_to_check.front();
52  vertex_to_check.pop_front();
53 
54  bool blocker_popable_found = true;
55  while (blocker_popable_found) {
56  blocker_popable_found = false;
57  for (auto block : this->blocker_range(v)) {
58  if (this->is_popable_blocker(block)) {
59  for (Vertex_handle nv : *block)
60  if (nv != v) vertex_to_check.push_back(nv);
61  this->delete_blocker(block);
62  blocker_popable_found = true;
63  break;
64  }
65  }
66  }
67  }
68 }
69 
73 template<typename SkeletonBlockerDS>
75  bool blocker_popable_found = true;
76  while (blocker_popable_found) {
77  blocker_popable_found = false;
78  for (auto block : this->blocker_range(v)) {
79  if (is_popable_blocker(block)) {
80  this->delete_blocker(block);
81  blocker_popable_found = true;
82  }
83  }
84  }
85 }
86 
92 template<typename SkeletonBlockerDS>
94  std::list<Vertex_handle> vertex_to_check;
95  vertex_to_check.push_front(v);
96 
97  while (!vertex_to_check.empty()) {
98  Vertex_handle v = vertex_to_check.front();
99  vertex_to_check.pop_front();
100 
101  bool blocker_popable_found = true;
102  while (blocker_popable_found) {
103  blocker_popable_found = false;
104  for (auto block : this->blocker_range(v)) {
105  if (this->is_popable_blocker(block)) {
106  for (Vertex_handle nv : *block)
107  if (nv != v) vertex_to_check.push_back(nv);
108  this->delete_blocker(block);
109  blocker_popable_found = true;
110  break;
111  }
112  }
113  }
114  }
115 }
116 
120 template<typename SkeletonBlockerDS>
122  // we remove the blockers that are not consistent anymore
123  update_blockers_after_remove_star_of_vertex_or_edge(Simplex(v));
124  while (this->degree(v) > 0) {
125  Vertex_handle w(* (adjacent_vertices(v.vertex, this->skeleton).first));
126  this->remove_edge(v, w);
127  }
128  this->remove_vertex(v);
129 }
130 
136 template<typename SkeletonBlockerDS>
138  std::list <Blocker_handle> blockers_to_update;
139  if (simplex_to_be_removed.empty()) return;
140 
141  auto v0 = simplex_to_be_removed.first_vertex();
142  for (auto blocker : this->blocker_range(v0)) {
143  if (blocker->contains(simplex_to_be_removed))
144  blockers_to_update.push_back(blocker);
145  }
146 
147  for (auto blocker_to_update : blockers_to_update) {
148  Simplex sub_blocker_to_be_added;
149  bool sub_blocker_need_to_be_added =
150  (blocker_to_update->dimension() - simplex_to_be_removed.dimension()) >= 2;
151  if (sub_blocker_need_to_be_added) {
152  sub_blocker_to_be_added = *blocker_to_update;
153  sub_blocker_to_be_added.difference(simplex_to_be_removed);
154  }
155  this->delete_blocker(blocker_to_update);
156  if (sub_blocker_need_to_be_added)
157  this->add_blocker(sub_blocker_to_be_added);
158  }
159 }
160 
165 template<typename SkeletonBlockerDS>
167  update_blockers_after_remove_star_of_vertex_or_edge(Simplex(a, b));
168  // we remove the edge
169  this->remove_edge(a, b);
170 }
171 
175 template<typename SkeletonBlockerDS>
177  return remove_star(this->first_vertex(e), this->second_vertex(e));
178 }
179 
183 template<typename SkeletonBlockerDS>
185  assert(this->contains(sigma));
186  if (sigma.dimension() == 0) {
187  remove_star(sigma.first_vertex());
188  } else if (sigma.dimension() == 1) {
189  remove_star(sigma.first_vertex(), sigma.last_vertex());
190  } else {
191  remove_blocker_containing_simplex(sigma);
192  this->add_blocker(sigma);
193  }
194 }
195 
196 template<typename SkeletonBlockerDS>
198  // to add a simplex s, all blockers included in s are first removed
199  // and then all simplex in the coboundary of s are added as blockers
200  assert(!this->contains(sigma));
201  assert(sigma.dimension() > 1);
202  if (!contains_vertices(sigma)) {
203  std::cerr << "add_simplex: Some vertices were not present in the complex, adding them" << std::endl;
204  size_t num_vertices_to_add = sigma.last_vertex() - this->num_vertices() + 1;
205  for (size_t i = 0; i < num_vertices_to_add; ++i)
206  this->add_vertex();
207  }
208  assert(contains_vertices(sigma));
209  if (!contains_edges(sigma))
210  add_edge(sigma);
211  remove_blocker_include_in_simplex(sigma);
212  add_blockers_after_simplex_insertion(sigma);
213 }
214 
215 template<typename SkeletonBlockerDS>
217  if (sigma.dimension() < 1) return;
218 
219  for (auto s : coboundary_range(sigma)) {
220  this->add_blocker(s);
221  }
222 }
223 
227 template<typename SkeletonBlockerDS>
229  std::vector <Blocker_handle> blockers_to_remove;
230  for (auto blocker : this->blocker_range(sigma.first_vertex())) {
231  if (blocker->contains(sigma))
232  blockers_to_remove.push_back(blocker);
233  }
234  for (auto blocker_to_update : blockers_to_remove)
235  this->delete_blocker(blocker_to_update);
236 }
237 
241 template<typename SkeletonBlockerDS>
243  // TODO(DS): write efficiently by using only superior blockers
244  // eg for all s, check blockers whose vertices are all greater than s
245  std::set <Blocker_handle> blockers_to_remove;
246  for (auto s : sigma) {
247  for (auto blocker : this->blocker_range(s)) {
248  if (sigma.contains(*blocker))
249  blockers_to_remove.insert(blocker);
250  }
251  }
252  for (auto blocker_to_update : blockers_to_remove) {
253  auto s = *blocker_to_update;
254  this->delete_blocker(blocker_to_update);
255  // now if there is a vertex v in the link of s
256  // and v is not included in sigma then v.s is a blocker
257  // (all faces of v.s are there since v belongs to the link of s)
258  for (const auto& b : coboundary_range(s))
259  if (!sigma.contains(b))
260  this->add_blocker(b);
261  }
262 }
263 
269 template<typename SkeletonBlockerDS>
271  std::vector<Simplex> & buffer) const {
272  for (auto const & blocker : this->const_blocker_range(a)) {
273  Simplex beta = (*blocker);
274  beta.remove_vertex(a);
275  buffer.push_back(beta);
276  }
277 
278  Simplex n;
279  this->add_neighbours(b, n);
280  this->remove_neighbours(a, n);
281  n.remove_vertex(a);
282 
283 
284  for (Vertex_handle y : n) {
285  Simplex beta;
286  beta.add_vertex(y);
287  buffer.push_back(beta);
288  }
289 }
290 
299 template<typename SkeletonBlockerDS>
300 void
302  this->add_edge_without_blockers(a, x);
303  if (this->visitor) this->visitor->on_swaped_edge(a, b, x);
304  this->remove_edge(b, x);
305 }
306 
307 template<typename SkeletonBlockerDS>
308 void
310  std::list <Blocker_handle> blockers_to_delete;
311  for (auto blocker : this->blocker_range(v)) {
312  blockers_to_delete.push_back(blocker);
313  }
314  while (!blockers_to_delete.empty()) {
315  this->remove_blocker(blockers_to_delete.back());
316  blockers_to_delete.pop_back();
317  }
318 }
319 
323 template<typename SkeletonBlockerDS>
324 void
326  std::list<Blocker_handle> blocker_to_delete;
327  for (auto blocker : this->blocker_range(a))
328  if (blocker->contains(b)) blocker_to_delete.push_back(blocker);
329  while (!blocker_to_delete.empty()) {
330  this->delete_blocker(blocker_to_delete.back());
331  blocker_to_delete.pop_back();
332  }
333 }
334 
340 template<typename SkeletonBlockerDS>
341 void
343  assert(this->contains_vertex(a));
344  assert(this->contains_vertex(b));
345 
346  if (this->contains_edge(a, b))
347  this->add_edge_without_blockers(a, b);
348 
349  // if some blockers passes through 'ab', we need to remove them.
350  if (!link_condition(a, b))
351  delete_blockers_around_edge(a, b);
352 
353  std::set<Simplex> blockers_to_add;
354 
355  get_blockers_to_be_added_after_contraction(a, b, blockers_to_add);
356 
357  delete_blockers_around_vertices(a, b);
358 
359  update_edges_after_contraction(a, b);
360 
361  this->remove_vertex(b);
362 
363  notify_changed_edges(a);
364 
365  for (auto block : blockers_to_add)
366  this->add_blocker(block);
367 
368  assert(this->contains_vertex(a));
369  assert(!this->contains_vertex(b));
370 }
371 
372 template<typename SkeletonBlockerDS>
374  Vertex_handle b,
375  std::set<Simplex>& blockers_to_add) {
376  blockers_to_add.clear();
377 
379 
380  LinkComplexType link_a(*this, a);
381  LinkComplexType link_b(*this, b);
382 
383  std::vector<Simplex> vector_alpha, vector_beta;
384 
385  tip_blockers(a, b, vector_alpha);
386  tip_blockers(b, a, vector_beta);
387 
388  for (auto alpha = vector_alpha.begin(); alpha != vector_alpha.end(); ++alpha) {
389  for (auto beta = vector_beta.begin(); beta != vector_beta.end(); ++beta) {
390  Simplex sigma = *alpha;
391  sigma.union_vertices(*beta);
392  Root_simplex_handle sigma_id = this->get_id(sigma);
393  if (this->contains(sigma) &&
394  proper_faces_in_union<Skeleton_blocker_complex < SkeletonBlockerDS >> (sigma_id, link_a, link_b)) {
395  // Blocker_handle blocker = new Simplex(sigma);
396  sigma.add_vertex(a);
397  blockers_to_add.insert(sigma);
398  }
399  }
400  }
401 }
402 
406 template<typename SkeletonBlockerDS>
407 void
409  std::vector<Blocker_handle> blocker_to_delete;
410  for (auto bl : this->blocker_range(a))
411  blocker_to_delete.push_back(bl);
412  for (auto bl : this->blocker_range(b))
413  blocker_to_delete.push_back(bl);
414  while (!blocker_to_delete.empty()) {
415  this->delete_blocker(blocker_to_delete.back());
416  blocker_to_delete.pop_back();
417  }
418 }
419 
420 template<typename SkeletonBlockerDS>
421 void
423  // We update the set of edges
424  this->remove_edge(a, b);
425 
426  // For all edges {b,x} incident to b,
427  // we remove {b,x} and add {a,x} if not already there.
428  while (this->degree(b) > 0) {
429  Vertex_handle x(*(adjacent_vertices(b.vertex, this->skeleton).first));
430  if (!this->contains_edge(a, x))
431  // we 'replace' the edge 'bx' by the edge 'ax'
432  this->swap_edge(a, b, x);
433  else
434  this->remove_edge(b, x);
435  }
436 }
437 
438 template<typename SkeletonBlockerDS>
439 void
441  // We notify the visitor that all edges incident to 'a' had changed
442  boost_adjacency_iterator v, v_end;
443 
444  for (tie(v, v_end) = adjacent_vertices(a.vertex, this->skeleton); v != v_end; ++v)
445  if (this->visitor) this->visitor->on_changed_edge(a, Vertex_handle(*v));
446 }
447 
448 
449 } // namespace skeleton_blocker
450 
451 namespace skbl = skeleton_blocker;
452 
453 } // namespace Gudhi
454 
455 #endif // SKELETON_BLOCKER_SIMPLIFIABLE_COMPLEX_H_
T last_vertex() const
Definition: Skeleton_blocker_simplex.h:220
Abstract simplex used in Skeleton blockers data-structure.
Definition: Skeleton_blocker_simplex.h:38
void add_vertex(T v)
Definition: Skeleton_blocker_simplex.h:110
virtual void clear()
Definition: Skeleton_blocker_complex.h:311
int dimension() const
Definition: Skeleton_blocker_simplex.h:197
SkeletonBlockerGeometricDS ::Vertex_handle Vertex_handle
The type of an handle to a vertex of the complex.
Definition: Skeleton_blocker_complex.h:77
void difference(const Skeleton_blocker_simplex &a)
Definition: Skeleton_blocker_simplex.h:139
void remove_vertex(T v)
Definition: Skeleton_blocker_simplex.h:117
void contract_edge(Edge_handle edge)
Definition: Skeleton_blocker_complex.h:1246
void remove_star(Vertex_handle v)
Definition: Skeleton_blocker_simplifiable_complex.h:121
Definition: SimplicialComplexForAlpha.h:14
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:93
void add_simplex(const Simplex &sigma)
add a simplex and all its faces.
Definition: Skeleton_blocker_simplifiable_complex.h:197
void union_vertices(const Skeleton_blocker_simplex &a)
Definition: Skeleton_blocker_simplex.h:155
boost::graph_traits< Graph >::edge_descriptor Edge_handle
Handle to an edge of the complex.
Definition: Skeleton_blocker_complex.h:114
bool is_popable_blocker(Blocker_handle sigma) const
Definition: Skeleton_blocker_simplifiable_complex.h:33
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:1164
Abstract Simplicial Complex represented with a skeleton/blockers pair.
Definition: Skeleton_blocker_complex.h:51
void remove_popable_blockers()
Definition: Skeleton_blocker_simplifiable_complex.h:45
T first_vertex() const
Definition: Skeleton_blocker_simplex.h:210
GUDHI  Version 3.4.1  - C++ library for Topological Data Analysis (TDA) and Higher Dimensional Geometry Understanding.  - Copyright : MIT Generated on Fri Jan 22 2021 09:41:15 for GUDHI by Doxygen 1.8.13