Skeleton_blocker_sub_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_SKELETON_BLOCKER_SUB_COMPLEX_H_
24 #define SKELETON_BLOCKER_SKELETON_BLOCKER_SUB_COMPLEX_H_
25 
26 #include <gudhi/Skeleton_blocker_complex.h>
27 #include <gudhi/Skeleton_blocker/Skeleton_blocker_simplex.h>
28 #include <gudhi/Debug_utils.h>
29 
30 #include <map>
31 #include <vector>
32 
33 namespace Gudhi {
34 
35 namespace skeleton_blocker {
36 
57 template<typename ComplexType>
58 class Skeleton_blocker_sub_complex : public ComplexType {
59  protected:
60  template<class T> friend class Skeleton_blocker_link_complex;
61 
62  typedef typename ComplexType::Graph Graph;
63  typedef typename ComplexType::Edge_handle Edge_handle;
64 
65  typedef typename ComplexType::boost_vertex_handle boost_vertex_handle;
66 
67  public:
68  using ComplexType::add_vertex;
69  using ComplexType::add_edge_without_blockers;
70  using ComplexType::add_blocker;
71 
72  typedef typename ComplexType::Vertex_handle Vertex_handle;
73  typedef typename ComplexType::Root_vertex_handle Root_vertex_handle;
74  typedef typename ComplexType::Simplex Simplex;
75  typedef typename ComplexType::Root_simplex_handle Root_simplex_handle;
76 
77  protected:
82  typedef std::map<Root_vertex_handle, Vertex_handle> IdAddressMap;
83  typedef typename IdAddressMap::value_type AddressPair;
84  typedef typename IdAddressMap::iterator IdAddressMapIterator;
85  typedef typename IdAddressMap::const_iterator IdAddressMapConstIterator;
86  std::map<Root_vertex_handle, Vertex_handle> adresses;
87 
88  public:
96  Vertex_handle add_vertex(Root_vertex_handle global) {
97  assert(!this->contains_vertex(global));
98  Vertex_handle address(boost::add_vertex(this->skeleton));
99  this->num_vertices_++;
100  (*this)[address].activate();
101  (*this)[address].set_id(global);
102  adresses.insert(AddressPair(global, address));
103  this->degree_.push_back(0);
104  return address;
105  }
106 
112  void add_edge_without_blockers(Root_vertex_handle v1_root, Root_vertex_handle v2_root) {
113  auto v1_sub(this->get_address(v1_root));
114  auto v2_sub(this->get_address(v2_root));
115  assert(v1_sub && v2_sub);
116  this->ComplexType::add_edge_without_blockers(*v1_sub, *v2_sub);
117  }
118 
124  void add_blocker(const Root_simplex_handle& blocker_root) {
125  auto blocker_sub = this->get_address(blocker_root);
126  assert(blocker_sub);
127  this->add_blocker(new Simplex(*blocker_sub));
128  }
129 
130  public:
135  void make_restricted_complex(const ComplexType & parent_complex,
136  const Simplex& simplex) {
137  this->clear();
138  // add vertices to the sub complex
139  for (auto x : simplex) {
140  assert(parent_complex.contains_vertex(x));
141  auto x_local = this->add_vertex(parent_complex[x].get_id());
142  (*this)[x_local] = parent_complex[x];
143  }
144 
145  // add edges to the sub complex
146  for (auto x : simplex) {
147  // x_neigh is the neighbor of x intersected with vertices_simplex
148  Simplex x_neigh;
149  parent_complex.add_neighbours(x, x_neigh, true);
150  x_neigh.intersection(simplex);
151  for (auto y : x_neigh) {
152  this->add_edge_without_blockers(parent_complex[x].get_id(), parent_complex[y].get_id());
153  }
154  }
155 
156  // add blockers to the sub complex
157  for (auto blocker : parent_complex.const_blocker_range()) {
158  // check if it is the first time we encounter the blocker
159  if (simplex.contains(*blocker)) {
160  Root_simplex_handle blocker_root(parent_complex.get_id(*(blocker)));
161  Simplex blocker_restr(
162  *(this->get_simplex_address(blocker_root)));
163  this->add_blocker(new Simplex(blocker_restr));
164  }
165  }
166  }
167 
168  void clear() {
169  adresses.clear();
170  ComplexType::clear();
171  }
172 
177  boost::optional<Vertex_handle> get_address(Root_vertex_handle global) const {
178  boost::optional < Vertex_handle > res;
179  IdAddressMapConstIterator it = adresses.find(global);
180  if (it == adresses.end())
181  res.reset();
182  else
183  res = (*it).second;
184  return res;
185  }
186 
187  // /**
188  // * Allocates a simplex in L corresponding to the simplex s in K
189  // * with its local adresses and returns an AddressSimplex.
190  // */
191  // boost::optional<Simplex> get_address(const Root_simplex_handle & s) const;
192 
193  // private:
198  // @remark should be private but problem with VS
199 
200  std::vector<boost::optional<Vertex_handle> > get_addresses(
201  const Root_simplex_handle & s) const {
202  std::vector < boost::optional<Vertex_handle> > res;
203  for (auto i : s) {
204  res.push_back(get_address(i));
205  }
206  return res;
207  }
208 };
209 
216 template<typename ComplexType>
217 bool proper_face_in_union(
219  std::vector<boost::optional<typename ComplexType::Vertex_handle> > & addresses_sigma_in_link,
220  std::size_t vertex_to_be_ignored) {
221  // we test that all vertices of 'addresses_sigma_in_link' but 'vertex_to_be_ignored'
222  // are in link1 if it is the case we construct the corresponding simplex
223  bool vertices_sigma_are_in_link = true;
224  typename ComplexType::Simplex sigma_in_link;
225  for (std::size_t i = 0; i < addresses_sigma_in_link.size(); ++i) {
226  if (i != vertex_to_be_ignored) {
227  if (!addresses_sigma_in_link[i]) {
228  vertices_sigma_are_in_link = false;
229  break;
230  } else {
231  sigma_in_link.add_vertex(*addresses_sigma_in_link[i]);
232  }
233  }
234  }
235  // If one of vertices of the simplex is not in the complex then it returns false
236  // Otherwise, it tests if the simplex is in the complex
237  return vertices_sigma_are_in_link && link.contains(sigma_in_link);
238 }
239 
240 // Remark: this function should be friend in order to leave get_adresses private
241 // however doing so seemes currently not possible due to a visual studio bug c2668
242 // "the compiler does not support partial ordering of template functions as specified in the C++ Standard"
243 // http://www.serkey.com/error-c2668-ambiguous-call-to-overloaded-function-bb45ft.html
244 
245 template<typename ComplexType>
246 bool proper_faces_in_union(
250  typedef typename ComplexType::Vertex_handle Vertex_handle;
251  std::vector < boost::optional<Vertex_handle> > addresses_sigma_in_link1 =
252  link1.get_addresses(sigma);
253  std::vector < boost::optional<Vertex_handle> > addresses_sigma_in_link2 =
254  link2.get_addresses(sigma);
255 
256  for (std::size_t current_index = 0; current_index < addresses_sigma_in_link1.size();
257  ++current_index) {
258  if (!proper_face_in_union(link1, addresses_sigma_in_link1, current_index)
259  && !proper_face_in_union(link2, addresses_sigma_in_link2,
260  current_index)) {
261  return false;
262  }
263  }
264  return true;
265 }
266 
267 } // namespace skeleton_blocker
268 
269 namespace skbl = skeleton_blocker;
270 
271 } // namespace Gudhi
272 
273 #endif // SKELETON_BLOCKER_SKELETON_BLOCKER_SUB_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
boost::optional< Vertex_handle > get_address(Root_vertex_handle global) const
Definition: Skeleton_blocker_sub_complex.h:177
std::vector< boost::optional< Vertex_handle > > get_addresses(const Root_simplex_handle &s) const
Definition: Skeleton_blocker_sub_complex.h:200
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
Link_complex link(Vertex_handle v) const
Definition: Skeleton_blocker_complex.h:905
Vertex_handle add_vertex(Root_vertex_handle global)
Definition: Skeleton_blocker_sub_complex.h:96
void clear()
Definition: Skeleton_blocker_sub_complex.h:168
void make_restricted_complex(const ComplexType &parent_complex, const Simplex &simplex)
Definition: Skeleton_blocker_sub_complex.h:135
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