Skeleton_blockers_simplices_iterators.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_ITERATORS_SKELETON_BLOCKERS_SIMPLICES_ITERATORS_H_
24 #define SKELETON_BLOCKER_ITERATORS_SKELETON_BLOCKERS_SIMPLICES_ITERATORS_H_
25 
26 #include <gudhi/Skeleton_blocker_link_complex.h>
27 #include <gudhi/Skeleton_blocker/Skeleton_blocker_link_superior.h>
28 #include <gudhi/Skeleton_blocker/internal/Trie.h>
29 #include <gudhi/Debug_utils.h>
30 
31 #include <boost/iterator/iterator_facade.hpp>
32 
33 #include <memory>
34 #include <list>
35 #include <iostream>
36 
37 namespace Gudhi {
38 
39 namespace skeleton_blocker {
40 
49 template<typename SkeletonBlockerComplex, typename Link>
51 public boost::iterator_facade < Simplex_around_vertex_iterator<SkeletonBlockerComplex, Link>
52 , typename SkeletonBlockerComplex::Simplex
53 , boost::forward_traversal_tag
54 , typename SkeletonBlockerComplex::Simplex
55 > {
56  friend class boost::iterator_core_access;
57  typedef SkeletonBlockerComplex Complex;
58  typedef typename Complex::Vertex_handle Vertex_handle;
59  typedef typename Complex::Edge_handle Edge_handle;
60  typedef typename Complex::Simplex Simplex;
61 
62  // Link_vertex_handle == Complex_Vertex_handle but this renaming helps avoiding confusion
63  typedef typename Link::Vertex_handle Link_vertex_handle;
64 
65  typedef typename Gudhi::skeleton_blocker::Trie<Simplex> Trie;
66 
67  private:
68  const Complex* complex;
69  Vertex_handle v;
70  std::shared_ptr<Link> link_v;
71  std::shared_ptr<Trie> trie;
72  // TODO(DS): use a deque instead
73  std::list<Trie*> nodes_to_be_seen;
74 
75  public:
76  Simplex_around_vertex_iterator() : complex(0) { }
77 
78  Simplex_around_vertex_iterator(const Complex* complex_, Vertex_handle v_) :
79  complex(complex_),
80  v(v_),
81  link_v(new Link(*complex_, v_)),
82  trie(new Trie(v_)) {
83  compute_trie_and_nodes_to_be_seen();
84  }
85 
86  // TODO(DS): avoid useless copy
87  // TODO(DS): currently just work if copy begin iterator
89  complex(other.complex),
90  v(other.v),
91  link_v(other.link_v),
92  trie(other.trie),
93  nodes_to_be_seen(other.nodes_to_be_seen) {
94  if (!other.is_end()) {
95  }
96  }
97 
101  Simplex_around_vertex_iterator(const Complex* complex_, Vertex_handle v_, bool end) :
102  complex(complex_),
103  v(v_) {
104  set_end();
105  }
106 
107  private:
108  void compute_trie_and_nodes_to_be_seen() {
109  // once we go through every simplices passing through v0
110  // we remove v0. That way, it prevents from passing a lot of times
111  // though edges leaving v0.
112  // another solution would have been to provides an adjacency iterator
113  // to superior vertices that avoids lower ones.
114  while (!link_v->empty()) {
115  auto v0 = *(link_v->vertex_range().begin());
116  trie->add_child(build_trie(v0, trie.get()));
117  link_v->remove_vertex(v0);
118  }
119  nodes_to_be_seen.push_back(trie.get());
120  }
121 
122  Trie* build_trie(Link_vertex_handle link_vh, Trie* parent) {
123  Trie* res = new Trie(parent_vertex(link_vh), parent);
124  for (Link_vertex_handle nv : link_v->vertex_range(link_vh)) {
125  if (link_vh < nv) {
126  Simplex simplex_node_plus_nv(res->simplex());
127  simplex_node_plus_nv.add_vertex(parent_vertex(nv));
128  if (complex->contains(simplex_node_plus_nv)) {
129  res->add_child(build_trie(nv, res));
130  }
131  }
132  }
133  return res;
134  }
135 
136  bool is_node_in_complex(Trie* trie) {
137  return true;
138  }
139 
140  Vertex_handle parent_vertex(Link_vertex_handle link_vh) const {
141  return complex->convert_handle_from_another_complex(*link_v, link_vh);
142  }
143 
144  public:
145  friend std::ostream& operator<<(std::ostream& stream, const Simplex_around_vertex_iterator& savi) {
146  stream << savi.trie << std::endl;
147  stream << "(" << savi.nodes_to_be_seen.size() << ") nodes to see\n";
148  return stream;
149  }
150 
151  bool equal(const Simplex_around_vertex_iterator& other) const {
152  bool same_complex = (complex == other.complex);
153  if (!same_complex)
154  return false;
155 
156  if (!(v == other.v))
157  return false;
158 
159  bool both_empty = nodes_to_be_seen.empty() && other.nodes_to_be_seen.empty();
160  if (both_empty)
161  return true;
162 
163  bool both_non_empty = !nodes_to_be_seen.empty() && !other.nodes_to_be_seen.empty();
164 
165  // one is empty the other is not
166  if (!both_non_empty) return false;
167 
168  bool same_node = (**(nodes_to_be_seen.begin()) == **(other.nodes_to_be_seen.begin()));
169  return same_node;
170  }
171 
172  void increment() {
173  assert(!is_end());
174  Trie* first_node = nodes_to_be_seen.front();
175 
176  nodes_to_be_seen.pop_front();
177 
178  for (auto childs : first_node->childs) {
179  nodes_to_be_seen.push_back(childs.get());
180  }
181  }
182 
183  Simplex dereference() const {
184  assert(!nodes_to_be_seen.empty());
185  Trie* first_node = nodes_to_be_seen.front();
186  return first_node->simplex();
187  }
188 
189  Simplex get_trie_address() const {
190  assert(!nodes_to_be_seen.empty());
191  return nodes_to_be_seen.front();
192  }
193 
194  private:
195  void set_end() {
196  nodes_to_be_seen.clear();
197  }
198 
199  bool is_end() const {
200  return nodes_to_be_seen.empty();
201  }
202 };
203 
204 template<typename SkeletonBlockerComplex>
205 class Simplex_iterator :
206 public boost::iterator_facade < Simplex_iterator<SkeletonBlockerComplex>
207 , typename SkeletonBlockerComplex::Simplex
208 , boost::forward_traversal_tag
209 , typename SkeletonBlockerComplex::Simplex
210 > {
212 
213  friend class boost::iterator_core_access;
214 
215  template<class SkBlDS> friend class Skeleton_blocker_complex;
216 
217  typedef SkeletonBlockerComplex Complex;
218  typedef typename Complex::Vertex_handle Vertex_handle;
219  typedef typename Complex::Edge_handle Edge_handle;
220  typedef typename Complex::Simplex Simplex;
221  typedef typename Complex::Complex_vertex_iterator Complex_vertex_iterator;
222  typedef typename Link::Vertex_handle Link_vertex_handle;
223 
224  private:
225  const Complex* complex_;
226  Complex_vertex_iterator current_vertex_;
227 
229  SAVI current_simplex_around_current_vertex_;
230  SAVI simplices_around_current_vertex_end_;
231 
232  public:
233  Simplex_iterator() : complex_(0) { }
234 
235  Simplex_iterator(const Complex* complex) :
236  complex_(complex),
237  current_vertex_(complex->vertex_range().begin()),
238  current_simplex_around_current_vertex_(complex, *current_vertex_),
239  simplices_around_current_vertex_end_(complex, *current_vertex_, true) {
240  // should not be called if the complex is empty
241  assert(!complex->empty());
242  }
243 
244  private:
245  Simplex_iterator(const Complex* complex, bool end) :
246  complex_(complex) {
247  set_end();
248  }
249 
250  public:
251  Simplex_iterator(const Simplex_iterator& other)
252  :
253  complex_(other.complex_),
254  current_vertex_(other.current_vertex_),
255  current_simplex_around_current_vertex_(other.current_simplex_around_current_vertex_),
256  simplices_around_current_vertex_end_(other.simplices_around_current_vertex_end_) { }
257 
258  friend Simplex_iterator make_begin_iterator(const Complex* complex) {
259  if (complex->empty())
260  return make_end_simplex_iterator(complex);
261  else
262  return Simplex_iterator(complex);
263  }
264 
265  friend Simplex_iterator make_end_simplex_iterator(const Complex* complex) {
266  return Simplex_iterator(complex, true);
267  }
268 
269  bool equal(const Simplex_iterator& other) const {
270  if (complex_ != other.complex_) return false;
271  if (current_vertex_ != other.current_vertex_) return false;
272  if (is_end() && other.is_end()) return true;
273  if (current_simplex_around_current_vertex_ != other.current_simplex_around_current_vertex_)
274  return false;
275  return true;
276  }
277 
278  void increment() {
279  if (current_simplex_around_current_vertex_ != simplices_around_current_vertex_end_) {
280  current_simplex_around_current_vertex_.increment();
281  if (current_simplex_around_current_vertex_ == simplices_around_current_vertex_end_)
282  goto_next_vertex();
283  } else {
284  goto_next_vertex();
285  }
286  }
287 
288  void goto_next_vertex() {
289  current_vertex_.increment();
290  if (!is_end()) {
291  current_simplex_around_current_vertex_ = SAVI(complex_, *current_vertex_);
292  simplices_around_current_vertex_end_ = SAVI(complex_, *current_vertex_, true);
293  }
294  }
295 
296  Simplex dereference() const {
297  return current_simplex_around_current_vertex_.dereference();
298  }
299 
300  private:
301  void set_end() {
302  current_vertex_ = complex_->vertex_range().end();
303  }
304 
305  bool is_end() const {
306  return (current_vertex_ == complex_->vertex_range().end());
307  }
308 };
309 
313 template<typename SkeletonBlockerComplex, typename Link>
315 public boost::iterator_facade < Simplex_coboundary_iterator<SkeletonBlockerComplex, Link>
316 , typename SkeletonBlockerComplex::Simplex, boost::forward_traversal_tag, typename SkeletonBlockerComplex::Simplex> {
317  friend class boost::iterator_core_access;
318  typedef SkeletonBlockerComplex Complex;
319  typedef typename Complex::Vertex_handle Vertex_handle;
320  typedef typename Complex::Edge_handle Edge_handle;
321  typedef typename Complex::Simplex Simplex;
322  typedef typename Complex::Complex_vertex_iterator Complex_vertex_iterator;
323 
324  // Link_vertex_handle == Complex_Vertex_handle but this renaming helps avoiding confusion
325  typedef typename Link::Vertex_handle Link_vertex_handle;
326 
327  private:
328  const Complex* complex;
329  const Simplex& sigma;
330  std::shared_ptr<Link> link;
331  Complex_vertex_iterator current_vertex;
332  Complex_vertex_iterator link_vertex_end;
333 
334  public:
335  Simplex_coboundary_iterator() : complex(0) { }
336 
337  Simplex_coboundary_iterator(const Complex* complex_, const Simplex& sigma_) :
338  complex(complex_),
339  sigma(sigma_),
340  // need only vertices of the link hence the true flag
341  link(new Link(*complex_, sigma_, false, true)) {
342  auto link_vertex_range = link->vertex_range();
343  current_vertex = link_vertex_range.begin();
344  link_vertex_end = link_vertex_range.end();
345  }
346 
348  complex(other.complex),
349  sigma(other.sigma),
350  link(other.link),
351  current_vertex(other.current_vertex),
352  link_vertex_end(other.link_vertex_end) { }
353 
354  // returns an iterator to the end
355  Simplex_coboundary_iterator(const Complex* complex_, const Simplex& sigma_, bool end) :
356  complex(complex_),
357  sigma(sigma_) {
358  // to represent an end iterator without having to build a useless link, we use
359  // the convection that link is not initialized.
360  }
361 
362  private:
363  Vertex_handle parent_vertex(Link_vertex_handle link_vh) const {
364  return complex->convert_handle_from_another_complex(*link, link_vh);
365  }
366 
367  public:
368  friend std::ostream& operator<<(std::ostream& stream, const Simplex_coboundary_iterator& sci) {
369  return stream;
370  }
371 
372  // assume that iterator points to the same complex and comes from the same simplex
373  bool equal(const Simplex_coboundary_iterator& other) const {
374  assert(complex == other.complex && sigma == other.sigma);
375  if (is_end()) return other.is_end();
376  if (other.is_end()) return is_end();
377  return *current_vertex == *(other.current_vertex);
378  }
379 
380  void increment() {
381  ++current_vertex;
382  }
383 
384  Simplex dereference() const {
385  Simplex res(sigma);
386  res.add_vertex(parent_vertex(*current_vertex));
387  return res;
388  }
389 
390  private:
391  bool is_end() const {
392  return !link || current_vertex == link_vertex_end;
393  }
394 };
395 
396 } // namespace skeleton_blocker
397 
398 namespace skbl = skeleton_blocker;
399 
400 } // namespace Gudhi
401 
402 #endif // SKELETON_BLOCKER_ITERATORS_SKELETON_BLOCKERS_SIMPLICES_ITERATORS_H_
Simplex_around_vertex_iterator(const Complex *complex_, Vertex_handle v_, bool end)
Definition: Skeleton_blockers_simplices_iterators.h:101
Definition: SimplicialComplexForAlpha.h:26
Definition: Skeleton_blockers_simplices_iterators.h:314
Definition: Skeleton_blockers_simplices_iterators.h:50
Abstract Simplicial Complex represented with a skeleton/blockers pair.
Definition: Skeleton_blocker_complex.h:63
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:54 for GUDHI by Doxygen 1.8.13