Bitmap_cubical_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): Pawel Dlotko
6  *
7  * Copyright (C) 2015 INRIA Sophia-Saclay (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 
23 #ifndef BITMAP_CUBICAL_COMPLEX_H_
24 #define BITMAP_CUBICAL_COMPLEX_H_
25 
26 #include <gudhi/Bitmap_cubical_complex_base.h>
27 #include <gudhi/Bitmap_cubical_complex_periodic_boundary_conditions_base.h>
28 
29 #ifdef GUDHI_USE_TBB
30 #include <tbb/parallel_sort.h>
31 #endif
32 
33 #include <limits>
34 #include <utility> // for pair<>
35 #include <algorithm> // for sort
36 #include <vector>
37 #include <numeric> // for iota
38 
39 namespace Gudhi {
40 
41 namespace cubical_complex {
42 
43 // global variable, was used just for debugging.
44 const bool globalDbg = false;
45 
46 template <typename T> class is_before_in_filtration;
47 
57 template <typename T>
58 class Bitmap_cubical_complex : public T {
59  public:
60  //*********************************************//
61  // Typedefs and typenames
62  //*********************************************//
63  typedef size_t Simplex_key;
64  typedef typename T::filtration_type Filtration_value;
65  typedef Simplex_key Simplex_handle;
66 
67 
68  //*********************************************//
69  // Constructors
70  //*********************************************//
71  // Over here we need to define various input types. I am proposing the following ones:
72  // Perseus style
73  // TODO(PD) H5 files?
74  // TODO(PD) binary files with little endiangs / big endians ?
75  // TODO(PD) constructor from a vector of elements of a type T. ?
76 
80  Bitmap_cubical_complex(const char* perseus_style_file) :
81  T(perseus_style_file), key_associated_to_simplex(this->total_number_of_cells + 1) {
82  if (globalDbg) {
83  std::cerr << "Bitmap_cubical_complex( const char* perseus_style_file )\n";
84  }
85  for (size_t i = 0; i != this->total_number_of_cells; ++i) {
86  this->key_associated_to_simplex[i] = i;
87  }
88  // we initialize this only once, in each constructor, when the bitmap is constructed.
89  // If the user decide to change some elements of the bitmap, then this procedure need
90  // to be called again.
92  }
93 
99  Bitmap_cubical_complex(const std::vector<unsigned>& dimensions,
100  const std::vector<Filtration_value>& top_dimensional_cells) :
101  T(dimensions, top_dimensional_cells),
102  key_associated_to_simplex(this->total_number_of_cells + 1) {
103  for (size_t i = 0; i != this->total_number_of_cells; ++i) {
104  this->key_associated_to_simplex[i] = i;
105  }
106  // we initialize this only once, in each constructor, when the bitmap is constructed.
107  // If the user decide to change some elements of the bitmap, then this procedure need
108  // to be called again.
110  }
111 
119  Bitmap_cubical_complex(const std::vector<unsigned>& dimensions,
120  const std::vector<Filtration_value>& top_dimensional_cells,
121  std::vector< bool > directions_in_which_periodic_b_cond_are_to_be_imposed) :
122  T(dimensions, top_dimensional_cells, directions_in_which_periodic_b_cond_are_to_be_imposed),
123  key_associated_to_simplex(this->total_number_of_cells + 1) {
124  for (size_t i = 0; i != this->total_number_of_cells; ++i) {
125  this->key_associated_to_simplex[i] = i;
126  }
127  // we initialize this only once, in each constructor, when the bitmap is constructed.
128  // If the user decide to change some elements of the bitmap, then this procedure need
129  // to be called again.
131  }
132 
137 
138  //*********************************************//
139  // Other 'easy' functions
140  //*********************************************//
141 
145  size_t num_simplices()const {
146  return this->total_number_of_cells;
147  }
148 
152  static Simplex_handle null_simplex() {
153  if (globalDbg) {
154  std::cerr << "Simplex_handle null_simplex()\n";
155  }
156  return std::numeric_limits<Simplex_handle>::max();
157  }
158 
162  inline size_t dimension()const {
163  return this->sizes.size();
164  }
165 
169  inline unsigned dimension(Simplex_handle sh)const {
170  if (globalDbg) {
171  std::cerr << "unsigned dimension(const Simplex_handle& sh)\n";
172  }
173  if (sh != null_simplex()) return this->get_dimension_of_a_cell(sh);
174  return -1;
175  }
176 
180  Filtration_value filtration(Simplex_handle sh) {
181  if (globalDbg) {
182  std::cerr << "Filtration_value filtration(const Simplex_handle& sh)\n";
183  }
184  // Returns the filtration value of a simplex.
185  if (sh != null_simplex()) return this->data[sh];
186  return std::numeric_limits<Filtration_value>::infinity();
187  }
188 
192  static Simplex_key null_key() {
193  if (globalDbg) {
194  std::cerr << "Simplex_key null_key()\n";
195  }
196  return std::numeric_limits<Simplex_handle>::max();
197  }
198 
202  Simplex_key key(Simplex_handle sh)const {
203  if (globalDbg) {
204  std::cerr << "Simplex_key key(const Simplex_handle& sh)\n";
205  }
206  if (sh != null_simplex()) {
207  return this->key_associated_to_simplex[sh];
208  }
209  return this->null_key();
210  }
211 
215  Simplex_handle simplex(Simplex_key key) {
216  if (globalDbg) {
217  std::cerr << "Simplex_handle simplex(Simplex_key key)\n";
218  }
219  if (key != null_key()) {
220  return this->simplex_associated_to_key[ key ];
221  }
222  return null_simplex();
223  }
224 
228  void assign_key(Simplex_handle sh, Simplex_key key) {
229  if (globalDbg) {
230  std::cerr << "void assign_key(Simplex_handle& sh, Simplex_key key)\n";
231  }
232  if (key == null_key()) return;
233  this->key_associated_to_simplex[sh] = key;
234  this->simplex_associated_to_key[key] = sh;
235  }
236 
241 
242  //*********************************************//
243  // Iterators
244  //*********************************************//
245 
249  typedef typename std::vector< Simplex_handle >::iterator Boundary_simplex_iterator;
250  typedef typename std::vector< Simplex_handle > Boundary_simplex_range;
251 
258  class Filtration_simplex_range;
259 
260  class Filtration_simplex_iterator : std::iterator< std::input_iterator_tag, Simplex_handle > {
261  // Iterator over all simplices of the complex in the order of the indexing scheme.
262  // 'value_type' must be 'Simplex_handle'.
263  public:
264  Filtration_simplex_iterator(Bitmap_cubical_complex* b) : b(b), position(0) { }
265 
266  Filtration_simplex_iterator() : b(NULL), position(0) { }
267 
268  Filtration_simplex_iterator operator++() {
269  if (globalDbg) {
270  std::cerr << "Filtration_simplex_iterator operator++\n";
271  }
272  ++this->position;
273  return (*this);
274  }
275 
276  Filtration_simplex_iterator operator++(int) {
277  Filtration_simplex_iterator result = *this;
278  ++(*this);
279  return result;
280  }
281 
282  Filtration_simplex_iterator& operator=(const Filtration_simplex_iterator& rhs) {
283  if (globalDbg) {
284  std::cerr << "Filtration_simplex_iterator operator =\n";
285  }
286  this->b = rhs.b;
287  this->position = rhs.position;
288  return (*this);
289  }
290 
291  bool operator==(const Filtration_simplex_iterator& rhs)const {
292  if (globalDbg) {
293  std::cerr << "bool operator == ( const Filtration_simplex_iterator& rhs )\n";
294  }
295  return ( this->position == rhs.position);
296  }
297 
298  bool operator!=(const Filtration_simplex_iterator& rhs)const {
299  if (globalDbg) {
300  std::cerr << "bool operator != ( const Filtration_simplex_iterator& rhs )\n";
301  }
302  return !(*this == rhs);
303  }
304 
305  Simplex_handle operator*() {
306  if (globalDbg) {
307  std::cerr << "Simplex_handle operator*()\n";
308  }
309  return this->b->simplex_associated_to_key[ this->position ];
310  }
311 
312  friend class Filtration_simplex_range;
313 
314  private:
316  size_t position;
317  };
318 
323  // Range over the simplices of the complex in the order of the filtration.
324  // .begin() and .end() return type Filtration_simplex_iterator.
325  public:
326  typedef Filtration_simplex_iterator const_iterator;
327  typedef Filtration_simplex_iterator iterator;
328 
330 
331  Filtration_simplex_iterator begin() {
332  if (globalDbg) {
333  std::cerr << "Filtration_simplex_iterator begin() \n";
334  }
335  return Filtration_simplex_iterator(this->b);
336  }
337 
338  Filtration_simplex_iterator end() {
339  if (globalDbg) {
340  std::cerr << "Filtration_simplex_iterator end()\n";
341  }
342  Filtration_simplex_iterator it(this->b);
343  it.position = this->b->simplex_associated_to_key.size();
344  return it;
345  }
346 
347  private:
349  };
350 
351 
352 
353  //*********************************************//
354  // Methods to access iterators from the container:
355 
360  Boundary_simplex_range boundary_simplex_range(Simplex_handle sh) {
361  return this->get_boundary_of_a_cell(sh);
362  }
363 
368  Filtration_simplex_range filtration_simplex_range() {
369  if (globalDbg) {
370  std::cerr << "Filtration_simplex_range filtration_simplex_range()\n";
371  }
372  // Returns a range over the simplices of the complex in the order of the filtration
373  return Filtration_simplex_range(this);
374  }
375  //*********************************************//
376 
377 
378 
379  //*********************************************//
380  // Elements which are in Gudhi now, but I (and in all the cases I asked also Marc) do not understand why they are
381  // there.
382  // TODO(PD) the file IndexingTag.h in the Gudhi library contains an empty structure, so
383  // I understand that this is something that was planned (for simplicial maps?)
384  // but was never finished. The only idea I have here is to use the same empty structure from
385  // IndexingTag.h file, but only if the compiler needs it. If the compiler
386  // do not need it, then I would rather not add here elements which I do not understand.
387  // typedef Indexing_tag
388 
392  std::pair<Simplex_handle, Simplex_handle> endpoints(Simplex_handle sh) {
393  std::vector< size_t > bdry = this->get_boundary_of_a_cell(sh);
394  if (globalDbg) {
395  std::cerr << "std::pair<Simplex_handle, Simplex_handle> endpoints( Simplex_handle sh )\n";
396  std::cerr << "bdry.size() : " << bdry.size() << std::endl;
397  }
398  // this method returns two first elements from the boundary of sh.
399  if (bdry.size() < 2)
400  throw("Error in endpoints in Bitmap_cubical_complex class. The cell have less than two elements in the "
401  "boundary.");
402  return std::make_pair(bdry[0], bdry[1]);
403  }
404 
405 
409  class Skeleton_simplex_range;
410 
411  class Skeleton_simplex_iterator : std::iterator< std::input_iterator_tag, Simplex_handle > {
412  // Iterator over all simplices of the complex in the order of the indexing scheme.
413  // 'value_type' must be 'Simplex_handle'.
414  public:
415  Skeleton_simplex_iterator(Bitmap_cubical_complex* b, size_t d) : b(b), dimension(d) {
416  if (globalDbg) {
417  std::cerr << "Skeleton_simplex_iterator ( Bitmap_cubical_complex* b , size_t d )\n";
418  }
419  // find the position of the first simplex of a dimension d
420  this->position = 0;
421  while (
422  (this->position != b->data.size()) &&
423  (this->b->get_dimension_of_a_cell(this->position) != this->dimension)
424  ) {
425  ++this->position;
426  }
427  }
428 
429  Skeleton_simplex_iterator() : b(NULL), position(0), dimension(0) { }
430 
431  Skeleton_simplex_iterator operator++() {
432  if (globalDbg) {
433  std::cerr << "Skeleton_simplex_iterator operator++()\n";
434  }
435  // increment the position as long as you did not get to the next element of the dimension dimension.
436  ++this->position;
437  while (
438  (this->position != this->b->data.size()) &&
439  (this->b->get_dimension_of_a_cell(this->position) != this->dimension)
440  ) {
441  ++this->position;
442  }
443  return (*this);
444  }
445 
446  Skeleton_simplex_iterator operator++(int) {
447  Skeleton_simplex_iterator result = *this;
448  ++(*this);
449  return result;
450  }
451 
452  Skeleton_simplex_iterator& operator=(const Skeleton_simplex_iterator& rhs) {
453  if (globalDbg) {
454  std::cerr << "Skeleton_simplex_iterator operator =\n";
455  }
456  this->b = rhs.b;
457  this->position = rhs.position;
458  this->dimension = rhs.dimension;
459  return (*this);
460  }
461 
462  bool operator==(const Skeleton_simplex_iterator& rhs)const {
463  if (globalDbg) {
464  std::cerr << "bool operator ==\n";
465  }
466  return ( this->position == rhs.position);
467  }
468 
469  bool operator!=(const Skeleton_simplex_iterator& rhs)const {
470  if (globalDbg) {
471  std::cerr << "bool operator != ( const Skeleton_simplex_iterator& rhs )\n";
472  }
473  return !(*this == rhs);
474  }
475 
476  Simplex_handle operator*() {
477  if (globalDbg) {
478  std::cerr << "Simplex_handle operator*() \n";
479  }
480  return this->position;
481  }
482 
483  friend class Skeleton_simplex_range;
484  private:
486  size_t position;
487  unsigned dimension;
488  };
489 
494  // Range over the simplices of the complex in the order of the filtration.
495  // .begin() and .end() return type Filtration_simplex_iterator.
496  public:
497  typedef Skeleton_simplex_iterator const_iterator;
498  typedef Skeleton_simplex_iterator iterator;
499 
500  Skeleton_simplex_range(Bitmap_cubical_complex<T>* b, unsigned dimension) : b(b), dimension(dimension) { }
501 
502  Skeleton_simplex_iterator begin() {
503  if (globalDbg) {
504  std::cerr << "Skeleton_simplex_iterator begin()\n";
505  }
506  return Skeleton_simplex_iterator(this->b, this->dimension);
507  }
508 
509  Skeleton_simplex_iterator end() {
510  if (globalDbg) {
511  std::cerr << "Skeleton_simplex_iterator end()\n";
512  }
513  Skeleton_simplex_iterator it(this->b, this->dimension);
514  it.position = this->b->data.size();
515  return it;
516  }
517 
518  private:
520  unsigned dimension;
521  };
522 
526  Skeleton_simplex_range skeleton_simplex_range(unsigned dimension) {
527  if (globalDbg) {
528  std::cerr << "Skeleton_simplex_range skeleton_simplex_range( unsigned dimension )\n";
529  }
530  return Skeleton_simplex_range(this, dimension);
531  }
532 
533  friend class is_before_in_filtration<T>;
534 
535  protected:
536  std::vector< size_t > key_associated_to_simplex;
537  std::vector< size_t > simplex_associated_to_key;
538 }; // Bitmap_cubical_complex
539 
540 template <typename T>
542  if (globalDbg) {
543  std::cerr << "void Bitmap_cubical_complex<T>::initialize_elements_ordered_according_to_filtration() \n";
544  }
545  this->simplex_associated_to_key = std::vector<size_t>(this->data.size());
546  std::iota(std::begin(simplex_associated_to_key), std::end(simplex_associated_to_key), 0);
547 #ifdef GUDHI_USE_TBB
548  tbb::parallel_sort(simplex_associated_to_key.begin(), simplex_associated_to_key.end(),
549  is_before_in_filtration<T>(this));
550 #else
551  std::sort(simplex_associated_to_key.begin(), simplex_associated_to_key.end(), is_before_in_filtration<T>(this));
552 #endif
553 
554  // we still need to deal here with a key_associated_to_simplex:
555  for ( size_t i = 0 ; i != simplex_associated_to_key.size() ; ++i ) {
556  this->key_associated_to_simplex[ simplex_associated_to_key[i] ] = i;
557  }
558 }
559 
560 template <typename T>
561 class is_before_in_filtration {
562  public:
563  explicit is_before_in_filtration(Bitmap_cubical_complex<T> * CC)
564  : CC_(CC) { }
565 
566  bool operator()(const typename Bitmap_cubical_complex<T>::Simplex_handle& sh1,
567  const typename Bitmap_cubical_complex<T>::Simplex_handle& sh2) const {
568  // Not using st_->filtration(sh1) because it uselessly tests for null_simplex.
569  typedef typename T::filtration_type Filtration_value;
570  Filtration_value fil1 = CC_->data[sh1];
571  Filtration_value fil2 = CC_->data[sh2];
572  if (fil1 != fil2) {
573  return fil1 < fil2;
574  }
575  // in this case they are on the same filtration level, so the dimension decide.
576  size_t dim1 = CC_->get_dimension_of_a_cell(sh1);
577  size_t dim2 = CC_->get_dimension_of_a_cell(sh2);
578  if (dim1 != dim2) {
579  return dim1 < dim2;
580  }
581  // in this case both filtration and dimensions of the considered cubes are the same. To have stable sort, we simply
582  // compare their positions in the bitmap:
583  return sh1 < sh2;
584  }
585 
586  protected:
588 };
589 
590 } // namespace cubical_complex
591 
592 namespace Cubical_complex = cubical_complex;
593 
594 } // namespace Gudhi
595 
596 #endif // BITMAP_CUBICAL_COMPLEX_H_
virtual ~Bitmap_cubical_complex()
Definition: Bitmap_cubical_complex.h:136
Boundary_simplex_range boundary_simplex_range(Simplex_handle sh)
Definition: Bitmap_cubical_complex.h:360
void initialize_simplex_associated_to_key()
Definition: Bitmap_cubical_complex.h:541
std::pair< Simplex_handle, Simplex_handle > endpoints(Simplex_handle sh)
Definition: Bitmap_cubical_complex.h:392
Definition: SimplicialComplexForAlpha.h:26
std::vector< Simplex_handle >::iterator Boundary_simplex_iterator
Definition: Bitmap_cubical_complex.h:249
Filtration_simplex_range filtration_simplex_range()
Definition: Bitmap_cubical_complex.h:368
Simplex_handle simplex(Simplex_key key)
Definition: Bitmap_cubical_complex.h:215
size_t num_simplices() const
Definition: Bitmap_cubical_complex.h:145
Simplex_key key(Simplex_handle sh) const
Definition: Bitmap_cubical_complex.h:202
Filtration_simplex_range provides the ranges for Filtration_simplex_iterator.
Definition: Bitmap_cubical_complex.h:322
void assign_key(Simplex_handle sh, Simplex_key key)
Definition: Bitmap_cubical_complex.h:228
Cubical complex represented as a bitmap.
Definition: Bitmap_cubical_complex.h:58
Bitmap_cubical_complex(const std::vector< unsigned > &dimensions, const std::vector< Filtration_value > &top_dimensional_cells)
Definition: Bitmap_cubical_complex.h:99
Bitmap_cubical_complex(const std::vector< unsigned > &dimensions, const std::vector< Filtration_value > &top_dimensional_cells, std::vector< bool > directions_in_which_periodic_b_cond_are_to_be_imposed)
Definition: Bitmap_cubical_complex.h:119
unsigned dimension(Simplex_handle sh) const
Definition: Bitmap_cubical_complex.h:169
Class needed for compatibility with Gudhi. Not useful for other purposes.
Definition: Bitmap_cubical_complex.h:493
static Simplex_key null_key()
Definition: Bitmap_cubical_complex.h:192
Bitmap_cubical_complex(const char *perseus_style_file)
Definition: Bitmap_cubical_complex.h:80
static Simplex_handle null_simplex()
Definition: Bitmap_cubical_complex.h:152
Skeleton_simplex_range skeleton_simplex_range(unsigned dimension)
Definition: Bitmap_cubical_complex.h:526
size_t dimension() const
Definition: Bitmap_cubical_complex.h:162
Filtration_value filtration(Simplex_handle sh)
Definition: Bitmap_cubical_complex.h:180
GUDHI  Version 2.0.1  - C++ library for Topological Data Analysis (TDA) and Higher Dimensional Geometry Understanding. Generated on Mon Oct 2 2017 10:20:49 for GUDHI by doxygen 1.8.11