Gudhi  1.1.0
 All Classes Functions Typedefs Friends Groups Pages
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 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_LINK_COMPLEX_H_
23 #define GUDHI_SKELETON_BLOCKERS_LINK_COMPLEX_H_
24 
25 #include "gudhi/Utils.h"
26 #include "gudhi/Skeleton_blocker_complex.h"
27 
28 namespace Gudhi{
29 
30 namespace skbl {
31 
32 template<class ComplexType> class Skeleton_blocker_sub_complex;
33 
34 
41 template<typename ComplexType>
43 {
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 
50 private:
51 
52  bool only_superior_vertices_;
53 
54 public:
55  typedef typename ComplexType::Vertex_handle Vertex_handle;
56  typedef typename ComplexType::Root_vertex_handle Root_vertex_handle;
57 
58  typedef typename ComplexType::Simplex_handle Simplex_handle;
59  typedef typename ComplexType::Root_simplex_handle Root_simplex_handle;
60 
61  typedef typename ComplexType::Blocker_handle Blocker_handle;
62 
63 
64  typedef typename ComplexType::Simplex_handle::Simplex_vertex_const_iterator Simplex_handle_iterator;
65  typedef typename ComplexType::Root_simplex_handle::Simplex_vertex_const_iterator Root_simplex_handle_iterator;
66 
67 
68  Skeleton_blocker_link_complex(bool only_superior_vertices=false):only_superior_vertices_(only_superior_vertices){
69  }
70 
75  Skeleton_blocker_link_complex(const ComplexType & parent_complex,const Simplex_handle& alpha_parent_adress,bool only_superior_vertices = false)
76  :only_superior_vertices_(only_superior_vertices) {
77  if(!alpha_parent_adress.empty())
78  build_link(parent_complex,alpha_parent_adress);
79 
80  }
81 
86  Skeleton_blocker_link_complex(const ComplexType & parent_complex, Vertex_handle a_parent_adress, bool only_superior_vertices = false)
87  :only_superior_vertices_(only_superior_vertices){
88  Simplex_handle alpha_simplex(a_parent_adress);
89  build_link(parent_complex,alpha_simplex);
90  }
91 
92 
97  Skeleton_blocker_link_complex(const ComplexType & parent_complex, Edge_handle edge, bool only_superior_vertices = false)
98  :only_superior_vertices_(only_superior_vertices){
99  Simplex_handle alpha_simplex(parent_complex.first_vertex(edge),parent_complex.second_vertex(edge));
100  build_link(parent_complex,alpha_simplex);
101  }
102 
103 protected:
104 
105 
111  void compute_link_vertices(const ComplexType & parent_complex,const Simplex_handle& alpha_parent_adress,bool only_superior_vertices,bool is_alpha_blocker = false){
112  if(alpha_parent_adress.dimension()==0)
113  // for a vertex we know exactly the number of vertices of the link (and the size of the corresponding vector)
114  // thus we call a specific function that will reserve a vector with appropriate size
115  this->compute_link_vertices(parent_complex,alpha_parent_adress.first_vertex(),only_superior_vertices_);
116  else{
117  // we compute the intersection of neighbors of alpha and store it in link_vertices
118  Simplex_handle link_vertices_parent;
119  parent_complex.add_neighbours(alpha_parent_adress,link_vertices_parent,only_superior_vertices);
120  // For all vertex 'v' in this intersection, we go through all its adjacent blockers.
121  // If one blocker minus 'v' is included in alpha then the vertex is not in the link complex.
122  for (auto v_parent : link_vertices_parent){
123  bool new_vertex = true;
124  for (auto beta : parent_complex.const_blocker_range(v_parent))
125  {
126  if(!is_alpha_blocker || *beta!=alpha_parent_adress){
127  new_vertex = !(alpha_parent_adress.contains_difference(*beta,v_parent));
128  if(!new_vertex) break;
129  }
130  }
131  if (new_vertex)
132  this->add_vertex(parent_complex.get_id(v_parent));
133  }
134  }
135  }
136 
137 
143  void compute_link_vertices(const ComplexType & parent_complex, Vertex_handle alpha_parent_adress,bool only_superior_vertices){
144  // for a vertex we know exactly the number of vertices of the link (and the size of the corresponding vector
145  this->skeleton.m_vertices.reserve(parent_complex.degree(alpha_parent_adress));
146 
147  // For all vertex 'v' in this intersection, we go through all its adjacent blockers.
148  // If one blocker minus 'v' is included in alpha then the vertex is not in the link complex.
149  for (auto v_parent : parent_complex.vertex_range(alpha_parent_adress)){
150  if(!only_superior_vertices || v_parent.vertex> alpha_parent_adress.vertex)
151  this->add_vertex(parent_complex.get_id(v_parent));
152  }
153 
154  }
155 
156 
157  void compute_link_edges(const ComplexType & parent_complex,const Simplex_handle& alpha_parent_adress,bool is_alpha_blocker = false){
158  Simplex_handle_iterator y_link, x_parent , y_parent;
159  // ----------------------------
160  // Compute edges in the link
161  // -------------------------
162 
163  if(this->num_vertices()<=1) return;
164 
165  for (auto x_link = this->vertex_range().begin() ;
166  x_link!= this->vertex_range().end();
167  ++x_link
168  )
169  {
170  for (auto y_link = x_link; ++y_link != this->vertex_range().end(); ){
171  Vertex_handle x_parent = *parent_complex.get_address(this->get_id(*x_link));
172  Vertex_handle y_parent = *parent_complex.get_address(this->get_id(*y_link));
173  if (parent_complex.contains_edge(x_parent,y_parent) ){
174  // we check that there is no blocker subset of alpha passing trough x and y
175  bool new_edge=true;
176  for (auto blocker_parent : parent_complex.const_blocker_range(x_parent))
177  {
178  if(!is_alpha_blocker || *blocker_parent!=alpha_parent_adress){
179  if (blocker_parent->contains(y_parent))
180  {
181  new_edge = !(alpha_parent_adress.contains_difference(*blocker_parent,x_parent,y_parent));
182  if (!new_edge) break;
183  }
184  }
185  }
186  if (new_edge)
187  this->add_edge(*x_link,*y_link);
188  }
189  }
190  }
191  }
192 
193 
199  boost::optional<Vertex_handle> give_equivalent_vertex(const ComplexType & other_complex,
200  Vertex_handle address) const{
201  Root_vertex_handle id((*this)[address].get_id());
202  return other_complex.get_address(id);
203  }
204 
205  /*
206  * compute the blockers of the link if is_alpha_blocker is false.
207  * Otherwise, alpha is a blocker, and the link is computed in the complex where
208  * the blocker is anticollapsed.
209  */
210  void compute_link_blockers(const ComplexType & parent_complex,const Simplex_handle& alpha_parent,bool is_alpha_blocker = false){
211 
212  for (auto x_link : this->vertex_range()){
213 
214  Vertex_handle x_parent = * this->give_equivalent_vertex(parent_complex,x_link);
215 
216  for (auto blocker_parent : parent_complex.const_blocker_range(x_parent)){
217  if(!is_alpha_blocker || *blocker_parent!=alpha_parent){
218  Simplex_handle sigma_parent(*blocker_parent);
219 
220  sigma_parent.difference(alpha_parent);
221 
222  if (sigma_parent.dimension()>=2 && sigma_parent.first_vertex() == x_parent){
223  Root_simplex_handle sigma_id(parent_complex.get_id(sigma_parent));
224  auto sigma_link = this->get_simplex_address(sigma_id);
225  // ie if the vertices of sigma are vertices of the link
226  if(sigma_link){
227  bool is_new_blocker = true;
228  for(auto a : alpha_parent){
229  for(auto eta_parent : parent_complex.const_blocker_range(a)){
230  if(!is_alpha_blocker || *eta_parent!=alpha_parent){
231  Simplex_handle eta_minus_alpha(*eta_parent);
232  eta_minus_alpha.difference(alpha_parent);
233  if(eta_minus_alpha != sigma_parent &&
234  sigma_parent.contains_difference(*eta_parent,alpha_parent)){
235  is_new_blocker = false;
236  break;
237  }
238  }
239  }
240  if (!is_new_blocker) break;
241  }
242  if (is_new_blocker)
243  this->add_blocker(new Simplex_handle(*sigma_link));
244 
245  }
246  }
247  }
248  }
249  }
250  }
251 
252 
253 public:
259  void build_link(const ComplexType & parent_complex,const Simplex_handle& alpha_parent_adress,bool is_alpha_blocker = false)
260  {
261  assert(is_alpha_blocker || parent_complex.contains(alpha_parent_adress));
262  compute_link_vertices(parent_complex,alpha_parent_adress,only_superior_vertices_);
263  compute_link_edges(parent_complex,alpha_parent_adress,is_alpha_blocker);
264  compute_link_blockers(parent_complex,alpha_parent_adress,is_alpha_blocker);
265  }
266 
267 
274  const ComplexType & parent_complex,
275  Simplex_handle& blocker,
277  assert(blocker.dimension()>=2);
278  assert(parent_complex.contains_blocker(blocker));
279  result.clear();
280  result.build_link(parent_complex,blocker,true);
281  }
282 
283 
284 };
285 
286 }
287 
288 } // namespace GUDHI
289 
290 #endif /* SKELETON_BLOCKERS_LINK_COMPLEX_H_ */
void clear()
Definition: Skeleton_blocker_sub_complex.h:194
void add_edge(Root_vertex_handle v1_root, Root_vertex_handle v2_root)
Definition: Skeleton_blocker_sub_complex.h:135
void add_blocker(const Root_simplex_handle &blocker_root)
Definition: Skeleton_blocker_sub_complex.h:147
Simplicial subcomplex of a complex represented by a skeleton/blockers pair.
Definition: Skeleton_blocker_link_superior.h:31
boost::optional< Simplex_handle > get_simplex_address(const Root_simplex_handle &s) const
Compute the local vertices of 's' in the current complex If one of them is not present in the complex...
Definition: Skeleton_blocker_complex.h:957
Complex_vertex_range vertex_range() const
Returns a Complex_vertex_range over all vertices of the complex.
Definition: Skeleton_blocker_complex.h:1089
Root_vertex_handle get_id(Vertex_handle local) const
Definition: Skeleton_blocker_complex.h:511
Vertex_handle add_vertex()
Adds a vertex to the simplicial complex and returns its Vertex_handle.
Definition: Skeleton_blocker_complex.h:443
Abstract simplex used in Skeleton blockers data-structure.
Definition: Skeleton_blocker_simplex.h:48
Root_vertex_handle and Vertex_handle are similar to global and local vertex descriptor used in boost ...
Definition: SkeletonBlockerDS.h:50