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