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
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 #include <cstddef>
39 
40 namespace Gudhi {
41 
42 namespace cubical_complex {
43 
44 // global variable, was used just for debugging.
45 const bool globalDbg = false;
46 
47 template <typename T>
48 class is_before_in_filtration;
49 
59 template <typename T>
60 class Bitmap_cubical_complex : public T {
61  public:
62  //*********************************************//
63  // Typedefs and typenames
64  //*********************************************//
65  typedef std::size_t Simplex_key;
66  typedef typename T::filtration_type Filtration_value;
67  typedef Simplex_key Simplex_handle;
68 
69  //*********************************************//
70  // Constructors
71  //*********************************************//
72  // Over here we need to define various input types. I am proposing the following ones:
73  // Perseus style
74  // TODO(PD) H5 files?
75  // TODO(PD) binary files with little endiangs / big endians ?
76  // TODO(PD) constructor from a vector of elements of a type T. ?
77 
81  Bitmap_cubical_complex(const char* perseus_style_file)
82  : T(perseus_style_file), key_associated_to_simplex(this->total_number_of_cells + 1) {
83  if (globalDbg) {
84  std::cerr << "Bitmap_cubical_complex( const char* perseus_style_file )\n";
85  }
86  for (std::size_t i = 0; i != this->total_number_of_cells; ++i) {
87  this->key_associated_to_simplex[i] = i;
88  }
89  // we initialize this only once, in each constructor, when the bitmap is constructed.
90  // If the user decide to change some elements of the bitmap, then this procedure need
91  // to be called again.
93  }
94 
100  Bitmap_cubical_complex(const std::vector<unsigned>& dimensions,
101  const std::vector<Filtration_value>& top_dimensional_cells)
102  : T(dimensions, top_dimensional_cells), key_associated_to_simplex(this->total_number_of_cells + 1) {
103  for (std::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 (std::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  std::size_t num_simplices() const { return this->total_number_of_cells; }
146 
150  static Simplex_handle null_simplex() {
151  if (globalDbg) {
152  std::cerr << "Simplex_handle null_simplex()\n";
153  }
154  return std::numeric_limits<Simplex_handle>::max();
155  }
156 
160  inline std::size_t dimension() const { return this->sizes.size(); }
161 
165  inline unsigned dimension(Simplex_handle sh) const {
166  if (globalDbg) {
167  std::cerr << "unsigned dimension(const Simplex_handle& sh)\n";
168  }
169  if (sh != null_simplex()) return this->get_dimension_of_a_cell(sh);
170  return -1;
171  }
172 
176  Filtration_value filtration(Simplex_handle sh) {
177  if (globalDbg) {
178  std::cerr << "Filtration_value filtration(const Simplex_handle& sh)\n";
179  }
180  // Returns the filtration value of a simplex.
181  if (sh != null_simplex()) return this->data[sh];
182  return std::numeric_limits<Filtration_value>::infinity();
183  }
184 
188  static Simplex_key null_key() {
189  if (globalDbg) {
190  std::cerr << "Simplex_key null_key()\n";
191  }
192  return std::numeric_limits<Simplex_handle>::max();
193  }
194 
198  Simplex_key key(Simplex_handle sh) const {
199  if (globalDbg) {
200  std::cerr << "Simplex_key key(const Simplex_handle& sh)\n";
201  }
202  if (sh != null_simplex()) {
203  return this->key_associated_to_simplex[sh];
204  }
205  return this->null_key();
206  }
207 
211  Simplex_handle simplex(Simplex_key key) {
212  if (globalDbg) {
213  std::cerr << "Simplex_handle simplex(Simplex_key key)\n";
214  }
215  if (key != null_key()) {
216  return this->simplex_associated_to_key[key];
217  }
218  return null_simplex();
219  }
220 
224  void assign_key(Simplex_handle sh, Simplex_key key) {
225  if (globalDbg) {
226  std::cerr << "void assign_key(Simplex_handle& sh, Simplex_key key)\n";
227  }
228  if (key == null_key()) return;
229  this->key_associated_to_simplex[sh] = key;
230  this->simplex_associated_to_key[key] = sh;
231  }
232 
237 
238  //*********************************************//
239  // Iterators
240  //*********************************************//
241 
245  typedef typename std::vector<Simplex_handle>::iterator Boundary_simplex_iterator;
246  typedef typename std::vector<Simplex_handle> Boundary_simplex_range;
247 
254  class Filtration_simplex_range;
255 
256  class Filtration_simplex_iterator : std::iterator<std::input_iterator_tag, Simplex_handle> {
257  // Iterator over all simplices of the complex in the order of the indexing scheme.
258  // 'value_type' must be 'Simplex_handle'.
259  public:
260  Filtration_simplex_iterator(Bitmap_cubical_complex* b) : b(b), position(0) {}
261 
262  Filtration_simplex_iterator() : b(NULL), position(0) {}
263 
264  Filtration_simplex_iterator operator++() {
265  if (globalDbg) {
266  std::cerr << "Filtration_simplex_iterator operator++\n";
267  }
268  ++this->position;
269  return (*this);
270  }
271 
272  Filtration_simplex_iterator operator++(int) {
273  Filtration_simplex_iterator result = *this;
274  ++(*this);
275  return result;
276  }
277 
278  Filtration_simplex_iterator& operator=(const Filtration_simplex_iterator& rhs) {
279  if (globalDbg) {
280  std::cerr << "Filtration_simplex_iterator operator =\n";
281  }
282  this->b = rhs.b;
283  this->position = rhs.position;
284  return (*this);
285  }
286 
287  bool operator==(const Filtration_simplex_iterator& rhs) const {
288  if (globalDbg) {
289  std::cerr << "bool operator == ( const Filtration_simplex_iterator& rhs )\n";
290  }
291  return (this->position == rhs.position);
292  }
293 
294  bool operator!=(const Filtration_simplex_iterator& rhs) const {
295  if (globalDbg) {
296  std::cerr << "bool operator != ( const Filtration_simplex_iterator& rhs )\n";
297  }
298  return !(*this == rhs);
299  }
300 
301  Simplex_handle operator*() {
302  if (globalDbg) {
303  std::cerr << "Simplex_handle operator*()\n";
304  }
305  return this->b->simplex_associated_to_key[this->position];
306  }
307 
308  friend class Filtration_simplex_range;
309 
310  private:
312  std::size_t position;
313  };
314 
319  // Range over the simplices of the complex in the order of the filtration.
320  // .begin() and .end() return type Filtration_simplex_iterator.
321  public:
322  typedef Filtration_simplex_iterator const_iterator;
323  typedef Filtration_simplex_iterator iterator;
324 
326 
327  Filtration_simplex_iterator begin() {
328  if (globalDbg) {
329  std::cerr << "Filtration_simplex_iterator begin() \n";
330  }
331  return Filtration_simplex_iterator(this->b);
332  }
333 
334  Filtration_simplex_iterator end() {
335  if (globalDbg) {
336  std::cerr << "Filtration_simplex_iterator end()\n";
337  }
338  Filtration_simplex_iterator it(this->b);
339  it.position = this->b->simplex_associated_to_key.size();
340  return it;
341  }
342 
343  private:
345  };
346 
347  //*********************************************//
348  // Methods to access iterators from the container:
349 
354  Boundary_simplex_range boundary_simplex_range(Simplex_handle sh) { return this->get_boundary_of_a_cell(sh); }
355 
360  Filtration_simplex_range filtration_simplex_range() {
361  if (globalDbg) {
362  std::cerr << "Filtration_simplex_range filtration_simplex_range()\n";
363  }
364  // Returns a range over the simplices of the complex in the order of the filtration
365  return Filtration_simplex_range(this);
366  }
367  //*********************************************//
368 
369  //*********************************************//
370  // Elements which are in Gudhi now, but I (and in all the cases I asked also Marc) do not understand why they are
371  // there.
372  // TODO(PD) the file IndexingTag.h in the Gudhi library contains an empty structure, so
373  // I understand that this is something that was planned (for simplicial maps?)
374  // but was never finished. The only idea I have here is to use the same empty structure from
375  // IndexingTag.h file, but only if the compiler needs it. If the compiler
376  // do not need it, then I would rather not add here elements which I do not understand.
377  // typedef Indexing_tag
378 
382  std::pair<Simplex_handle, Simplex_handle> endpoints(Simplex_handle sh) {
383  std::vector<std::size_t> bdry = this->get_boundary_of_a_cell(sh);
384  if (globalDbg) {
385  std::cerr << "std::pair<Simplex_handle, Simplex_handle> endpoints( Simplex_handle sh )\n";
386  std::cerr << "bdry.size() : " << bdry.size() << "\n";
387  }
388  // this method returns two first elements from the boundary of sh.
389  if (bdry.size() < 2)
390  throw(
391  "Error in endpoints in Bitmap_cubical_complex class. The cell have less than two elements in the "
392  "boundary.");
393  return std::make_pair(bdry[0], bdry[1]);
394  }
395 
399  class Skeleton_simplex_range;
400 
401  class Skeleton_simplex_iterator : std::iterator<std::input_iterator_tag, Simplex_handle> {
402  // Iterator over all simplices of the complex in the order of the indexing scheme.
403  // 'value_type' must be 'Simplex_handle'.
404  public:
405  Skeleton_simplex_iterator(Bitmap_cubical_complex* b, std::size_t d) : b(b), dimension(d) {
406  if (globalDbg) {
407  std::cerr << "Skeleton_simplex_iterator ( Bitmap_cubical_complex* b , std::size_t d )\n";
408  }
409  // find the position of the first simplex of a dimension d
410  this->position = 0;
411  while ((this->position != b->data.size()) &&
412  (this->b->get_dimension_of_a_cell(this->position) != this->dimension)) {
413  ++this->position;
414  }
415  }
416 
417  Skeleton_simplex_iterator() : b(NULL), position(0), dimension(0) {}
418 
419  Skeleton_simplex_iterator operator++() {
420  if (globalDbg) {
421  std::cerr << "Skeleton_simplex_iterator operator++()\n";
422  }
423  // increment the position as long as you did not get to the next element of the dimension dimension.
424  ++this->position;
425  while ((this->position != this->b->data.size()) &&
426  (this->b->get_dimension_of_a_cell(this->position) != this->dimension)) {
427  ++this->position;
428  }
429  return (*this);
430  }
431 
432  Skeleton_simplex_iterator operator++(int) {
433  Skeleton_simplex_iterator result = *this;
434  ++(*this);
435  return result;
436  }
437 
438  Skeleton_simplex_iterator& operator=(const Skeleton_simplex_iterator& rhs) {
439  if (globalDbg) {
440  std::cerr << "Skeleton_simplex_iterator operator =\n";
441  }
442  this->b = rhs.b;
443  this->position = rhs.position;
444  this->dimension = rhs.dimension;
445  return (*this);
446  }
447 
448  bool operator==(const Skeleton_simplex_iterator& rhs) const {
449  if (globalDbg) {
450  std::cerr << "bool operator ==\n";
451  }
452  return (this->position == rhs.position);
453  }
454 
455  bool operator!=(const Skeleton_simplex_iterator& rhs) const {
456  if (globalDbg) {
457  std::cerr << "bool operator != ( const Skeleton_simplex_iterator& rhs )\n";
458  }
459  return !(*this == rhs);
460  }
461 
462  Simplex_handle operator*() {
463  if (globalDbg) {
464  std::cerr << "Simplex_handle operator*() \n";
465  }
466  return this->position;
467  }
468 
469  friend class Skeleton_simplex_range;
470 
471  private:
473  std::size_t position;
474  unsigned dimension;
475  };
476 
481  // Range over the simplices of the complex in the order of the filtration.
482  // .begin() and .end() return type Filtration_simplex_iterator.
483  public:
484  typedef Skeleton_simplex_iterator const_iterator;
485  typedef Skeleton_simplex_iterator iterator;
486 
487  Skeleton_simplex_range(Bitmap_cubical_complex<T>* b, unsigned dimension) : b(b), dimension(dimension) {}
488 
489  Skeleton_simplex_iterator begin() {
490  if (globalDbg) {
491  std::cerr << "Skeleton_simplex_iterator begin()\n";
492  }
493  return Skeleton_simplex_iterator(this->b, this->dimension);
494  }
495 
496  Skeleton_simplex_iterator end() {
497  if (globalDbg) {
498  std::cerr << "Skeleton_simplex_iterator end()\n";
499  }
500  Skeleton_simplex_iterator it(this->b, this->dimension);
501  it.position = this->b->data.size();
502  return it;
503  }
504 
505  private:
507  unsigned dimension;
508  };
509 
513  Skeleton_simplex_range skeleton_simplex_range(unsigned dimension) {
514  if (globalDbg) {
515  std::cerr << "Skeleton_simplex_range skeleton_simplex_range( unsigned dimension )\n";
516  }
517  return Skeleton_simplex_range(this, dimension);
518  }
519 
520  friend class is_before_in_filtration<T>;
521 
522  protected:
523  std::vector<std::size_t> key_associated_to_simplex;
524  std::vector<std::size_t> simplex_associated_to_key;
525 }; // Bitmap_cubical_complex
526 
527 template <typename T>
529  if (globalDbg) {
530  std::cerr << "void Bitmap_cubical_complex<T>::initialize_elements_ordered_according_to_filtration() \n";
531  }
532  this->simplex_associated_to_key = std::vector<std::size_t>(this->data.size());
533  std::iota(std::begin(simplex_associated_to_key), std::end(simplex_associated_to_key), 0);
534 #ifdef GUDHI_USE_TBB
535  tbb::parallel_sort(simplex_associated_to_key.begin(), simplex_associated_to_key.end(),
536  is_before_in_filtration<T>(this));
537 #else
538  std::sort(simplex_associated_to_key.begin(), simplex_associated_to_key.end(), is_before_in_filtration<T>(this));
539 #endif
540 
541  // we still need to deal here with a key_associated_to_simplex:
542  for (std::size_t i = 0; i != simplex_associated_to_key.size(); ++i) {
543  this->key_associated_to_simplex[simplex_associated_to_key[i]] = i;
544  }
545 }
546 
547 template <typename T>
548 class is_before_in_filtration {
549  public:
550  explicit is_before_in_filtration(Bitmap_cubical_complex<T>* CC) : CC_(CC) {}
551 
552  bool operator()(const typename Bitmap_cubical_complex<T>::Simplex_handle& sh1,
553  const typename Bitmap_cubical_complex<T>::Simplex_handle& sh2) const {
554  // Not using st_->filtration(sh1) because it uselessly tests for null_simplex.
555  typedef typename T::filtration_type Filtration_value;
556  Filtration_value fil1 = CC_->data[sh1];
557  Filtration_value fil2 = CC_->data[sh2];
558  if (fil1 != fil2) {
559  return fil1 < fil2;
560  }
561  // in this case they are on the same filtration level, so the dimension decide.
562  std::size_t dim1 = CC_->get_dimension_of_a_cell(sh1);
563  std::size_t dim2 = CC_->get_dimension_of_a_cell(sh2);
564  if (dim1 != dim2) {
565  return dim1 < dim2;
566  }
567  // in this case both filtration and dimensions of the considered cubes are the same. To have stable sort, we simply
568  // compare their positions in the bitmap:
569  return sh1 < sh2;
570  }
571 
572  protected:
574 };
575 
576 } // namespace cubical_complex
577 
578 namespace Cubical_complex = cubical_complex;
579 
580 } // namespace Gudhi
581 
582 #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:354
std::vector< Simplex_handle >::iterator Boundary_simplex_iterator
Definition: Bitmap_cubical_complex.h:245
Simplex_key key(Simplex_handle sh) const
Definition: Bitmap_cubical_complex.h:198
void initialize_simplex_associated_to_key()
Definition: Bitmap_cubical_complex.h:528
std::size_t dimension() const
Definition: Bitmap_cubical_complex.h:160
std::pair< Simplex_handle, Simplex_handle > endpoints(Simplex_handle sh)
Definition: Bitmap_cubical_complex.h:382
Definition: SimplicialComplexForAlpha.h:26
std::size_t num_simplices() const
Definition: Bitmap_cubical_complex.h:145
unsigned dimension(Simplex_handle sh) const
Definition: Bitmap_cubical_complex.h:165
Filtration_simplex_range filtration_simplex_range()
Definition: Bitmap_cubical_complex.h:360
Simplex_handle simplex(Simplex_key key)
Definition: Bitmap_cubical_complex.h:211
Filtration_simplex_range provides the ranges for Filtration_simplex_iterator.
Definition: Bitmap_cubical_complex.h:318
void assign_key(Simplex_handle sh, Simplex_key key)
Definition: Bitmap_cubical_complex.h:224
Cubical complex represented as a bitmap.
Definition: Bitmap_cubical_complex.h:60
Bitmap_cubical_complex(const std::vector< unsigned > &dimensions, const std::vector< Filtration_value > &top_dimensional_cells)
Definition: Bitmap_cubical_complex.h:100
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
Class needed for compatibility with Gudhi. Not useful for other purposes.
Definition: Bitmap_cubical_complex.h:480
static Simplex_key null_key()
Definition: Bitmap_cubical_complex.h:188
Bitmap_cubical_complex(const char *perseus_style_file)
Definition: Bitmap_cubical_complex.h:81
static Simplex_handle null_simplex()
Definition: Bitmap_cubical_complex.h:150
Skeleton_simplex_range skeleton_simplex_range(unsigned dimension)
Definition: Bitmap_cubical_complex.h:513
Filtration_value filtration(Simplex_handle sh)
Definition: Bitmap_cubical_complex.h:176
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