Gudhi  1.1.0
 All Classes Functions Typedefs Friends Groups Pages
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 Sophia Antipolis-Mediterranee (France)
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 #ifndef GUDHI_SKELETON_BLOCKERS_SIMPLIFIABLE_COMPLEX_H_
23 #define GUDHI_SKELETON_BLOCKERS_SIMPLIFIABLE_COMPLEX_H_
24 
25 #include "gudhi/Skeleton_blocker/Skeleton_blocker_sub_complex.h"
26 
27 namespace Gudhi{
28 
29 namespace skbl {
30 
37 template<typename SkeletonBlockerDS>
39 {
40  template<class ComplexType> friend class Skeleton_blocker_sub_complex;
41 
42 public:
43 
45 
47 
48  typedef typename SkeletonBlockerComplex::boost_adjacency_iterator boost_adjacency_iterator;
50  typedef typename SkeletonBlockerComplex::boost_vertex_handle boost_vertex_handle;
56 
57 
58  typedef typename SkeletonBlockerComplex::Root_simplex_iterator Root_simplex_iterator;
59  typedef typename SkeletonBlockerComplex::Simplex_handle_iterator Simplex_handle_iterator;
60  typedef typename SkeletonBlockerComplex::BlockerMap BlockerMap;
61  typedef typename SkeletonBlockerComplex::BlockerPair BlockerPair;
62  typedef typename SkeletonBlockerComplex::BlockerMapIterator BlockerMapIterator;
63  typedef typename SkeletonBlockerComplex::BlockerMapConstIterator BlockerMapConstIterator;
64 
66 
67 
71  Skeleton_blocker_simplifiable_complex(int num_vertices_ = 0,Visitor* visitor_=NULL):
72  Skeleton_blocker_complex<SkeletonBlockerDS>(num_vertices_,visitor_){ }
73 
74 
81  Skeleton_blocker_simplifiable_complex(std::list<Simplex_handle>& simplices,Visitor* visitor_=NULL):
82  Skeleton_blocker_complex<SkeletonBlockerDS>(simplices,visitor_)
83  {}
84 
85 
86 
88  }
89 
91 
100  virtual bool is_popable_blocker(Blocker_handle sigma) const{
101  assert(this->contains_blocker(*sigma));
103  build_link_of_blocker(*this,*sigma,link_blocker_sigma);
104 
105  bool res = link_blocker_sigma.is_contractible()==CONTRACTIBLE;
106  return res;
107  }
108 
109 
110 
111 
112 private:
118  std::list<Blocker_handle> get_blockers(){
119  std::list<Blocker_handle> res;
120  for (auto blocker : this->blocker_range()){
121  res.push_back(blocker);
122  }
123  return res;
124  }
125 
126 
127 
128 public:
129 
135  std::list<Vertex_handle> vertex_to_check;
136  for(auto v : this->vertex_range())
137  vertex_to_check.push_front(v);
138 
139  while(!vertex_to_check.empty()){
140  Vertex_handle v = vertex_to_check.front();
141  vertex_to_check.pop_front();
142 
143  bool blocker_popable_found=true;
144  while (blocker_popable_found){
145  blocker_popable_found = false;
146  for(auto block : this->blocker_range(v)){
147  if (this->is_popable_blocker(block)) {
148  for(Vertex_handle nv : *block)
149  if(nv!=v) vertex_to_check.push_back(nv);
150  this->delete_blocker(block);
151  blocker_popable_found = true;
152  break;
153  }
154  }
155  }
156  }
157  }
158 
159 
164  bool blocker_popable_found=true;
165  while (blocker_popable_found){
166  blocker_popable_found = false;
167  for(auto block : this->blocker_range(v)){
168  if (is_popable_blocker(block)) {
169  this->delete_blocker(block);
170  blocker_popable_found = true;
171  }
172  }
173  }
174  }
175 
176 
181  // we remove the blockers that are not consistent anymore
182 
183  update_blockers_after_remove_star_of_vertex_or_edge(v);
184 
185  while (this->degree(v) > 0)
186  {
187  Vertex_handle w( * (adjacent_vertices(v.vertex, this->skeleton).first));
188  this->remove_edge(v,w);
189  }
190  this->remove_vertex(v);
191  }
192 
193 private:
199  void update_blockers_after_remove_star_of_vertex_or_edge(const Simplex_handle& simplex_to_be_removed){
200  std::list <Blocker_handle> blockers_to_update;
201  if(simplex_to_be_removed.empty()) return;
202 
203  auto v0 = simplex_to_be_removed.first_vertex();
204  for (auto blocker : this->blocker_range(v0)){
205  if(blocker->contains(simplex_to_be_removed))
206  blockers_to_update.push_back(blocker);
207  }
208 
209  for(auto blocker_to_update : blockers_to_update){
210  Simplex_handle sub_blocker_to_be_added;
211  bool sub_blocker_need_to_be_added =
212  (blocker_to_update->dimension()-simplex_to_be_removed.dimension()) >= 2;
213  if(sub_blocker_need_to_be_added){
214  sub_blocker_to_be_added = *blocker_to_update;
215  sub_blocker_to_be_added.difference(simplex_to_be_removed);
216  }
217  this->delete_blocker(blocker_to_update);
218  if(sub_blocker_need_to_be_added)
219  this->add_blocker(sub_blocker_to_be_added);
220  }
221  }
222 
223 
224 
225 public:
231  update_blockers_after_remove_star_of_vertex_or_edge(Simplex_handle(a,b));
232  // we remove the edge
233  this->remove_edge(a,b);
234  }
235 
236 
241  return remove_star(this->first_vertex(e),this->second_vertex(e));
242  }
243 
247  void remove_star(const Simplex_handle& sigma){
248  assert(this->contains(sigma));
249  if (sigma.dimension()==0)
250  remove_star(sigma.first_vertex());
251  else
252  if (sigma.dimension()==1)
253  remove_star(sigma.first_vertex(),sigma.last_vertex());
254  else{
255  remove_blocker_containing_simplex(sigma);
256  this->add_blocker(sigma);
257  }
258  }
259 
264  void add_simplex(const Simplex_handle& sigma){
265  assert(!this->contains(sigma));
266  assert(sigma.dimension()>1);
267  remove_blocker_include_in_simplex(sigma);
268  }
269 
270 private:
274  void remove_blocker_containing_simplex(const Simplex_handle& sigma){
275  std::vector <Blocker_handle> blockers_to_remove;
276  for (auto blocker : this->blocker_range(sigma.first_vertex())){
277  if(blocker->contains(sigma))
278  blockers_to_remove.push_back(blocker);
279  }
280  for(auto blocker_to_update : blockers_to_remove)
281  this->delete_blocker(blocker_to_update);
282  }
283 
287  void remove_blocker_include_in_simplex(const Simplex_handle& sigma){
288  std::vector <Blocker_handle> blockers_to_remove;
289  for (auto blocker : this->blocker_range(sigma.first_vertex())){
290  if(sigma.contains(*blocker))
291  blockers_to_remove.push_back(blocker);
292  }
293  for(auto blocker_to_update : blockers_to_remove)
294  this->delete_blocker(blocker_to_update);
295  }
296 
297 
298 public:
299 
300  enum simplifiable_status{ NOT_HOMOTOPY_EQ,MAYBE_HOMOTOPY_EQ,HOMOTOPY_EQ};
301  simplifiable_status is_remove_star_homotopy_preserving(const Simplex_handle& simplex){
302  return MAYBE_HOMOTOPY_EQ;
303  }
304 
305 
306 
307  enum contractible_status{ NOT_CONTRACTIBLE,MAYBE_CONTRACTIBLE,CONTRACTIBLE};
317  virtual contractible_status is_contractible() const{
318  if (this->is_cone()) return CONTRACTIBLE;
319  else return MAYBE_CONTRACTIBLE;
320  // return this->is_cone();
321  }
322 
323 
327 
328 
329 
337  bool link_condition(Vertex_handle a, Vertex_handle b,bool ignore_popable_blockers = false) const{
338  for (auto blocker : this->const_blocker_range(a))
339  if ( blocker->contains(b) ){
340  // false if ignore_popable_blockers is false
341  // otherwise the blocker has to be popable
342  return ignore_popable_blockers && is_popable_blocker(blocker);
343  }
344  return true;
345  }
346 
354  bool link_condition(Edge_handle & e,bool ignore_popable_blockers = false) const{
355  const Graph_edge& edge = (*this)[e];
356  assert(this->get_address(edge.first()));
357  assert(this->get_address(edge.second()));
358  Vertex_handle a(*this->get_address(edge.first()));
359  Vertex_handle b(*this->get_address(edge.second()));
360  return link_condition(a,b,ignore_popable_blockers);
361  }
362 
363 
364 protected:
371  void tip_blockers(Vertex_handle a, Vertex_handle b, std::vector<Simplex_handle> & buffer) const{
372  for (auto const & blocker : this->const_blocker_range(a))
373  {
374  Simplex_handle beta = (*blocker);
375  beta.remove_vertex(a);
376  buffer.push_back(beta);
377  }
378 
379  Simplex_handle n;
380  this->add_neighbours(b,n);
381  this->remove_neighbours(a,n);
382  n.remove_vertex(a);
383 
384 
385  for (Vertex_handle y : n)
386  {
387  Simplex_handle beta;
388  beta.add_vertex( y );
389  buffer.push_back(beta);
390  }
391  }
392 
393 
394 private:
395 
404  void swap_edge(Vertex_handle a,Vertex_handle b,Vertex_handle x){
405  this->add_edge(a,x);
406  if (this->visitor) this->visitor->on_swaped_edge(a,b,x);
407  this->remove_edge(b,x);
408  }
409 
410 
411 private:
415  void delete_blockers_around_vertex(Vertex_handle v){
416  std::list <Blocker_handle> blockers_to_delete;
417  for (auto blocker : this->blocker_range(v)){
418  blockers_to_delete.push_back(blocker);
419  }
420  while (!blockers_to_delete.empty()){
421  this->remove_blocker(blockers_to_delete.back());
422  blockers_to_delete.pop_back();
423  }
424 
425  }
429  void delete_blockers_around_edge(Vertex_handle a, Vertex_handle b){
430  std::list<Blocker_handle> blocker_to_delete;
431  for (auto blocker : this->blocker_range(a))
432  if (blocker->contains(b)) blocker_to_delete.push_back(blocker);
433  while (!blocker_to_delete.empty())
434  {
435  this->delete_blocker(blocker_to_delete.back());
436  blocker_to_delete.pop_back();
437  }
438  }
439 
440 public:
441 
448  contract_edge(this->first_vertex(edge),this->second_vertex(edge));
449  }
450 
451 
458  assert(this->contains_vertex(a));
459  assert(this->contains_vertex(b));
460  assert(this->contains_edge(a,b));
461 
462  // if some blockers passes through 'ab', we remove them.
463  if (!link_condition(a,b))
464  delete_blockers_around_edge(a,b);
465 
466  std::set<Simplex_handle> blockers_to_add;
467 
468  get_blockers_to_be_added_after_contraction(a,b,blockers_to_add);
469 
470  delete_blockers_around_vertices(a,b);
471 
472  update_edges_after_contraction(a,b);
473 
474  this->remove_vertex(b);
475 
476  notify_changed_edges(a);
477 
478  for(auto block : blockers_to_add)
479  this->add_blocker(block);
480 
481  assert(this->contains_vertex(a));
482  assert(!this->contains_vertex(b));
483  }
484 
485 
486 private:
487 
488  void get_blockers_to_be_added_after_contraction(Vertex_handle a,Vertex_handle b,std::set<Simplex_handle>& blockers_to_add){
489  blockers_to_add.clear();
490 
492 
493  LinkComplexType link_a(*this,a);
494  LinkComplexType link_b(*this,b);
495 
496  std::vector<Simplex_handle> vector_alpha, vector_beta;
497 
498  tip_blockers(a,b,vector_alpha);
499  tip_blockers(b,a,vector_beta);
500 
501  for (auto alpha = vector_alpha.begin(); alpha != vector_alpha.end(); ++alpha){
502  for (auto beta = vector_beta.begin(); beta != vector_beta.end(); ++beta)
503  {
504  Simplex_handle sigma = *alpha; sigma.union_vertices(*beta);
505  Root_simplex_handle sigma_id = this->get_id(sigma);
506  if ( this->contains(sigma) &&
507  proper_faces_in_union<SkeletonBlockerComplex>(sigma_id,link_a,link_b))
508  {
509  // Blocker_handle blocker = new Simplex_handle(sigma);
510  sigma.add_vertex(a);
511  blockers_to_add.insert(sigma);
512  }
513  }
514  }
515  }
516 
517 
521  void delete_blockers_around_vertices(Vertex_handle a,Vertex_handle b){
522  std::vector<Blocker_handle> blocker_to_delete;
523  for(auto bl : this->blocker_range(a))
524  blocker_to_delete.push_back(bl);
525  for(auto bl : this->blocker_range(b))
526  blocker_to_delete.push_back(bl);
527  while (!blocker_to_delete.empty())
528  {
529  this->delete_blocker(blocker_to_delete.back());
530  blocker_to_delete.pop_back();
531  }
532  }
533 
534 
535  void update_edges_after_contraction(Vertex_handle a,Vertex_handle b){
536  // We update the set of edges
537  this->remove_edge(a,b);
538 
539  // For all edges {b,x} incident to b,
540  // we remove {b,x} and add {a,x} if not already there.
541  while (this->degree(b)> 0)
542  {
543  Vertex_handle x(*(adjacent_vertices(b.vertex, this->skeleton).first));
544  if(!this->contains_edge(a,x))
545  // we 'replace' the edge 'bx' by the edge 'ax'
546  this->swap_edge(a,b,x);
547  else
548  this->remove_edge(b,x);
549  }
550  }
551 
552  void notify_changed_edges(Vertex_handle a){
553  // We notify the visitor that all edges incident to 'a' had changed
554  boost_adjacency_iterator v, v_end;
555 
556  for (tie(v, v_end) = adjacent_vertices(a.vertex, this->skeleton); v != v_end; ++v)
557  if (this->visitor) this->visitor->on_changed_edge(a,Vertex_handle(*v));
558  }
559 
561 
562 
563 };
564 
565 }
566 
567 } // namespace GUDHI
568 
569 #endif /* GUDHI_SKELETON_BLOCKERS_SIMPLIFIABLE_COMPLEX_H_ */
Const_complex_blocker_range const_blocker_range() const
Returns a range of the blockers of the complex.
Definition: Skeleton_blocker_complex.h:1332
void remove_blocker(const Blocker_handle sigma)
Removes the simplex from the set of blockers.
Definition: Skeleton_blocker_complex.h:789
bool contains_blocker(const Blocker_handle s) const
Definition: Skeleton_blocker_complex.h:844
virtual bool is_popable_blocker(Blocker_handle sigma) const
Definition: Skeleton_blocker_simplifiable_complex.h:100
Blocker_handle add_blocker(const Simplex_handle &blocker)
Adds the simplex to the set of blockers and returns a Blocker_handle toward it if was not present bef...
Definition: Skeleton_blocker_complex.h:719
Class that allows simplification operation on a simplicial complex represented by a skeleton/blockers...
Definition: Skeleton_blocker_simplifiable_complex.h:38
Complex_blocker_range blocker_range()
Returns a range of the blockers of the complex.
Definition: Skeleton_blocker_complex.h:1322
bool link_condition(Vertex_handle a, Vertex_handle b, bool ignore_popable_blockers=false) const
Definition: Skeleton_blocker_simplifiable_complex.h:337
Vertex_handle second_vertex(Edge_handle edge_handle) const
returns the first vertex of an edge
Definition: Skeleton_blocker_complex.h:589
void remove_star(Edge_handle e)
Definition: Skeleton_blocker_simplifiable_complex.h:240
void remove_star(const Simplex_handle &sigma)
Definition: Skeleton_blocker_simplifiable_complex.h:247
void delete_blocker(Blocker_handle sigma)
Definition: Skeleton_blocker_complex.h:834
boost::graph_traits< Graph >::edge_descriptor Edge_handle
Handle to an edge of the complex.
Definition: Skeleton_blocker_complex.h:139
void contract_edge(Edge_handle edge)
Definition: Skeleton_blocker_simplifiable_complex.h:447
void remove_star(Vertex_handle a, Vertex_handle b)
Definition: Skeleton_blocker_simplifiable_complex.h:230
Skeleton_blocker_simplifiable_complex(std::list< Simplex_handle > &simplices, Visitor *visitor_=NULL)
Constructor with a list of simplices.
Definition: Skeleton_blocker_simplifiable_complex.h:81
Vertex_handle first_vertex(Edge_handle edge_handle) const
returns the first vertex of an edge
Definition: Skeleton_blocker_complex.h:581
The type of edges that are stored the boost graph. An Edge must be Default Constructible and Equality...
Definition: SkeletonBlockerDS.h:97
void remove_star(Vertex_handle v)
Definition: Skeleton_blocker_simplifiable_complex.h:180
virtual boost::optional< Vertex_handle > get_address(Root_vertex_handle id) const
Given an Id return the address of the vertex having this Id in the complex.
Definition: Skeleton_blocker_complex.h:500
Root_vertex_handle first() const
Returns the first vertex of the edge.
int degree(Vertex_handle local) const
return the graph degree of a vertex.
Definition: Skeleton_blocker_complex.h:537
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_simplifiable_complex.h:317
Abstract Simplicial Complex represented with a skeleton/blockers pair.
Definition: Skeleton_blocker_complex.h:63
T last_vertex() const
Definition: Skeleton_blocker_simplex.h:245
T first_vertex() const
Definition: Skeleton_blocker_simplex.h:235
void remove_popable_blockers(Vertex_handle v)
Definition: Skeleton_blocker_simplifiable_complex.h:163
bool link_condition(Edge_handle &e, bool ignore_popable_blockers=false) const
Definition: Skeleton_blocker_simplifiable_complex.h:354
Edge_handle add_edge(Vertex_handle a, Vertex_handle b)
Adds an edge between vertices a and b and all its cofaces.
Definition: Skeleton_blocker_complex.h:606
Simplicial subcomplex of a complex represented by a skeleton/blockers pair.
Definition: Skeleton_blocker_link_superior.h:31
Concept for the template class passed for Skeleton_blocker_complex. Most importantly, it contains the nodes for vertices and edges (Graph_vertex and Graph_edge) that are stored in the simplicial complex. The user can redefine these classes to attach additional information to vertices and edges.
Definition: SkeletonBlockerDS.h:25
Complex_vertex_range vertex_range() const
Returns a Complex_vertex_range over all vertices of the complex.
Definition: Skeleton_blocker_complex.h:1089
void add_simplex(const Simplex_handle &sigma)
add a maximal simplex plus all its cofaces.
Definition: Skeleton_blocker_simplifiable_complex.h:264
Root_vertex_handle get_id(Vertex_handle local) const
Definition: Skeleton_blocker_complex.h:511
void remove_vertex(Vertex_handle address)
Remove a vertex from the simplicial complex.
Definition: Skeleton_blocker_complex.h:461
virtual Edge_handle remove_edge(Vertex_handle a, Vertex_handle b)
Removes an edge from the simplicial complex and all its cofaces.
Definition: Skeleton_blocker_complex.h:639
bool contains_edge(Vertex_handle a, Vertex_handle b) const
Definition: Skeleton_blocker_complex.h:686
Abstract simplex used in Skeleton blockers data-structure.
Definition: Skeleton_blocker_simplex.h:48
Root_vertex_handle second() const
Returns the second vertex of the edge.
bool is_cone() const
Test if the complex is a cone.
Definition: Skeleton_blocker_complex.h:1055
Interface for a visitor of a simplicial complex.
Definition: Skeleton_blocker_complex_visitor.h:38
int dimension() const
Definition: Skeleton_blocker_simplex.h:222
Definition: SkeletonBlockerDS.h:60
void contract_edge(Vertex_handle a, Vertex_handle b)
Definition: Skeleton_blocker_simplifiable_complex.h:457
void remove_popable_blockers()
Definition: Skeleton_blocker_simplifiable_complex.h:134
Root_vertex_handle and Vertex_handle are similar to global and local vertex descriptor used in boost ...
Definition: SkeletonBlockerDS.h:50
virtual bool contains(const Simplex_handle &s) const
returns true iff the simplex s belongs to the simplicial complex.
Definition: Skeleton_blocker_complex.h:994